https://www.cdslab.org/paramonte/fortran/2
Current view: top level - main - pm_mathErf@routines.inc.F90 (source / functions) Hit Total Coverage
Test: ParaMonte 2.0.0 :: Serial Fortran - Code Coverage Report Lines: 54 57 94.7 %
Date: 2024-04-08 03:18:57 Functions: 0 0 -
Legend: Lines: hit not hit

          Line data    Source code
       1             : !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
       2             : !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
       3             : !!!!                                                                                                                            !!!!
       4             : !!!!    ParaMonte: Parallel Monte Carlo and Machine Learning Library.                                                           !!!!
       5             : !!!!                                                                                                                            !!!!
       6             : !!!!    Copyright (C) 2012-present, The Computational Data Science Lab                                                          !!!!
       7             : !!!!                                                                                                                            !!!!
       8             : !!!!    This file is part of the ParaMonte library.                                                                             !!!!
       9             : !!!!                                                                                                                            !!!!
      10             : !!!!    LICENSE                                                                                                                 !!!!
      11             : !!!!                                                                                                                            !!!!
      12             : !!!!       https://github.com/cdslaborg/paramonte/blob/main/LICENSE.md                                                          !!!!
      13             : !!!!                                                                                                                            !!!!
      14             : !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
      15             : !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
      16             : 
      17             : !>  \brief
      18             : !>  This include file contains the implementation of procedures in [pm_mathErf](@ref pm_mathErf).
      19             : !>
      20             : !>  \finmain
      21             : !>
      22             : !>  \author
      23             : !>  \AmirShahmoradi, Oct 16, 2009, 11:14 AM, Michigan
      24             : 
      25             : !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      26             : 
      27             : #if     getErfInv_ENABLED
      28        8013 :         if (present(abserr)) then
      29           0 :             call setErfInv(erfinv, x, abserr)
      30             :         else
      31        8013 :             call setErfInv(erfinv, x, 100 * epsilon(0._RKC))
      32             :         end if
      33             : #elif   setErfInv_ENABLED
      34             :         real(RKC) :: temp, absx
      35             :         real(RKC), parameter :: TWO_OVER_SQRTPI = 2._RKC / sqrt(acos(-1._RKC))
      36             :         ! Chebyshev declarations.
      37             :         integer(IK) , parameter :: MINDEL = 0, NDELTA = 37, NLAMDA = 26, NMU = 25, NXI = 38
      38             :         integer(IK) , parameter :: MAXDEL = MINDEL + NDELTA ! 37
      39             :         integer(IK) , parameter :: MINLAM = MAXDEL + 1 ! 38
      40             :         integer(IK) , parameter :: MAXLAM = MINLAM + NLAMDA ! 64
      41             :         integer(IK) , parameter :: MINMU = MAXLAM + 1 ! 65
      42             :         integer(IK) , parameter :: MAXMU = MINMU + NMU ! 90
      43             :         integer(IK) , parameter :: MINXI = MAXMU + 1 ! 91
      44             :         integer(IK) , parameter :: MAXXI = MINXI + NXI ! 129
      45             :         ! The vector `chebyshScaler` is used to scale the argument of the Chebyshev polynomial expansion in the range 1.D-300 < 1 - X < 0.2.
      46             :         real(RKC), parameter :: chebyshScaler(6) =  [ -1.548813042373261659512742_RKC &
      47             :                                                     , +2.565490123147816151928163_RKC &
      48             :                                                     , -.5594576313298323225436913_RKC &
      49             :                                                     , +2.287915716263357638965891_RKC &
      50             :                                                     , -9.199992358830151031278420_RKC &
      51             :                                                     , +2.794990820124599493768426_RKC ]
      52             :         ! The coefficients of polynomial expansions, stored in the order DELTA(0..37), LAMDA(0..26), MU(0..25), XI(0..38), where
      53             :         !   DELTA are coefficients of the Chebyshev polynomial expansion of erfinv(X) for 0.9975 < X <= 1-5.0D-16.
      54             :         !   LAMDA are coefficients of the Chebyshev polynomial expansion of erfinv(X) for 0.8 < X <= 0.9975.
      55             :         !   MU    are coefficients of the Chebyshev polynomial expansion of erfinv(X) for 1 - 5.0D-16 < X <= 1 - 1.D-300.
      56             :         !   XI    are coefficients of the Chebyshev polynomial expansion of erfinv(X) in the range 0.0 <= X <= 0.8.
      57             :         real(RKC), parameter :: coef(0:MAXXI) = [ +0.9566797090204925274526373_RKC &
      58             :                                                 , -0.0231070043090649036999908_RKC &
      59             :                                                 , -0.0043742360975084077333218_RKC &
      60             :                                                 , -0.0005765034226511854809364_RKC &
      61             :                                                 , -0.0000109610223070923931242_RKC &
      62             :                                                 , +0.0000251085470246442787982_RKC &
      63             :                                                 , +0.0000105623360679477511955_RKC &
      64             :                                                 , +0.0000027544123300306391503_RKC &
      65             :                                                 , +0.0000004324844983283380689_RKC &
      66             :                                                 , -0.0000000205303366552086916_RKC &
      67             :                                                 , -0.0000000438915366654316784_RKC &
      68             :                                                 , -0.0000000176840095080881795_RKC &
      69             :                                                 , -0.0000000039912890280463420_RKC &
      70             :                                                 , -0.0000000001869324124559212_RKC &
      71             :                                                 , +0.0000000002729227396746077_RKC &
      72             :                                                 , +0.0000000001328172131565497_RKC &
      73             :                                                 , +0.0000000000318342484482286_RKC &
      74             :                                                 , +0.0000000000016700607751926_RKC &
      75             :                                                 , -0.0000000000020364649611537_RKC &
      76             :                                                 , -0.0000000000009648468127965_RKC &
      77             :                                                 , -0.0000000000002195672778128_RKC &
      78             :                                                 , -0.0000000000000095689813014_RKC &
      79             :                                                 , +0.0000000000000137032572230_RKC &
      80             :                                                 , +0.0000000000000062538505417_RKC &
      81             :                                                 , +0.0000000000000014584615266_RKC &
      82             :                                                 , +0.0000000000000001078123993_RKC &
      83             :                                                 , -0.0000000000000000709229988_RKC &
      84             :                                                 , -0.0000000000000000391411775_RKC &
      85             :                                                 , -0.0000000000000000111659209_RKC &
      86             :                                                 , -0.0000000000000000015770366_RKC &
      87             :                                                 , +0.0000000000000000002853149_RKC &
      88             :                                                 , +0.0000000000000000002716662_RKC &
      89             :                                                 , +0.0000000000000000000957770_RKC &
      90             :                                                 , +0.0000000000000000000176835_RKC &
      91             :                                                 , -0.0000000000000000000009828_RKC &
      92             :                                                 , -0.0000000000000000000020464_RKC &
      93             :                                                 , -0.0000000000000000000008020_RKC &
      94             :                                                 , -0.0000000000000000000001650_RKC &
      95             :                                                 , +0.9121588034175537733059200_RKC &
      96             :                                                 , -0.0162662818676636958546661_RKC &
      97             :                                                 , +0.0004335564729494453650589_RKC &
      98             :                                                 , +0.0002144385700744592065205_RKC &
      99             :                                                 , +0.0000026257510757648130176_RKC &
     100             :                                                 , -0.0000030210910501037969912_RKC &
     101             :                                                 , -0.0000000124060618367572157_RKC &
     102             :                                                 , +0.0000000624066092999917380_RKC &
     103             :                                                 , -0.0000000005401247900957858_RKC &
     104             :                                                 , -0.0000000014232078975315910_RKC &
     105             :                                                 , +0.0000000000343840281955305_RKC &
     106             :                                                 , +0.0000000000335848703900138_RKC &
     107             :                                                 , -0.0000000000014584288516512_RKC &
     108             :                                                 , -0.0000000000008102174258833_RKC &
     109             :                                                 , +0.0000000000000525324085874_RKC &
     110             :                                                 , +0.0000000000000197115408612_RKC &
     111             :                                                 , -0.0000000000000017494333828_RKC &
     112             :                                                 , -0.0000000000000004800596619_RKC &
     113             :                                                 , +0.0000000000000000557302987_RKC &
     114             :                                                 , +0.0000000000000000116326054_RKC &
     115             :                                                 , -0.0000000000000000017262489_RKC &
     116             :                                                 , -0.0000000000000000002784973_RKC &
     117             :                                                 , +0.0000000000000000000524481_RKC &
     118             :                                                 , +0.0000000000000000000065270_RKC &
     119             :                                                 , -0.0000000000000000000015707_RKC &
     120             :                                                 , -0.0000000000000000000001475_RKC &
     121             :                                                 , +0.0000000000000000000000450_RKC &
     122             :                                                 , +0.9885750640661893136460358_RKC &
     123             :                                                 , +0.0108577051845994776160281_RKC &
     124             :                                                 , -0.0017511651027627952494825_RKC &
     125             :                                                 , +0.0000211969932065633437984_RKC &
     126             :                                                 , +0.0000156648714042435087911_RKC &
     127             :                                                 , -0.0000005190416869103124261_RKC &
     128             :                                                 , -0.0000000371357897426717780_RKC &
     129             :                                                 , +0.0000000012174308662357429_RKC &
     130             :                                                 , -0.0000000001768115526613442_RKC &
     131             :                                                 , -0.0000000000119372182556161_RKC &
     132             :                                                 , +0.0000000000003802505358299_RKC &
     133             :                                                 , -0.0000000000000660188322362_RKC &
     134             :                                                 , -0.0000000000000087917055170_RKC &
     135             :                                                 , -0.0000000000000003506869329_RKC &
     136             :                                                 , -0.0000000000000000697221497_RKC &
     137             :                                                 , -0.0000000000000000109567941_RKC &
     138             :                                                 , -0.0000000000000000011536390_RKC &
     139             :                                                 , -0.0000000000000000001326235_RKC &
     140             :                                                 , -0.0000000000000000000263938_RKC &
     141             :                                                 , +0.0000000000000000000005341_RKC &
     142             :                                                 , -0.0000000000000000000022610_RKC &
     143             :                                                 , +0.0000000000000000000009552_RKC &
     144             :                                                 , -0.0000000000000000000005250_RKC &
     145             :                                                 , +0.0000000000000000000002487_RKC &
     146             :                                                 , -0.0000000000000000000001134_RKC &
     147             :                                                 , +0.0000000000000000000000420_RKC &
     148             :                                                 , +0.9928853766189408231495800_RKC &
     149             :                                                 , +0.1204675161431044864647846_RKC &
     150             :                                                 , +0.0160781993420999447257039_RKC &
     151             :                                                 , +0.0026867044371623158279591_RKC &
     152             :                                                 , +0.0004996347302357262947170_RKC &
     153             :                                                 , +0.0000988982185991204409911_RKC &
     154             :                                                 , +0.0000203918127639944337340_RKC &
     155             :                                                 , +0.0000043272716177354218758_RKC &
     156             :                                                 , +0.0000009380814128593406758_RKC &
     157             :                                                 , +0.0000002067347208683427411_RKC &
     158             :                                                 , +0.0000000461596991054300078_RKC &
     159             :                                                 , +0.0000000104166797027146217_RKC &
     160             :                                                 , +0.0000000023715009995921222_RKC &
     161             :                                                 , +0.0000000005439284068471390_RKC &
     162             :                                                 , +0.0000000001255489864097987_RKC &
     163             :                                                 , +0.0000000000291381803663201_RKC &
     164             :                                                 , +0.0000000000067949421808797_RKC &
     165             :                                                 , +0.0000000000015912343331469_RKC &
     166             :                                                 , +0.0000000000003740250585245_RKC &
     167             :                                                 , +0.0000000000000882087762421_RKC &
     168             :                                                 , +0.0000000000000208650897725_RKC &
     169             :                                                 , +0.0000000000000049488041039_RKC &
     170             :                                                 , +0.0000000000000011766394740_RKC &
     171             :                                                 , +0.0000000000000002803855725_RKC &
     172             :                                                 , +0.0000000000000000669506638_RKC &
     173             :                                                 , +0.0000000000000000160165495_RKC &
     174             :                                                 , +0.0000000000000000038382583_RKC &
     175             :                                                 , +0.0000000000000000009212851_RKC &
     176             :                                                 , +0.0000000000000000002214615_RKC &
     177             :                                                 , +0.0000000000000000000533091_RKC &
     178             :                                                 , +0.0000000000000000000128488_RKC &
     179             :                                                 , +0.0000000000000000000031006_RKC &
     180             :                                                 , +0.0000000000000000000007491_RKC &
     181             :                                                 , +0.0000000000000000000001812_RKC &
     182             :                                                 , +0.0000000000000000000000439_RKC &
     183             :                                                 , +0.0000000000000000000000106_RKC &
     184             :                                                 , +0.0000000000000000000000026_RKC &
     185             :                                                 , +0.0000000000000000000000006_RKC &
     186             :                                                 , +0.0000000000000000000000002_RKC &
     187             :                                                 ]
     188             :         real(RKC), parameter :: HALF_EPS = 0.5_RKC * epsilon(0._RKC)
     189             :         real(RKC) :: carg, cargTwice, w1, w2, w3
     190             :         ! COEF_LIM_FULL is an array containing MINXI, MAXXI, MINLAM, MAXLAM, MINDEL, MAXDEL, MINMU, MAXMU in locations -1..6 where,
     191             :         !       MAX...  is the position in `coef` of the last coefficient of a Chebyshev polynomial expansion.
     192             :         !       MIN...  is the position in `coef` of the first coefficient of a Chebyshev polynomial expansion.
     193             :         integer(IK) , parameter :: COEF_LIM_FULL(-1:6) = [MINXI, MAXXI, MINLAM, MAXLAM, MINDEL, MAXDEL, MINMU, MAXMU]
     194             :         ! Decide which approximation to use, and calculate the argument of the Chebyshev polynomial expansion.
     195             :         ! Compute the minimum index of a coefficient in the Chebyshev polynomial expansion to be used.
     196             :         ! That is, include only the coefficients whose precision is relevant to the requested output precision.
     197             :         ! \bug ifort 2021.8 : Cannot digest implied do loop below. Gfortran is fine.
     198             :         ! \remedy For now, the loop was unrolled.
     199             :        !integer(IK) , parameter :: COEF_LIM(-1:6) = [(COEF_LIM_FULL(i - 1), COEF_LIM_FULL(i) - count(abs(coef(COEF_LIM_FULL(i - 1) : COEF_LIM_FULL(i))) < HALF_EPS), i = 0, 6, 2)]
     200             :         integer(IK) , parameter :: COEF_LIM(-1:6) = [ COEF_LIM_FULL(-1), COEF_LIM_FULL(0) - count(abs(coef(COEF_LIM_FULL(-1) : COEF_LIM_FULL(0))) < HALF_EPS) &
     201             :                                                     , COEF_LIM_FULL(+1), COEF_LIM_FULL(2) - count(abs(coef(COEF_LIM_FULL(+1) : COEF_LIM_FULL(2))) < HALF_EPS) &
     202             :                                                     , COEF_LIM_FULL(+3), COEF_LIM_FULL(4) - count(abs(coef(COEF_LIM_FULL(+3) : COEF_LIM_FULL(4))) < HALF_EPS) &
     203             :                                                     , COEF_LIM_FULL(+5), COEF_LIM_FULL(6) - count(abs(coef(COEF_LIM_FULL(+5) : COEF_LIM_FULL(6))) < HALF_EPS) &
     204             :                                                     ]
     205             :         integer(IK) :: i, j, imin
     206       24056 :         if(-1._RKC < x .and. x < 1._RKC) then
     207       24056 :             if(1.e-7_RKC < abserr) then
     208       12042 :                 temp = -log((1.0 - x)*(1.0 + x));
     209       12042 :                 if (temp < 5._RKC) then
     210       11992 :                     temp = temp - 2.5_RKC
     211             :                     erfinv = +2.81022636e-08_RKC
     212       11992 :                     erfinv = +3.43273939e-07_RKC + erfinv * temp
     213       11992 :                     erfinv = -3.5233877e-06_RKC + erfinv * temp
     214       11992 :                     erfinv = -4.39150654e-06_RKC + erfinv * temp
     215       11992 :                     erfinv = +0.00021858087_RKC + erfinv * temp
     216       11992 :                     erfinv = -0.00125372503_RKC + erfinv * temp
     217       11992 :                     erfinv = -0.00417768164_RKC + erfinv * temp
     218       11992 :                     erfinv = +0.246640727_RKC + erfinv * temp
     219       11992 :                     erfinv = +1.50140941_RKC + erfinv * temp
     220             :                 else
     221          50 :                     temp = sqrt(temp) - 3._RKC
     222             :                     erfinv = -0.000200214257_RKC
     223          50 :                     erfinv = +0.000100950558_RKC + erfinv * temp
     224          50 :                     erfinv = +0.00134934322_RKC + erfinv * temp
     225          50 :                     erfinv = -0.00367342844_RKC + erfinv * temp
     226          50 :                     erfinv = +0.00573950773_RKC + erfinv * temp
     227          50 :                     erfinv = -0.0076224613_RKC + erfinv * temp
     228          50 :                     erfinv = +0.00943887047_RKC + erfinv * temp
     229          50 :                     erfinv = +1.00167406_RKC + erfinv * temp
     230          50 :                     erfinv = +2.83297682_RKC + erfinv * temp
     231             :                 end if
     232       12042 :                 erfinv = erfinv * x
     233       12014 :             elseif (2.e-24_RKC < abserr) then
     234             :                 !       This algorithm is based on the approximate formulae of Mathematics of Computation 22, (1968) PP144-158, which he claims to be accurate up to 23 decimal points.
     235             :                 !       Amir Shahmoradi, Nov 10, 2009, 8:53 PM, Michigan
     236             :                 !       Amir Shahmoradi, Wednesday 5:30 AM, XXX XX, 2012, Institute for Fusion Studies, The University of Texas Austin
     237             :                 !       HAPPY BIRTHDAY AMIR! (Self-congrats syndrome caused by lack of sleep)
     238        6001 :                 if (x == 0._RKC) then
     239           1 :                     erfinv = 0._RKC
     240           1 :                     return
     241             :                 end if
     242        6000 :                 absx = abs(x) ! The argument of the Chebyshev polynomial expansion.
     243        6000 :                 if (absx <= 0.8_RKC) then
     244        4800 :                     carg = 3.125_RKC * absx * absx - 1._RKC
     245             :                     j = -1
     246             :                 else
     247        1200 :                     if (absx <= 0.9975_RKC) then
     248             :                         j = 1
     249             :                     else
     250             :                         j = 3
     251             :                     end if
     252        1200 :                     absx = sqrt(-log((1._RKC - absx) * (1._RKC + absx)))
     253        1200 :                     carg = chebyshScaler(j) * absx + chebyshScaler(j + 1)
     254             :                 end if
     255             :                 ! Evaluate the Chebyshev polynomial expansion.
     256        6000 :                 cargTwice = carg + carg
     257             :                 ! W1..W3 are the adjacent elements of the recurrence used to evaluate the Chebyshev polynomial expansion.
     258        2000 :                 w1 = 0._RKC
     259        2000 :                 w2 = 0._RKC
     260        6000 :                 imin = COEF_LIM(j)
     261        6000 :                 i = COEF_LIM(j + 1)
     262             :                 do
     263       71266 :                     w3 = w2
     264       71266 :                     w2 = w1
     265      158550 :                     w1 = (cargTwice * w2 - w3) + coef(i)
     266      158550 :                     i = i - 1
     267      158550 :                     if (imin < i) cycle
     268      152550 :                     exit
     269             :                 end do
     270        6000 :                 erfinv = sign(absx * ((carg * w1 - w2) + coef(imin)), x)
     271             :             else
     272             :                 ! Use Halley approximation. 
     273             :                 ! Verified accuracy up to at least 2 * 10**-26.
     274        6013 :                 absx = 1._RKC - abs(x)
     275        6013 :                 temp = sqrt(-2._RKC * log(0.5_RKC * absx))
     276        6013 :                 erfinv = -0.70711_RKC * ((2.30753_RKC + temp * 0.27061_RKC) / (1._RKC + temp * (0.99229_RKC + temp * 0.04481_RKC)) - temp)
     277       18039 :                 do i = 1, 2
     278       12026 :                     temp = erfc(erfinv) - absx
     279       18039 :                     erfinv = erfinv + temp / (TWO_OVER_SQRTPI * exp(-erfinv**2) - erfinv * temp)
     280             :                 end do
     281        6013 :                 if (x < 0._RKC) erfinv = -erfinv
     282             :             end if
     283             :         else
     284           0 :             CHECK_ASSERTION(__LINE__, -1._RKC < x .and. x < 1._RKC, SK_"@setErfInv(): The condition `-1. < x .and. x < 1.` must hold. x = "//getStr(x)) ! fpp
     285           0 :             erfinv = sign(huge(x), x)
     286             :         end if
     287             : #else
     288             : #error  "Unrecognized interface."
     289             : #endif
     290             : #undef  strecok_ENABLED
     291             : #undef  halley_ENABLED

ParaMonte: Parallel Monte Carlo and Machine Learning Library 
The Computational Data Science Lab
© Copyright 2012 - 2024