LCOV - code coverage report
Current view: top level - src/common - erf_complex.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:2c0d679) Lines: 29.2 % 192 56
Test Date: 2026-09-25 00:58:37 Functions: 50.0 % 4 2

            Line data    Source code
       1              : !--------------------------------------------------------------------------------------------------!
       2              : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3              : !   Copyright 2000-2026 CP2K developers group <https://cp2k.org>                                   !
       4              : !                                                                                                  !
       5              : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6              : !--------------------------------------------------------------------------------------------------!
       7              : 
       8              : ! Copyright (c) 2016 Anton Shterenlikht, The University of Bristol, UK
       9              : !
      10              : ! Redistribution and use in source and binary forms, with or without
      11              : ! modification, are permitted provided that the following conditions are
      12              : ! met:
      13              : !
      14              : ! 1. Redistributions of source code must retain the above copyright
      15              : ! notice, this list of conditions and the following disclaimer.
      16              : !
      17              : ! 2. Redistributions in binary form must reproduce the above copyright
      18              : ! notice, this list of conditions and the following disclaimer in the
      19              : ! documentation and/or other materials provided with the distribution.
      20              : !
      21              : ! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
      22              : ! IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
      23              : ! TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
      24              : ! PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
      25              : ! HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
      26              : ! SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
      27              : ! TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
      28              : ! PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
      29              : ! LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
      30              : ! NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
      31              : ! SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      32              : !
      33              : ! Module with error function and related functions.
      34              : ! Two algorithms are implemented: Poppe and Wijers (faddeyeva_fast, erfz_fast)
      35              : ! and Zaghloul and Ali (faddeyeva_accurate, erfz_accurate). The second algorithm is
      36              : ! supposed to be more accurate for some values. However, the first
      37              : ! algorithm can be over an order of magnitude faster.
      38              : !
      39              : ! This code was written before the author became aware of
      40              : ! M. R. Zaghloul, Remark on "Algorithm 916: Computing the
      41              : ! Faddeyeva and Voight functions": efficiency improvements and
      42              : ! Fortran translation, ACM Trans. Math. Software 42, Article 26, 2016.
      43              : 
      44              : ! **************************************************************************************************
      45              : !> \brief Module to compute the error function of a complex argument
      46              : !> \par History
      47              : !>      08.2025 Adapted to use CP2K intrinsics and constants
      48              : !> \author Stefano Battaglia
      49              : ! **************************************************************************************************
      50              : MODULE erf_complex
      51              : 
      52              :    USE kinds,                           ONLY: dp
      53              :    USE mathconstants,                   ONLY: half,&
      54              :                                               one,&
      55              :                                               oorootpi,&
      56              :                                               pi,&
      57              :                                               two,&
      58              :                                               zero
      59              : 
      60              :    IMPLICIT NONE
      61              : 
      62              :    REAL(kind=dp), PARAMETER :: rmin = TINY(one), eps0 = EPSILON(one), &
      63              :                                sqrt_log_rmin = SQRT(-LOG(rmin)), &
      64              :                                pi2 = pi*pi
      65              :    COMPLEX(kind=dp), PARAMETER :: &
      66              :       cmplxj = CMPLX(zero, one, kind=dp), &
      67              :       cmplx0 = CMPLX(zero, zero, kind=dp)
      68              : 
      69              :    PRIVATE
      70              :    PUBLIC :: faddeyeva_fast, faddeyeva_accurate, erfz_fast, erfz_accurate
      71              : 
      72              : CONTAINS
      73              : 
      74              : ! **************************************************************************************************
      75              : !> \brief Computes the Faddeyeva function w(z) = exp(-z**2) * erfc(-i*z)
      76              : !> \param z complex argument
      77              : !> \param err desired accuracy (positive)
      78              : !> \return Faddeyeva function w(z)
      79              : ! **************************************************************************************************
      80            0 :    elemental COMPLEX(kind=dp) FUNCTION faddeyeva_accurate(z, err)
      81              : 
      82              :       ! This is the Faddeyeva or the plasma dispersion function,
      83              :       ! w(z) = exp(-z**2) * erfc(-i*z). erfc(z) is the complex complementary
      84              :       ! error function of z. z is a complex number.
      85              :       !
      86              :       ! Adapted from the Matlab code implementing TOMS
      87              :       ! Algorithm 916: http://www.netlib.org/toms/
      88              :       !
      89              :       ! file: 916.zip
      90              :       ! ref: TOMS 38,2 (Dec 2011) Article: 15
      91              :       ! for: Computing the Faddeyeva and Voigt Functions
      92              :       ! by: Mofreh R. Zaghloul and Ahmed N. Ali
      93              :       !
      94              :       ! Most of the code is calculation of equations (13)-(19) of the
      95              :       ! above paper.
      96              :       !
      97              :       ! Inputs:
      98              :       !    z - the argument of the function
      99              :       !  err - The desired accuracy (positive). err must be (err .le. 1.0e-4)
     100              :       !        and  (err .ge. 0.06447*epsilon). For efficiency,
     101              :       !        no checks are made!
     102              :       !        The lowest accuracy and the fastest calculation are obtained
     103              :       !        with err .eq. 1.0e-4. For higher accuracy use smaller err.
     104              : 
     105              :       COMPLEX(kind=dp), INTENT(in)                       :: z
     106              :       REAL(kind=dp), INTENT(in)                          :: err
     107              : 
     108              :       INTEGER                                            :: n, n3, n3_3
     109              :       REAL(kind=dp) :: a, a_pi, a_sqr, aux13, cos_2yx, del2_tmp, del3, del3_3_tmp, del3_tmp, del5, &
     110              :          delta3, delta5, den1, erfcsy, exp1, exp2, exp3, exp3_3_den, exp3_den, exp_del1, &
     111              :          exp_x_sqr, four_a_sqr, half_a, l_old, myerr, sigma1, sigma2, sigma3, sigma4, sigma4_5, &
     112              :          sigma5, sin_2yx, two_a, two_a_pi, two_a_sqr, two_a_x, two_exp_x_sqr_ysqr, two_yx, v_old, &
     113              :          x, x_sqr, xsign, y, y_sqr, ysign
     114              : 
     115            0 :       x = REAL(z)
     116            0 :       y = AIMAG(z)
     117              : 
     118              :       ! For purely imaginary z, use intrinsic scaled complement of
     119              :       ! the error function, erfc_scaled (F2008 and beyond).
     120              :       ! Return immediately.
     121            0 :       IF (ABS(x) == zero) THEN
     122            0 :          faddeyeva_accurate = erfc_scaled(y)
     123            0 :          RETURN
     124              :       END IF
     125              : 
     126            0 :       myerr = MAX(err, eps0)
     127            0 :       a = SQRT(-pi2/LOG(err/2.0_dp))
     128            0 :       half_a = half*a
     129            0 :       a_sqr = a**2
     130            0 :       two_a = 2*a
     131            0 :       two_a_sqr = 2*a_sqr
     132            0 :       four_a_sqr = 4*a_sqr
     133            0 :       a_pi = a/pi
     134            0 :       two_a_pi = 2*a_pi
     135            0 :       erfcsy = erfc_scaled(ABS(y))
     136            0 :       xsign = SIGN(one, x)
     137            0 :       ysign = SIGN(one, y)
     138            0 :       x = ABS(x)
     139            0 :       y = MAX(rmin, ABS(y))
     140            0 :       x_sqr = x**2
     141            0 :       y_sqr = y**2
     142            0 :       two_yx = 2*y*x
     143            0 :       two_a_x = two_a*x
     144            0 :       exp_x_sqr = EXP(-x_sqr)
     145            0 :       cos_2yx = COS(two_yx)
     146            0 :       sin_2yx = SIN(two_yx)
     147              :       v_old = exp_x_sqr* &
     148            0 :               (erfcsy*cos_2yx + two_a_pi*SIN(two_yx/2)**2/y)
     149            0 :       l_old = -erfcsy + a_pi/y
     150            0 :       sigma3 = rmin
     151            0 :       sigma5 = rmin
     152            0 :       sigma4_5 = zero
     153            0 :       delta3 = one
     154            0 :       delta5 = one
     155            0 :       n = 0
     156            0 :       n3 = CEILING(x/a)
     157            0 :       n3_3 = n3 - 1
     158              : 
     159            0 :       outer: IF ((sqrt_log_rmin - x) > 0) THEN
     160            0 :          sigma1 = rmin
     161            0 :          sigma2 = rmin
     162            0 :          sigma4 = rmin
     163            0 :          exp1 = EXP(-two_a_x)
     164            0 :          exp2 = EXP(four_a_sqr*n3 - 2*two_a_x - two_a_sqr)
     165            0 :          exp3 = EXP(-(two_a_sqr*n3 - two_a_x - two_a_sqr))
     166            0 :          del2_tmp = one
     167              :          del3_tmp = EXP(-(a_sqr*n3**2 - two_a_x*n3 &
     168            0 :                           - two_a_sqr*n3 + x_sqr + two_a_x + a_sqr))
     169            0 :          del3_3_tmp = EXP(a_sqr - (two_a_sqr*n3 - two_a_x))
     170              : 
     171            0 :          loop1: DO
     172            0 :             IF (delta3 < myerr .AND. delta5 < myerr .AND. &
     173              :                 n > 50) EXIT loop1
     174            0 :             n = n + 1
     175            0 :             den1 = a_sqr*n**2 + y_sqr
     176            0 :             exp_del1 = EXP(-(a_sqr*n**2))/den1
     177            0 :             del2_tmp = del2_tmp*exp1
     178              : 
     179            0 :             minor: IF (n3_3 >= 1) THEN
     180            0 :                del3_tmp = del3_tmp*exp3
     181              :                exp3_den = del3_tmp*exp_del1* &
     182            0 :                           (den1/(a_sqr*n3**2 + y_sqr))
     183            0 :                del3_3_tmp = del3_3_tmp*exp2
     184              :                exp3_3_den = exp3_den*del3_3_tmp* &
     185              :                             ((a_sqr*n3**2 + y_sqr)/ &
     186            0 :                              (a_sqr*n3_3**2 + y_sqr))
     187            0 :                del5 = n3_3*exp3_3_den + n3*exp3_den
     188            0 :                del3 = exp3_3_den + exp3_den
     189              :             ELSE
     190            0 :                del3_tmp = del3_tmp*exp3
     191              :                del3 = del3_tmp*exp_del1* &
     192            0 :                       (den1/(a_sqr*n3**2 + y_sqr))
     193            0 :                del5 = n3*del3
     194              :             END IF minor
     195              : 
     196            0 :             delta3 = del3/sigma3
     197            0 :             delta5 = del5/sigma5
     198            0 :             sigma1 = sigma1 + exp_del1
     199            0 :             sigma2 = sigma2 + del2_tmp*exp_x_sqr*exp_del1
     200            0 :             sigma3 = sigma3 + del3
     201            0 :             sigma4 = sigma4 + n*del2_tmp*exp_x_sqr*exp_del1
     202            0 :             sigma5 = sigma5 + del5
     203              : 
     204            0 :             IF (x >= 5.0e-4_dp) THEN
     205            0 :                sigma4_5 = -sigma4 + sigma5
     206              :             ELSE
     207              :                sigma4_5 = sigma4_5 + 2*n**2*two_a_x*exp_x_sqr &
     208              :                           *exp_del1*(one + 1.666666666666667e-1_dp &
     209              :                                      *(two_a_x*n)**2 + 8.333333333333333e-3_dp &
     210            0 :                                      *(two_a_x*n)**4)
     211              :             END IF
     212              : 
     213            0 :             n3 = n3 + 1
     214            0 :             n3_3 = n3_3 - 1
     215              : 
     216              :          END DO loop1
     217              : 
     218              :          ! Second line of Eqn (13)
     219              :          aux13 = y*two_a_pi* &
     220            0 :                  (-cos_2yx*exp_x_sqr*sigma1 + half*(sigma2 + sigma3))
     221            0 :          mumu: IF (y <= 5.0_dp .AND. two_yx > rmin) THEN
     222              :             faddeyeva_accurate = v_old + aux13 + cmplxj*xsign &
     223              :                                  *(sin_2yx*exp_x_sqr*(l_old + two_a_pi*y*sigma1) &
     224            0 :                                    + two_a_pi*half_a*sigma4_5)
     225            0 :          ELSE IF (y <= 5.0_dp .AND. two_yx <= rmin) THEN
     226              :             faddeyeva_accurate = v_old + aux13 + cmplxj*xsign &
     227              :                                  *(two*y*exp_x_sqr*(x*l_old + x*two_a_pi*y &
     228            0 :                                                     *sigma1) + two_a_pi*half_a*sigma4_5)
     229              :          ELSE
     230              :             faddeyeva_accurate = v_old + aux13 + cmplxj*xsign &
     231              :                                  *(sin_2yx*exp_x_sqr*MIN(zero, ABS(l_old &
     232              :                                                                    + (two_a_pi*y*sigma1))) + two_a_pi*half_a &
     233            0 :                                    *sigma4_5)
     234              :          END IF mumu
     235              : 
     236            0 :       ELSE IF (x >= sqrt_log_rmin .AND. x < 1.0e15_dp) THEN
     237              : 
     238            0 :          exp2 = EXP(four_a_sqr*n3 - 2*two_a_x - two_a_sqr)
     239            0 :          del3_3_tmp = EXP(a_sqr + two_a_x - two_a_sqr*n3)
     240              : 
     241            0 :          loop2: DO
     242            0 :             IF (delta3 < myerr .AND. delta5 < myerr .AND. &
     243              :                 n > 50) EXIT loop2
     244            0 :             n = n + 1
     245            0 :             IF (n3_3 >= 1) THEN
     246              :                exp3_den = EXP(-(a*n3 - x)*(a*n3 - x)) &
     247            0 :                           /(a_sqr*n3**2 + y_sqr)
     248            0 :                del3_3_tmp = del3_3_tmp*exp2
     249              :                exp3_3_den = exp3_den*del3_3_tmp*((a_sqr*n3**2 + y_sqr) &
     250            0 :                                                  /(a_sqr*n3_3**2 + y_sqr))
     251            0 :                del5 = n3_3*exp3_3_den + n3*exp3_den
     252            0 :                del3 = exp3_3_den + exp3_den
     253              :             ELSE
     254            0 :                del3 = EXP(-(a*n3 - x)**2)/(a_sqr*n3**2 + y_sqr)
     255            0 :                del5 = n3*del3
     256              :             END IF
     257              : 
     258            0 :             delta3 = del3/sigma3
     259            0 :             delta5 = del5/sigma5
     260            0 :             sigma3 = sigma3 + del3
     261            0 :             sigma5 = sigma5 + del5
     262            0 :             n3 = n3 + 1
     263            0 :             n3_3 = n3_3 - 1
     264              : 
     265              :          END DO loop2
     266              : 
     267              :          faddeyeva_accurate = v_old + y*a_pi*sigma3 + cmplxj*xsign*(sin_2yx &
     268            0 :                                                                     *exp_x_sqr*l_old + two_a_pi*half_a*sigma5)
     269              : 
     270              :       ELSE
     271            0 :          faddeyeva_accurate = oorootpi*((y + cmplxj*xsign*x)/(x_sqr + y_sqr))
     272              :       END IF outer
     273              : 
     274            0 :       IF (ysign < zero) THEN
     275            0 :          two_exp_x_sqr_ysqr = two*EXP(-x_sqr + y_sqr)
     276              :          faddeyeva_accurate = two_exp_x_sqr_ysqr*cos_2yx - REAL(faddeyeva_accurate) - cmplxj &
     277            0 :                               *(-xsign*two_exp_x_sqr_ysqr*sin_2yx - AIMAG(faddeyeva_accurate))
     278              :       END IF
     279              : 
     280              :    END FUNCTION faddeyeva_accurate
     281              : 
     282              : ! **************************************************************************************************
     283              : !> \brief Computes the error function of a complex argument using the Zaghloul and Ali algorithm
     284              : !> \param z complex argument
     285              : !> \param err desired accuracy (positive)
     286              : !> \return error function of z
     287              : ! **************************************************************************************************
     288            0 :    elemental COMPLEX(kind=dp) FUNCTION erfz_accurate(z, err)
     289              : 
     290              :       ! This is an error function of a complex argument, which uses faddeyeva_accurate(z).
     291              : 
     292              :       COMPLEX(kind=dp), INTENT(in)                       :: z
     293              :       REAL(kind=dp), INTENT(in)                          :: err
     294              : 
     295            0 :       erfz_accurate = one - faddeyeva_accurate(cmplxj*z, err)*EXP(-z**2)
     296              : 
     297            0 :    END FUNCTION erfz_accurate
     298              : 
     299              : ! **************************************************************************************************
     300              : !> \brief Computes the Faddeyeva function w(z) = exp(-z**2) * erfc(-i*z)
     301              : !> \param z complex argument
     302              : !> \return Faddeyeva function w(z)
     303              : ! **************************************************************************************************
     304       842260 :    elemental COMPLEX(kind=dp) FUNCTION faddeyeva_fast(z)
     305              : 
     306              :       ! A modified version of algorithm 680, rewritten in Fortran 2008.
     307              :       ! G.P.M. Poppe, C.M.J. Wijers, More efficient computation of
     308              :       ! the complex error-function, ACM Trans. Math. Software 16:38-46, 1990.
     309              :       !  and
     310              :       ! G.P.M. Poppe, C.M.J. Wijers, Algorithm 680, Evaluation of the
     311              :       ! complex error function, ACM Trans. Math. Software 16:47, 1990.
     312              :       !
     313              :       ! Given a complex number z, this function computes
     314              :       ! the value of the Faddeeva-function w(z) = exp(-z**2)*erfc(-i*z),
     315              :       ! where erfc is the complex complementary error-function and i
     316              :       ! means sqrt(-1).  The accuracy of the algorithm for z in the 1st
     317              :       ! and 2nd quadrant is 14 significant digits; in the 3rd and 4th
     318              :       ! it is 13 significant digits outside a circular region with radius
     319              :       ! 0.126 around a zero of the function.
     320              : 
     321              :       COMPLEX(kind=dp), INTENT(in)                       :: z
     322              : 
     323              :       REAL(kind=dp), PARAMETER :: factor = 1.12837916709551257388_dp
     324              : 
     325              :       INTEGER                                            :: i, j, kapn, n, np1, nu
     326              :       LOGICAL                                            :: a, b
     327              :       REAL(kind=dp)                                      :: c, daux, h, h2, qlambda, qrho, rx, ry, &
     328              :                                                             sx, sy, tx, ty, u, u1, u2, v, v1, v2, &
     329              :                                                             w1, x, xabs, xabsq, xaux, xi, xquad, &
     330              :                                                             xsum, y, yabs, yi, yquad, ysum
     331              : 
     332              :       !  factor is 2/sqrt(pi)
     333              : 
     334              :       ! To avoid the complier uninitialised varning
     335       842260 :       h2 = zero
     336              : 
     337       842260 :       xi = REAL(z)
     338       842260 :       yi = AIMAG(z)
     339       842260 :       xabs = ABS(xi)
     340       842260 :       yabs = ABS(yi)
     341       842260 :       x = xabs/6.3_dp
     342       842260 :       y = yabs/4.4_dp
     343       842260 :       qrho = x**2 + y**2
     344       842260 :       xabsq = xabs**2
     345       842260 :       xquad = xabsq - yabs**2
     346       842260 :       yquad = 2*xabs*yabs
     347              : 
     348       842260 :       a = qrho < 0.085264_dp
     349              : 
     350       842260 :       branch1: IF (a) THEN
     351              : 
     352              :          ! If ( qrho .lt. 0.085264 ) then the Faddeeva-function is evaluated
     353              :          !  using a power-series (abramowitz/stegun, equation (7.1.5), p.297)
     354              :          !  n is the minimum number of terms needed to obtain the required
     355              :          !  accuracy
     356              : 
     357            0 :          qrho = (one - 0.85_dp*y)*SQRT(qrho)
     358            0 :          n = NINT(6.0_dp + 72.0_dp*qrho)
     359            0 :          j = 2*n + 1
     360            0 :          xsum = one/REAL(j, kind=dp)
     361            0 :          ysum = zero
     362              : 
     363            0 :          DO i = n, 1, -1
     364            0 :             j = j - 2
     365            0 :             xaux = (xsum*xquad - ysum*yquad)/REAL(i, kind=dp)
     366            0 :             ysum = (xsum*yquad + ysum*xquad)/REAL(i, kind=dp)
     367            0 :             xsum = xaux + one/REAL(j, kind=dp)
     368              :          END DO
     369              : 
     370            0 :          u1 = -factor*(xsum*yabs + ysum*xabs) + one
     371            0 :          v1 = factor*(xsum*xabs - ysum*yabs)
     372            0 :          daux = EXP(-xquad)
     373            0 :          u2 = daux*COS(yquad)
     374            0 :          v2 = -daux*SIN(yquad)
     375            0 :          u = u1*u2 - v1*v2
     376            0 :          v = u1*v2 + v1*u2
     377              :       ELSE
     378              : 
     379       842260 :          bran2: IF (qrho > one) THEN
     380              : 
     381              :             ! If ( qrho .gt. 1) then w(z) is evaluated using the laplace
     382              :             ! continued fraction. nu is the minimum number of terms needed
     383              :             ! to obtain the required accuracy.
     384              : 
     385       841340 :             h = zero
     386       841340 :             kapn = 0
     387       841340 :             qrho = SQRT(qrho)
     388              :             nu = INT(3.0_dp + (1442.0_dp/(26.0_dp*qrho &
     389       841340 :                                           + 77.0_dp)))
     390              : 
     391              :          ELSE
     392              : 
     393              :             ! If ( qrho .ge. 0.085264 .and. qrho .le. one ) then
     394              :             ! w(z) is evaluated by a truncated Taylor expansion,
     395              :             ! where the Laplace continued fraction is used to calculate
     396              :             ! the derivatives of w(z). KAPN is the minimum number of terms
     397              :             ! in the Taylor expansion needed to obtain the required accuracy.
     398              :             ! NU is the minimum number of terms of the continued fraction
     399              :             ! needed to calculate the derivatives with the required accuracy.
     400              : 
     401          920 :             qrho = (one - y)*SQRT(one - qrho)
     402          920 :             h = 1.88_dp*qrho
     403          920 :             h2 = two*h
     404          920 :             kapn = NINT(7.0_dp + 34.0_dp*qrho)
     405          920 :             nu = NINT(16.0_dp + 26.0_dp*qrho)
     406              : 
     407              :          END IF bran2
     408              : 
     409       842260 :          b = h > zero
     410              : 
     411              :          ! To avoid uninitialise compiler warning. qlambda is used
     412              :          ! only if (b), so can define to any value otherwise.
     413       841340 :          qlambda = zero
     414          920 :          IF (b) qlambda = h2**kapn
     415              : 
     416       842260 :          rx = zero
     417       842260 :          ry = zero
     418       842260 :          sx = zero
     419       842260 :          sy = zero
     420              : 
     421     13006912 :          DO n = nu, 0, -1
     422     12164652 :             np1 = n + 1
     423     12164652 :             tx = yabs + h + np1*rx
     424     12164652 :             ty = xabs - np1*ry
     425     12164652 :             c = half/(tx**2 + ty**2)
     426     12164652 :             rx = c*tx
     427     12164652 :             ry = c*ty
     428     13006912 :             IF (b .AND. n <= kapn) THEN
     429         7360 :                tx = qlambda + sx
     430         7360 :                sx = rx*tx - ry*sy
     431         7360 :                sy = ry*tx + rx*sy
     432         7360 :                qlambda = qlambda/h2
     433              :             END IF
     434              :          END DO
     435              : 
     436       842260 :          IF (h == zero) THEN
     437       841340 :             u = factor*rx
     438       841340 :             v = factor*ry
     439              :          ELSE
     440          920 :             u = factor*sx
     441          920 :             v = factor*sy
     442              :          END IF
     443              : 
     444       842260 :          IF (yabs == zero) u = EXP(-xabs**2)
     445              : 
     446              :       END IF branch1
     447              : 
     448              :       ! Evaluation of w(z) in the other quadrants
     449              : 
     450       842260 :       IF (yi < zero) THEN
     451              : 
     452            0 :          IF (a) THEN
     453            0 :             u2 = two*u2
     454            0 :             v2 = two*v2
     455              :          ELSE
     456            0 :             xquad = -xquad
     457            0 :             w1 = two*EXP(xquad)
     458            0 :             u2 = w1*COS(yquad)
     459            0 :             v2 = -w1*SIN(yquad)
     460              :          END IF
     461              : 
     462            0 :          u = u2 - u
     463            0 :          v = v2 - v
     464            0 :          IF (xi > zero) v = -v
     465              :       ELSE
     466       842260 :          IF (xi < zero) v = -v
     467              :       END IF
     468              : 
     469       842260 :       faddeyeva_fast = CMPLX(u, v, kind=dp)
     470              : 
     471       842260 :    END FUNCTION faddeyeva_fast
     472              : 
     473              : ! **************************************************************************************************
     474              : !> \brief Computes the error function of a complex argument using the Poppe and Wijers algorithm
     475              : !> \param z complex argument
     476              : !> \return error function of z
     477              : ! **************************************************************************************************
     478       842260 :    elemental COMPLEX(kind=dp) FUNCTION erfz_fast(z)
     479              : 
     480              :       ! This is an error function of a complex argument, which uses faddeyeva_fast(z).
     481              : 
     482              :       COMPLEX(kind=dp), INTENT(in)                       :: z
     483              : 
     484       842260 :       erfz_fast = one - faddeyeva_fast(cmplxj*z)*EXP(-z**2)
     485              : 
     486       842260 :    END FUNCTION erfz_fast
     487              : 
     488              :    !*********************************************************************
     489              : END MODULE erf_complex
        

Generated by: LCOV version 2.0-1