00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00024
00025 #include <iostream>
00026 #include <qvmath.h>
00027 #include <qvmath/qvrationalnumber.h>
00028
00029 double norm2(const QPointF &p)
00030 {
00031 return sqrt(p.x() * p.x() + p.y() * p.y());
00032 }
00033
00034 int qvFactorial(const int n)
00035 {
00036 int result = 1;
00037 for (int i = 2; i <= n; i++)
00038 result *= i;
00039
00040 return result;
00041 };
00042
00043 double qvFactorialDivisionDouble(const int numerator, const int denominator)
00044 {
00045 double result = 1;
00046 for (int i = denominator+1; i <= numerator; i++)
00047 result *= i;
00048
00049 return result;
00050 }
00051
00052 double qvCombination(const int setRange, const int subsetRange)
00053 {
00054 Q_ASSERT(setRange > subsetRange);
00055
00056 QVRationalNumber subSetFactorial, divisionFactorial;
00057
00058 for (int i = 2; i <= subsetRange; i++)
00059 subSetFactorial.mult(i);
00060
00061 for (int i = setRange - subsetRange + 1; i <= setRange; i++)
00062 divisionFactorial.mult(i);
00063
00064 return divisionFactorial/subSetFactorial;
00065 }
00066
00067 double qvAngle(const QPointF &point)
00068 {
00069 const double x = point.x(), y = point.y();
00070
00071 if (x>0)
00072 if (y>=0)
00073 return atan(y/x);
00074 else
00075 return atan(y/x) + 2*PI;
00076 else if (x == 0.0)
00077 if (y>0)
00078 return PI/2;
00079 else
00080 return 3*PI/2;
00081 else
00082 return atan(y/x)+PI;
00083 }
00084
00085 double qvAngle(const QPointF &point1, const QPointF &point2)
00086 {
00087 double dtheta = atan2(point2.y(), point2.x()) - atan2(point1.y(), point1.x());
00088
00089 while (dtheta >= 2*PI)
00090 dtheta -= 2*PI;
00091
00092 while (dtheta < -2*PI)
00093 dtheta += 2*PI;
00094
00095 Q_ASSERT(dtheta >= -2*PI);
00096 Q_ASSERT(dtheta <= 2*PI);
00097
00098 return dtheta;
00099 }
00100
00101 int qvRandom(const int minValue, const int maxValue)
00102 { return rand()%(maxValue-minValue+1) + minValue; }
00103
00104
00105 double qvClockWiseAngle(const QPointF &point1, const QPointF &point2)
00106 {
00107 return qvAngle(point1, point2);
00108 }
00109
00110
00111 #define RANDOM_PRECISSION 32767
00112 double random(const double min, const double max)
00113 {
00114 return ABS(max-min) * double(rand()%RANDOM_PRECISSION)/double(RANDOM_PRECISSION-1) + MIN(min, max);
00115 }
00116
00117 double relativeEuclideanDistance(const double &v1, const double &v2)
00118 {
00119 if ( (v1 == 0) or (v2 == 0) )
00120 return 0.5;
00121
00122 return 0.5 * ABS(v1-v2) / (ABS(v1) + ABS(v2));
00123 }
00124
00125 double relativeEuclideanDistance(const QVVector &v1, const QVVector &v2)
00126 {
00127 if ( (v1.sum() == 0) or (v2.sum() == 0) )
00128 return 0.5;
00129
00130 return 0.5 * (v1-v2).norm2() / (v1.norm2() + v2.norm2());
00131 }
00132
00133
00134 QVector<QVComplex> qvSolveCubicPolynomial(const double coeff0, const double coeff1, const double coeff2, const double coeff3)
00135 {
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151 const double
00152 t1 = 0.1e1 / coeff3,
00153 t2 = ( coeff1 * coeff2),
00154 t5 = ( coeff3 * coeff3),
00155 t8 = (coeff2 * coeff2),
00156 t9 = ( t8 * coeff2),
00157 t11 = sqrt(0.3e1),
00158 t12 = ( coeff1 * coeff1),
00159 t20 = ( coeff0 * coeff0),
00160 t25 = 4 * t12 * coeff1 * coeff3 - t12 * t8 - 18 * t2 * coeff3 * coeff0 + 27 * t20 * t5 + 4 * coeff0 * t9,
00161 t26 = abs(t25),
00162 t27 = sqrt( t26),
00163 t28 = t11 * t27,
00164 t29 = ( t25>0 ? 1 : ( t25<0 ? -1 : 0)),
00165 t34 = (36 * t2 * coeff3) - (108 * coeff0 * t5) - (8 * t9) + 0.6e1 * t28 * (1 + t29) * coeff3,
00166 t35 = t34 * t34,
00167 t36 = 1 - t29,
00168 t37 = t36 * t36,
00169 t42 = pow(t35 + (108 * t26 * t37 * t5), 0.1e1 / 0.6e1),
00170 t43 = t1 * t42,
00171 t47 = atan2(0.6e1 * t28 * t36 * coeff3, t34),
00172 t48 = t47 / 0.3e1,
00173 t49 = cos(t48),
00174 t50 = t43 * t49,
00175 t51 = t50 / 0.6e1,
00176 t52 = coeff1 * coeff3,
00177 t55 = -12 * t52 + 4 * t8,
00178 t56 = t55 * t1,
00179 t57 = 0.1e1 / t42,
00180 t58 = t57 * t49,
00181 t62 = coeff2 * t1 / 0.3e1,
00182 t64 = sin(t48),
00183 t65 = t43 * t64,
00184 t66 = t57 * t64,
00185 t69 = t50 / 0.12e2,
00186 t70 = - t55 * t1,
00187 t72 = t70 * t58 / 0.12e2,
00188 t77 = ( (2 * t52) - 0.2e1 / 0.3e1 * t8) * t1,
00189 t81 = t11 * (t65 / 0.6e1 - t77 * t66) / 0.2e1,
00190 t83 = t65 / 0.12e2,
00191 t85 = t70 * t66 / 0.12e2,
00192 t89 = t11 * (t51 + t77 * t58) / 0.2e1;
00193
00194 double cg[3][2];
00195 cg[0][0] = t51 + t56 * t58 / 0.6e1 - t62;
00196 cg[0][1] = t65 / 0.6e1 - t56 * t66 / 0.6e1;
00197 cg[1][0] = -t69 + t72 - t62 - t81;
00198 cg[1][1] = -t83 - t85 + t89;
00199 cg[2][0] = -t69 + t72 - t62 + t81;
00200 cg[2][1] = -t83 - t85 - t89;
00201
00202 QVector<QVComplex> result(3);
00203 result[0].real() = cg[0][0]; result[0].imaginary() = cg[0][1];
00204 result[1].real() = cg[1][0]; result[1].imaginary() = cg[1][1];
00205 result[2].real() = cg[2][0]; result[2].imaginary() = cg[2][1];
00206
00207 return result;
00208 }
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286 double qvPointLineDistance(const QVVector &l, const QPointF &p)
00287 {
00288 return ABS(l[0] * p.x() + l[1] * p.y() + l[2]) / sqrt(POW2(l[0]) + POW2(l[1]));
00289 }
00290
00291 double qvSymmetricFloor( const double value )
00292 {
00293 if (value < 0.0)
00294 return ceil( value );
00295 else
00296 return floor( value );
00297 }
00298
00299