erf.h Source File

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files
- Examples

- File List
- File Members

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