as66.c 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. /*-Algorithm AS 66
  2. * The Normal Integral, by I. D. Hill, 1973.
  3. * Applied Statistics 22(3):424-427.
  4. *
  5. * Translation to C by James Darrell McCauley, mccauley@ecn.purdue.edu.
  6. *
  7. * Calculates the upper or lower tail area of the standardized normal
  8. * curve corresponding to any given argument.
  9. *
  10. * x - the argument value
  11. * upper: 1 -> the area from x to \infty
  12. * 0 -> the area from -\infty to x
  13. *
  14. * Notes:
  15. * The constant LTONE should be set to the value at which the
  16. * lower tail area becomes 1.0 to the accuracy of the machine.
  17. * LTONE=(n+9)/3 gives the required value accurately enough, for a
  18. * machine that produces n decimal digits in its real numbers.
  19. *
  20. * The constant UTZERO should be set to the value at which the upper
  21. * tail area becomes 0.0 to the accuracy of the machine. This may be
  22. * taken as the value such that exp(-0.5 * UTZERO * UTZERO) /
  23. * (UTZERO * sqrt(2*M_PI)) is just greater than the smallest allowable
  24. * real numbers.
  25. */
  26. #include <math.h>
  27. #define LTONE 7.0
  28. #define UTZERO 18.66
  29. double Cdhc_alnorm(double x, int upper)
  30. {
  31. double ret, z, y;
  32. int up;
  33. up = upper;
  34. z = x;
  35. if (x < 0.0) {
  36. up = up == 0 ? 1 : 0;
  37. z = -x;
  38. }
  39. if (!(z <= LTONE || (up == 1 && z <= UTZERO)))
  40. ret = 0.0;
  41. else {
  42. y = 0.5 * z * z;
  43. if (z <= 1.28)
  44. ret = 0.5 - z * (0.398942280444 - 0.399903438504 * y /
  45. (y + 5.75885480458 - 29.8213557808 /
  46. (y + 2.62433121679 + 48.6959930692 /
  47. (y + 5.92885724438))));
  48. else
  49. ret = 0.398942280385 * exp(-y) /
  50. (z - 3.8052e-8 + 1.00000615302 /
  51. (z + 3.98064794e-4 + 1.98615381364 /
  52. (z - 0.151679116635 + 5.29330324926 /
  53. (z + 4.8385912808 - 15.1508972451 /
  54. (z + 0.742380924027 + 30.789933034 /
  55. (z + 3.99019417011))))));
  56. }
  57. if (up == 0)
  58. ret = 1.0 - ret;
  59. return ret;
  60. }