inverse_normal_cdf.h
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #ifndef INVERSE_NORMAL_CDF_H
00033 #define INVERSE_NORMAL_CDF_H
00034
00035 class InverseNormalCDF {
00036
00037 public:
00038
00039 #define A1 (-3.969683028665376e+01)
00040 #define A2 2.209460984245205e+02
00041 #define A3 (-2.759285104469687e+02)
00042 #define A4 1.383577518672690e+02
00043 #define A5 (-3.066479806614716e+01)
00044 #define A6 2.506628277459239e+00
00045
00046 #define B1 (-5.447609879822406e+01)
00047 #define B2 1.615858368580409e+02
00048 #define B3 (-1.556989798598866e+02)
00049 #define B4 6.680131188771972e+01
00050 #define B5 (-1.328068155288572e+01)
00051
00052 #define C1 (-7.784894002430293e-03)
00053 #define C2 (-3.223964580411365e-01)
00054 #define C3 (-2.400758277161838e+00)
00055 #define C4 (-2.549732539343734e+00)
00056 #define C5 4.374664141464968e+00
00057 #define C6 2.938163982698783e+00
00058
00059 #define D1 7.784695709041462e-03
00060 #define D2 3.224671290700398e-01
00061 #define D3 2.445134137142996e+00
00062 #define D4 3.754408661907416e+00
00063
00064 #define P_LOW 0.02425
00065
00066 #define P_HIGH 0.97575
00067
00068 static double Compute(double p) {
00069
00070 long double x = 0;
00071 long double q, r, u, e;
00072 if ((0 < p ) && (p < P_LOW)){
00073 q = sqrt(-2*log(p));
00074 x = (((((C1*q+C2)*q+C3)*q+C4)*q+C5)*q+C6) / ((((D1*q+D2)*q+D3)*q+D4)*q+1);
00075 }
00076 else{
00077 if ((P_LOW <= p) && (p <= P_HIGH)){
00078 q = p - 0.5;
00079 r = q*q;
00080 x = (((((A1*r+A2)*r+A3)*r+A4)*r+A5)*r+A6)*q /(((((B1*r+B2)*r+B3)*r+B4)*r+B5)*r+1);
00081 }
00082 else{
00083 if ((P_HIGH < p)&&(p < 1)){
00084 q = sqrt(-2*log(1-p));
00085 x = -(((((C1*q+C2)*q+C3)*q+C4)*q+C5)*q+C6) / ((((D1*q+D2)*q+D3)*q+D4)*q+1);
00086 }
00087 }
00088 }
00089
00090
00091
00092 if(( 0 < p)&&(p < 1)){
00093 e = 0.5 * erfc(-x/sqrt(2)) - p;
00094 u = e * sqrt(2*M_PI) * exp(x*x/2);
00095 x = x - u/(1 + x*u/2);
00096 }
00097 return x;
00098 }
00099 };
00100
00101 #endif