m7_cumnor.F90 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. #include "tm5.inc"
  2. SUBROUTINE m7_cumnor ( arg, RESULT, ccum )
  3. !
  4. !*******************************************************************************
  5. !
  6. !! CUMNOR computes the cumulative normal distribution.
  7. !
  8. !
  9. ! the integral from -infinity to x of
  10. ! (1/sqrt(2*pi)) exp(-u*u/2) du
  11. !
  12. ! Author:
  13. ! -------
  14. ! Original source:
  15. !
  16. ! W. J. Cody Mathematics and Computer Science Division
  17. ! Argonne National Laboratory
  18. ! Argonne, IL 60439
  19. !
  20. ! DCDFLIB is attributed to Barry Brown, James Lovato, and Kathy Russell
  21. ! bwb@odin.mda.uth.tmc.edu.
  22. !
  23. ! Adopted to ECHAM/M7:
  24. !
  25. ! Philip Stier (MPI-MET) 2001
  26. !
  27. !
  28. ! Reference:
  29. ! ----------
  30. !
  31. ! W D Cody,
  32. ! "ALGORITHM 715: SPECFUN - A Portable FORTRAN Package of Special
  33. ! Function Routines and Test Drivers"
  34. ! ACM Transactions on Mathematical Software,
  35. ! Volume 19, 1993, pages 22-32.
  36. !
  37. ! Parameters:
  38. !
  39. ! ARG --> Upper limit of integration.
  40. ! X is double precision
  41. !
  42. ! RESULT <-- Cumulative normal distribution.
  43. ! RESULT is double precision
  44. !
  45. ! CCUM <-- Complement of Cumulative normal distribution.
  46. ! CCUM is double precision
  47. !
  48. !
  49. ! Original Comments:
  50. !
  51. !
  52. ! This function evaluates the normal distribution function:
  53. !
  54. ! / x
  55. ! 1 | -t*t/2
  56. ! P(x) = ----------- | e dt
  57. ! sqrt(2 pi) |
  58. ! /-oo
  59. !
  60. ! The main computation evaluates near-minimax approximations
  61. ! derived from those in "Rational Chebyshev approximations for
  62. ! the error function" by W. J. Cody, Math. Comp., 1969, 631-637.
  63. ! This transportable program uses rational functions that
  64. ! theoretically approximate the normal distribution function to
  65. ! at least 18 significant decimal digits. The accuracy achieved
  66. ! depends on the arithmetic system, the compiler, the intrinsic
  67. ! functions, and proper selection of the machine-dependent
  68. ! constants.
  69. !
  70. ! Explanation of machine-dependent constants.
  71. !
  72. ! MIN = smallest machine representable number.
  73. !
  74. ! EPS = argument below which anorm(x) may be represented by
  75. ! 0.5 and above which x*x will not underflow.
  76. ! A conservative value is the largest machine number X
  77. ! such that 1.0 + X = 1.0 to machine precision.
  78. !
  79. ! Error returns
  80. !
  81. ! The program returns ANORM = 0 for ARG .LE. XLOW.
  82. !
  83. ! Author:
  84. !
  85. ! W. J. Cody
  86. ! Mathematics and Computer Science Division
  87. ! Argonne National Laboratory
  88. ! Argonne, IL 60439
  89. !
  90. ! Latest modification: March 15, 1992
  91. !
  92. DOUBLE PRECISION, PARAMETER, DIMENSION ( 5 ) :: a = (/ &
  93. 2.2352520354606839287d00, &
  94. 1.6102823106855587881d02, &
  95. 1.0676894854603709582d03, &
  96. 1.8154981253343561249d04, &
  97. 6.5682337918207449113d-2 /)
  98. DOUBLE PRECISION arg
  99. DOUBLE PRECISION, PARAMETER, DIMENSION ( 4 ) :: b = (/ &
  100. 4.7202581904688241870d01, &
  101. 9.7609855173777669322d02, &
  102. 1.0260932208618978205d04, &
  103. 4.5507789335026729956d04 /)
  104. DOUBLE PRECISION, PARAMETER, DIMENSION ( 9 ) :: c = (/ &
  105. 3.9894151208813466764d-1, &
  106. 8.8831497943883759412d00, &
  107. 9.3506656132177855979d01, &
  108. 5.9727027639480026226d02, &
  109. 2.4945375852903726711d03, &
  110. 6.8481904505362823326d03, &
  111. 1.1602651437647350124d04, &
  112. 9.8427148383839780218d03, &
  113. 1.0765576773720192317d-8 /)
  114. DOUBLE PRECISION ccum
  115. DOUBLE PRECISION, PARAMETER, DIMENSION ( 8 ) :: d = (/ &
  116. 2.2266688044328115691d01, &
  117. 2.3538790178262499861d02, &
  118. 1.5193775994075548050d03, &
  119. 6.4855582982667607550d03, &
  120. 1.8615571640885098091d04, &
  121. 3.4900952721145977266d04, &
  122. 3.8912003286093271411d04, &
  123. 1.9685429676859990727d04 /)
  124. DOUBLE PRECISION del
  125. !@@@ DOUBLE PRECISION dpmpar
  126. DOUBLE PRECISION eps
  127. INTEGER i
  128. DOUBLE PRECISION min
  129. DOUBLE PRECISION, PARAMETER, DIMENSION ( 6 ) :: p = (/ &
  130. 2.1589853405795699d-1, &
  131. 1.274011611602473639d-1, &
  132. 2.2235277870649807d-2, &
  133. 1.421619193227893466d-3, &
  134. 2.9112874951168792d-5, &
  135. 2.307344176494017303d-2 /)
  136. DOUBLE PRECISION, PARAMETER, DIMENSION ( 5 ) :: q = (/ &
  137. 1.28426009614491121d00, &
  138. 4.68238212480865118d-1, &
  139. 6.59881378689285515d-2, &
  140. 3.78239633202758244d-3, &
  141. 7.29751555083966205d-5 /)
  142. DOUBLE PRECISION RESULT
  143. DOUBLE PRECISION, PARAMETER :: root32 = 5.656854248d0
  144. DOUBLE PRECISION, PARAMETER :: sixten = 16.0
  145. DOUBLE PRECISION temp
  146. DOUBLE PRECISION, PARAMETER :: sqrpi = 3.9894228040143267794d-1
  147. DOUBLE PRECISION, PARAMETER :: thrsh = 0.66291d0
  148. DOUBLE PRECISION x
  149. DOUBLE PRECISION xden
  150. DOUBLE PRECISION xnum
  151. DOUBLE PRECISION y
  152. DOUBLE PRECISION xsq
  153. !
  154. ! Machine dependent constants
  155. !
  156. eps = EPSILON ( 1.0d0 ) * 0.5d0
  157. !
  158. !@@@ Simplified calculation of the smallest machine representable number
  159. ! (Higher accuracy than needed!)
  160. !
  161. !@@@ min = dpmpar(2)
  162. min = epsilon ( 1.0D0)
  163. x = arg
  164. y = ABS ( x )
  165. IF ( y <= thrsh ) THEN
  166. !
  167. ! Evaluate anorm for |X| <= 0.66291
  168. !
  169. IF ( y > eps ) THEN
  170. xsq = x * x
  171. ELSE
  172. xsq = 0.0
  173. END IF
  174. xnum = a(5) * xsq
  175. xden = xsq
  176. DO i = 1, 3
  177. xnum = ( xnum + a(i) ) * xsq
  178. xden = ( xden + b(i) ) * xsq
  179. END DO
  180. RESULT = x * ( xnum + a(4) ) / ( xden + b(4) )
  181. temp = RESULT
  182. RESULT = 0.5 + temp
  183. ccum = 0.5 - temp
  184. !
  185. ! Evaluate ANORM for 0.66291 <= |X| <= sqrt(32)
  186. !
  187. ELSE IF ( y <= root32 ) THEN
  188. xnum = c(9) * y
  189. xden = y
  190. !CDIR UNROLL=7
  191. DO i = 1, 7
  192. xnum = ( xnum + c(i) ) * y
  193. xden = ( xden + d(i) ) * y
  194. END DO
  195. RESULT = ( xnum + c(8) ) / ( xden + d(8) )
  196. xsq = AINT ( y * sixten ) / sixten
  197. del = ( y - xsq ) * ( y + xsq )
  198. RESULT = EXP(-xsq*xsq*0.5) * EXP(-del*0.5) * RESULT
  199. ccum = 1.0 - RESULT
  200. IF ( x > 0.0 ) THEN
  201. temp = RESULT
  202. RESULT = ccum
  203. ccum = temp
  204. END IF
  205. !
  206. ! Evaluate anorm for |X| > sqrt(32).
  207. !
  208. ELSE
  209. RESULT = 0.0
  210. xsq = 1.0 / ( x * x )
  211. xnum = p(6) * xsq
  212. xden = xsq
  213. DO i = 1, 4
  214. xnum = ( xnum + p(i) ) * xsq
  215. xden = ( xden + q(i) ) * xsq
  216. END DO
  217. RESULT = xsq * ( xnum + p(5) ) / ( xden + q(5) )
  218. RESULT = ( sqrpi - RESULT ) / y
  219. xsq = AINT ( x * sixten ) / sixten
  220. del = ( x - xsq ) * ( x + xsq )
  221. RESULT = EXP ( - xsq * xsq * 0.5 ) * EXP ( - del * 0.5 ) * RESULT
  222. ccum = 1.0 - RESULT
  223. IF ( x > 0.0 ) THEN
  224. temp = RESULT
  225. RESULT = ccum
  226. ccum = temp
  227. END IF
  228. END IF
  229. IF ( RESULT < min ) THEN
  230. RESULT = 0.0d0
  231. END IF
  232. IF ( ccum < min ) THEN
  233. ccum = 0.0d0
  234. END IF
  235. END SUBROUTINE m7_cumnor