erf.h
Go to the documentation of this file.
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 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines