Open Babel  3.0
erf.h
Go to the documentation of this file.
1 //From http://www.digitalmars.com/archives/cplusplus/3634.html (Jan 2004)
2 //Author Steve Strand. No intellectual propery rights claimed.
3 #ifndef OB_ERF_H
4 #define OB_ERF_H
5 
6 #include <math.h>
7 
9 // Hide this from doxygen -- internal only code
10 namespace temperf
11 {
12 double erf(double x);
13 double erfc(double x);
14 
15 static const double rel_error= 1E-12; //calculate 12 significant figures
16 //you can adjust rel_error to trade off between accuracy and speed
17 //but don't ask for > 15 figures (assuming usual 52 bit mantissa in a double)
18 
19 inline double erf(double x)
20 {
21  //erf(x) = 2/sqrt(pi)*integral(exp(-t^2),t,0,x)
22  // = 2/sqrt(pi)*[x - x^3/3 + x^5/5*2! - x^7/7*3! + ...]
23  // = 1-erfc(x)
24  static const double two_sqrtpi= 1.128379167095512574; // 2/sqrt(pi)
25  if (abs(x) > 2.2)
26  return 1.0 - erfc(x); //use continued fraction when fabs(x) > 2.2
27 
28  double sum= x, term= x, xsqr= x*x;
29  int j= 1;
30  do
31  {
32  term*= xsqr/j;
33  sum-= term/(2*j+1);
34  ++j;
35  term*= xsqr/j;
36  sum+= term/(2*j+1);
37  ++j;
38  } while (fabs(term/sum) > rel_error);
39  return two_sqrtpi*sum;
40 }
41 
42 inline double erfc(double x)
43 {
44  //erfc(x) = 2/sqrt(pi)*integral(exp(-t^2),t,x,inf)
45  // = exp(-x^2)/sqrt(pi) * [1/x+ (1/2)/x+ (2/2)/x+ (3/2)/x+ (4/2)/x+ ...]
46  // = 1-erf(x)
47  //expression inside [] is a continued fraction so '+' means add to denominator only
48 
49  static const double one_sqrtpi= 0.564189583547756287; // 1/sqrt(pi)
50  if (abs(x) < 2.2)
51  return 1.0 - erf(x); //use series when fabs(x) < 2.2
52 
53  if (x<0)//continued fraction only valid for x>0
54  return 2.0 - erfc(-x);
55 
56  double a=1, b=x; //last two convergent numerators
57  double c=x, d=x*x+0.5; //last two convergent denominators
58  double q1, q2= b/d; //last two convergents (a/c and b/d)
59  double n= 1.0, t;
60  do
61  {
62  t= a*n+b*x;
63  a= b;
64  b= t;
65  t= c*n+d*x;
66  c= d;
67  d= t;
68  n+= 0.5;
69  q1= q2;
70  q2= b/d;
71  } while (fabs(q1-q2)/q2 > rel_error);
72  return one_sqrtpi*exp(-x*x)*q2;
73 }
75 
76 }//namespace
77 #endif // OB_ERF_H
78