00001 //From http://www.digitalmars.com/archives/cplusplus/3634.html (Jan 2004) 00002 //Author Steve Strand. No intellectual propery rights claimed. 00003 #ifndef OB_ERF_H 00004 #define OB_ERF_H 00005 00006 #include <math.h> 00007 00009 // Hide this from doxygen -- internal only code 00010 namespace temperf 00011 { 00012 double erf(double x); 00013 double erfc(double x); 00014 00015 static const double rel_error= 1E-12; //calculate 12 significant figures 00016 //you can adjust rel_error to trade off between accuracy and speed 00017 //but don't ask for > 15 figures (assuming usual 52 bit mantissa in a double) 00018 00019 inline double erf(double x) 00020 { 00021 //erf(x) = 2/sqrt(pi)*integral(exp(-t^2),t,0,x) 00022 // = 2/sqrt(pi)*[x - x^3/3 + x^5/5*2! - x^7/7*3! + ...] 00023 // = 1-erfc(x) 00024 static const double two_sqrtpi= 1.128379167095512574; // 2/sqrt(pi) 00025 if (abs(x) > 2.2) 00026 return 1.0 - erfc(x); //use continued fraction when fabs(x) > 2.2 00027 00028 double sum= x, term= x, xsqr= x*x; 00029 int j= 1; 00030 do 00031 { 00032 term*= xsqr/j; 00033 sum-= term/(2*j+1); 00034 ++j; 00035 term*= xsqr/j; 00036 sum+= term/(2*j+1); 00037 ++j; 00038 } while (fabs(term/sum) > rel_error); 00039 return two_sqrtpi*sum; 00040 } 00041 00042 inline double erfc(double x) 00043 { 00044 //erfc(x) = 2/sqrt(pi)*integral(exp(-t^2),t,x,inf) 00045 // = exp(-x^2)/sqrt(pi) * [1/x+ (1/2)/x+ (2/2)/x+ (3/2)/x+ (4/2)/x+ ...] 00046 // = 1-erf(x) 00047 //expression inside [] is a continued fraction so '+' means add to denominator only 00048 00049 static const double one_sqrtpi= 0.564189583547756287; // 1/sqrt(pi) 00050 if (abs(x) < 2.2) 00051 return 1.0 - erf(x); //use series when fabs(x) < 2.2 00052 00053 if (x<0)//continued fraction only valid for x>0 00054 return 2.0 - erfc(-x); 00055 00056 double a=1, b=x; //last two convergent numerators 00057 double c=x, d=x*x+0.5; //last two convergent denominators 00058 double q1, q2= b/d; //last two convergents (a/c and b/d) 00059 double n= 1.0, t; 00060 do 00061 { 00062 t= a*n+b*x; 00063 a= b; 00064 b= t; 00065 t= c*n+d*x; 00066 c= d; 00067 d= t; 00068 n+= 0.5; 00069 q1= q2; 00070 q2= b/d; 00071 } while (fabs(q1-q2)/q2 > rel_error); 00072 return one_sqrtpi*exp(-x*x)*q2; 00073 } 00075 00076 }//namespace 00077 #endif // OB_ERF_H 00078
This file is part of the documentation for Open Babel, version 2.3.