00001 /*---------------------------------------------------------------------+ 00002 | Library QgarLib, graphics analysis and recognition | 00003 | Copyright (C) 2002 Qgar Project, LORIA | 00004 | | 00005 | This library is free software; you can redistribute it and/or | 00006 | modify it under the terms of the GNU Lesser General Public | 00007 | License version 2.1, as published by the Free Software Foundation. | 00008 | | 00009 | This library is distributed in the hope that it will be useful, | 00010 | but WITHOUT ANY WARRANTY; without even the implied warranty of | 00011 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | 00012 | See the GNU Lesser General Public License for more details. | 00013 | | 00014 | The GNU Lesser General Public License is included in the file | 00015 | LICENSE.LGPL, in the root directory of the Qgar packaging. See | 00016 | http://www.gnu.org/licenses/lgpl.html for the terms of the licence. | 00017 | To receive a paper copy, write to the Free Software Foundation, | 00018 | Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. | 00019 | | 00020 | Contact Project Qgar for any information: | 00021 | LORIA - équipe Qgar | 00022 | B.P. 239, 54506 Vandoeuvre-lès-Nancy Cedex, France | 00023 | email: qgar-contact@loria.fr | 00024 | http://www.qgar.org/ | 00025 *---------------------------------------------------------------------*/ 00026 00027 00028 /** 00029 * @file math.C 00030 * @brief Implementation of utilities for mathematical operations. 00031 * 00032 * See file math.H for the interface. 00033 * 00034 * @author <a href="mailto:qgar-develop@loria.fr?subject=Qgar fwd Gérald Masini">Gérald Masini</a> 00035 * @date December 06, 2004 18:08 00036 * @since Qgar 2.2 00037 */ 00038 00039 00040 00041 // STL 00042 #include <limits> 00043 // QGAR 00044 #include <qgarlib/math.H> 00045 00046 00047 00048 namespace qgar 00049 { 00050 00051 00052 /*---------------------------------------------------------------------* 00053 | | 00054 | C L A S S M A T H | 00055 | | 00056 *---------------------------------------------------------------------*/ 00057 00058 00059 // --------------------------------------------------------------------- 00060 // CONSTANTS TO PRESERVE COMPATIBILITY WITH WINDOWS OS 00061 // ---------------------------------------------------------------------- 00062 00063 00064 // Maximum double number 00065 const double 00066 Math::QG_DOUBLE_MAX = 1.79769313486231570e+308; 00067 00068 // Minimum double number 00069 const double 00070 Math::QG_DOUBLE_MIN = 4.94065645841246544e-324; 00071 00072 // Maximum float number. 00073 const float 00074 Math::QG_FLOAT_MAX = 3.40282346638528860e+38; 00075 00076 // Minimum double number 00077 const float 00078 Math::QG_FLOAT_MIN = 1.40129846432481707e-45; 00079 00080 00081 // ---------------------------------------------------------------------- 00082 // CONSTANTS RELATED TO E 00083 // ---------------------------------------------------------------------- 00084 00085 // ALL VALUES COMPUTED BY MAPLE 00086 // ============================ 00087 00088 00089 // E = 2.718281828459045235360287471352662497757 00090 const double 00091 Math::QG_E = 2.7182818284590452354; 00092 00093 00094 // log_2(E) = 1.442695040888963407359924681001892137426 00095 const double 00096 Math::QG_LOG2E = 1.4426950408889634074; 00097 00098 // log_10(E) = 0.434294481903251827651128918916605082294 00099 const double 00100 Math::QG_LOG10E = 0.43429448190325182765; 00101 00102 // Log_E(2) = 0.693147180559945309417232121458176568075 00103 const double 00104 Math::QG_LN2 = 0.69314718055994530942; 00105 00106 // Log_E(10) = 2.302585092994045684017991454684364207601 00107 const double 00108 Math::QG_LN10 = 2.30258509299404568402; 00109 00110 00111 // ---------------------------------------------------------------------- 00112 // CONSTANTS RELATED TO PI 00113 // ---------------------------------------------------------------------- 00114 00115 // ALL VALUES COMPUTED BY MAPLE 00116 00117 00118 // PI = 3.141592653589793238462643383279502884197 00119 const double 00120 Math::QG_PI = 3.14159265358979323846; 00121 00122 // PI/2 = 1.570796326794896619231321691639751442098 00123 const double 00124 Math::QG_PI_2 = 1.57079632679489661923; 00125 00126 // PI/3 = 1.047197551196597746154214461093167628066 00127 const double 00128 Math::QG_PI_3 = 1.04719755119659774615; 00129 00130 // PI/4 = 0.7853981633974483096156608458198757210492 00131 const double 00132 Math::QG_PI_4 = 0.78539816339744830962; 00133 00134 // PI/6 = 0.5235987755982988730771072305465838140329 00135 const double 00136 Math::QG_PI_6 = 0.52359877559829887308; 00137 00138 // 2*PI = 6.283185307179586476925286766559005768394 00139 const double 00140 Math::QG_2PI = 6.28318530717958647692; 00141 00142 00143 // sqrt(2*PI) = 2.506628274631000502415765284811045253008 00144 const double 00145 Math::QG_SQRT_2PI = 2.50662827463100050242; 00146 00147 // sqrt(PI) = 1.772453850905516027298167483341145182798 00148 const double 00149 Math::QG_SQRT_PI = 1.77245385090551602730; 00150 00151 00152 // 1/(2*PI) = 0.1591549430918953357688837633725143620344 00153 const double 00154 Math::QG_1_2PI = 0.15915494309189533577; 00155 00156 // 1/PI = 0.3183098861837906715377675267450287240689 00157 const double 00158 Math::QG_1_PI = 0.31830988618379067154; 00159 00160 // 1/sqrt(PI) = 0.5641895835477562869480794515607725858441 00161 const double 00162 Math::QG_1_SQRT_PI = 0.56418958354775628695; 00163 00164 // 1/sqrt(2*PI) = 0.3989422804014326779399460599343818684758 00165 const double 00166 Math::QG_1_SQRT_2PI = 0.39894228040143267794; 00167 00168 00169 // 2/PI = 0.6366197723675813430755350534900574481378 00170 const double 00171 Math::QG_2_PI = 0.63661977236758134308; 00172 00173 // 2/sqrt(PI) = 1.1283791670955125738961589031215451716881 00174 const double 00175 Math::QG_2_SQRT_PI = 1.12837916709551257390; 00176 00177 00178 // ---------------------------------------------------------------------- 00179 // CONSTANTS RELATED TO SQRT(2) 00180 // ---------------------------------------------------------------------- 00181 00182 // ALL VALUES COMPUTED BY MAPLE 00183 00184 00185 // sqrt(2) = 1.414213562373095048801688724209698078570 00186 const double 00187 Math::QG_SQRT_2 = 1.41421356237309504880; 00188 00189 // 1/sqrt(2) = 0.7071067811865475244008443621048490392847 00190 const double 00191 Math::QG_1_SQRT_2 = 0.70710678118654752440; 00192 00193 00194 // ---------------------------------------------------------------------- 00195 // CONSTANTS RELATED TO SQRT(3) 00196 // ---------------------------------------------------------------------- 00197 00198 // ALL VALUES COMPUTED BY MAPLE 00199 00200 00201 // sqrt(3) = 1.732050807568877293527446341505872366943 00202 const double 00203 Math::QG_SQRT_3 = 1.73205080756887729353; 00204 00205 // 1/sqrt(3) = 0.5773502691896257645091487805019574556475 00206 const double 00207 Math::QG_1_SQRT_3 = 0.57735026918962576451; 00208 00209 00210 // ---------------------------------------------------------------------- 00211 // CONSTANTS FOR CONVERSIONS 00212 // ---------------------------------------------------------------------- 00213 00214 // ALL VALUES COMPUTED BY MAPLE 00215 00216 00217 // To convert radians to degrees: 180 / PI 00218 const double 00219 Math::QG_RADIANS_TO_DEGREES = 57.2957795130823208768; 00220 00221 // To convert degrees to radians: PI / 180 00222 const double 00223 Math::QG_DEGREES_TO_RADIANS = 0.01745329251994329577; 00224 00225 00226 // ---------------------------------------------------------------------- 00227 // LIMITS 00228 // ---------------------------------------------------------------------- 00229 00230 00231 // Square root of the maximum positive integer coded on 4 bytes 00232 const int 00233 Math::QG_SQRT_MAX_INT16b = 46340; 00234 00235 00236 // --------------------------------------------------------------------- 00237 // THRESHOLDS FOR (IN)EQUALITY TESTS 00238 // --------------------------------------------------------------------- 00239 00240 00241 // Threshold for double numbers 00242 double 00243 Math::_s_epsilon_double = 0.0001; 00244 00245 00246 // Threshold for float numbers 00247 float 00248 Math::_s_epsilon_float = 0.0001f; 00249 00250 00251 // Threshold for integer numbers 00252 int 00253 Math::_s_epsilon_int = 1; 00254 00255 // Threshold for angles in radians 00256 // 0.005 radian ~ 0.25 degree 00257 double 00258 Math::_s_epsilon_radian = 0.005; 00259 00260 // Threshold for angles in degrees 00261 // 0.25 degree ~ 0.005 radian 00262 double 00263 Math::_s_epsilon_degree = 0.25; 00264 00265 00266 // --------------------------------------------------------------------- 00267 // THRESHOLDS FOR NUMERIC CALCULUS 00268 // --------------------------------------------------------------------- 00269 00270 00271 // Relative error for floating point numeric calculus 00272 // The default value corresponds to 12 significant figures 00273 double 00274 Math::_s_rel_error_fp = 1.e-12; 00275 00276 00277 00278 00279 /*********************************************************************** 00280 * * 00281 * G L O B A L F U N C T I O N S * 00282 * * 00283 ***********************************************************************/ 00284 00285 00286 00287 // ********************************************************************* 00288 // ERROR FUNCTIONS 00289 // ********************************************************************* 00290 00291 00292 // Code inspired by various pieces of free code 00293 00294 00295 // COMPUTE THE ERROR FUNCTION OF THE ARGUMENT 00296 // 00297 // erf(x) = 1 - erfc(x) 00298 // = 2/sqrt(pi) * integral_0^x e^{-t^2} dt 00299 // 00300 // -1 <= erf(x) <= 1 00301 // 00302 // For |x| <= 2.2, the integral is calculated as: 00303 // 00304 // x - x^3/3 + x^5/(5*2!) - x^7/(7*3!) + ... 00305 // 00306 double 00307 qgErf(double x) 00308 { 00309 // Use erfc(x) when |x| > 2.2 00310 if (fabs(x) > 2.2) 00311 { 00312 return 1. - qgErfc(x); 00313 } 00314 00315 double sum = x; 00316 double term = x; 00317 double xsqr = x * x; 00318 00319 int iCnt = 1; 00320 00321 do 00322 { 00323 term *= xsqr / iCnt; 00324 sum -= term / ((2 * iCnt) + 1); 00325 ++iCnt; 00326 00327 term *= xsqr / iCnt; 00328 sum += term / ((2 * iCnt) + 1); 00329 ++iCnt; 00330 } 00331 while (fabs(term/sum) > Math::relError()); 00332 00333 return Math::QG_2_SQRT_PI * sum; 00334 } 00335 00336 00337 // COMPUTE THE COMPLEMENTARY ERROR FUNCTION OF THE ARGUMENT 00338 // 00339 // erfc(x) = 1 - erf(x) 00340 // = 2/sqrt(pi) * integral_x^infinity e^{-t^2} dt 00341 // 00342 // 0 <= erfc(x) <= 2 00343 // 00344 // For x >= 2.2, erfc(x) is calculated as: 00345 // 00346 // e^{-x^2}/sqrt(pi) 00347 // * 00348 // (1 / (x + (2/2 / (x + (3/2 / x + (4/2 / (x +...))))))) 00349 // 00350 double 00351 qgErfc(double x) 00352 { 00353 // Use erf(x) when |x| < 2.2 00354 if (fabs(x) < 2.2) 00355 { 00356 return 1. - qgErf(x); 00357 } 00358 00359 // The calculus hereafter is only valid for x >= 0 00360 // 00361 // It would be certainly better to use function signbit() 00362 // from <cmath>, but this function is not (yet) in the standard 00363 // if (signbit(x)) 00364 if (x < 0.) 00365 { 00366 return 2.0 - qgErfc(-x); 00367 } 00368 00369 // Numerator 00370 double n = 1.; 00371 // Last two convergent numerators 00372 double n1 = 1.; 00373 double n2 = x; 00374 // Last two convergent denominators 00375 double d1 = x; 00376 double d2 = (x * x) + 0.5; 00377 // Last two convergents quotients: n1/d1 and n2/d2 00378 double nd1; 00379 double nd2 = n2 / d2; 00380 00381 do 00382 { 00383 double tmp = (n1 * n) + (n2 * x); 00384 n1 = n2; 00385 n2 = tmp; 00386 00387 tmp = (d1 * n) + (d2 * x); 00388 d1 = d2; 00389 d2 = tmp; 00390 00391 nd1 = nd2; 00392 nd2 = n2 / d2; 00393 00394 n += 0.5; 00395 } 00396 while ((fabs(nd1 - nd2) / nd2) > Math::relError()); 00397 00398 return Math::QG_1_SQRT_PI * exp(-x * x) * nd2; 00399 } 00400 00401 00402 // ********************************************************************* 00403 00404 } // namespace qgar