LCOV - code coverage report
Current view: top level - src/grpp - grpp_specfunc_dawson.c (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:936074a) Lines: 0.0 % 114 0
Test Date: 2025-12-04 06:27:48 Functions: 0.0 % 11 0

            Line data    Source code
       1              : /*----------------------------------------------------------------------------*/
       2              : /*  CP2K: A general program to perform molecular dynamics simulations         */
       3              : /*  Copyright 2000-2025 CP2K developers group <https://cp2k.org>              */
       4              : /*                                                                            */
       5              : /*  SPDX-License-Identifier: MIT                                              */
       6              : /*----------------------------------------------------------------------------*/
       7              : 
       8              : /*
       9              :  *  libgrpp - a library for the evaluation of integrals over
      10              :  *            generalized relativistic pseudopotentials.
      11              :  *
      12              :  *  Copyright (C) 2021-2023 Alexander Oleynichenko
      13              :  */
      14              : 
      15              : #include <float.h> // required for LDBL_EPSILON
      16              : #include <math.h>  // required for fabsl()
      17              : #ifndef M_PI
      18              : #define M_PI 3.1415926535897932384626433
      19              : #endif
      20              : 
      21              : #include "grpp_specfunc.h"
      22              : 
      23              : /*
      24              :  * This code is taken from the website:
      25              :  * http://www.mymathlib.com/functions/dawsons_integral.html
      26              :  */
      27              : 
      28              : ////////////////////////////////////////////////////////////////////////////////
      29              : // File: specfunc_dawson.c                                                    //
      30              : // Routine(s):                                                                //
      31              : //    Dawsons_Integral                                                        //
      32              : //    xDawsons_Integral                                                       //
      33              : ////////////////////////////////////////////////////////////////////////////////
      34              : ////////////////////////////////////////////////////////////////////////////////
      35              : //  Description:                                                              //
      36              : //     Dawson's integral, Daw(x), is the integral from 0 to x of the          //
      37              : //     integrand:                                                             //
      38              : //                          exp(-x^2) exp(t^2) dt.                            //
      39              : //     I.e.                                                                   //
      40              : //                Daw(x) = exp(-x^2) * I[0,x] (exp(t^2)) dt,                  //
      41              : //     where I[0,x] indicates the integral from 0 to x.                       //
      42              : ////////////////////////////////////////////////////////////////////////////////
      43              : #define Asymptotic_Expansion_Cutoff 50
      44              : 
      45              : //                         Externally Defined Routines                        //
      46              : static long double xChebyshev_Tn_Series(long double x, long double a[],
      47              :                                         int degree);
      48              : 
      49              : //                         Internally Defined Routines                        //
      50              : double libgrpp_Dawsons_Integral(double x);
      51              : long double xDawsons_Integral(long double x);
      52              : 
      53              : static long double Dawson_Power_Series(long double x);
      54              : static long double Dawson_Chebyshev_Expansion_1_175(long double x);
      55              : static long double Dawson_Chebyshev_Expansion_175_250(long double x);
      56              : static long double Dawson_Chebyshev_Expansion_250_325(long double x);
      57              : static long double Dawson_Chebyshev_Expansion_325_425(long double x);
      58              : static long double Dawson_Chebyshev_Expansion_425_550(long double x);
      59              : static long double Dawson_Chebyshev_Expansion_550_725(long double x);
      60              : static long double Dawson_Asymptotic_Expansion(long double x);
      61              : 
      62              : ////////////////////////////////////////////////////////////////////////////////
      63              : // double libgrpp_Dawsons_Integral( double x ) //
      64              : //                                                                            //
      65              : //  Description:                                                              //
      66              : //     Dawson's integral, Daw(x), is the integral with integrand              //
      67              : //                          exp(-x^2) exp(t^2) dt                             //
      68              : //     where the integral extends from 0 to x.                                //
      69              : //                                                                            //
      70              : //  Arguments:                                                                //
      71              : //     double  x  The argument of Dawson's integral Daw().                    //
      72              : //                                                                            //
      73              : //  Return Value:                                                             //
      74              : //     The value of Dawson's integral, Daw(), evaluated at x.                 //
      75              : //                                                                            //
      76              : //  Example:                                                                  //
      77              : //     double y, x;                                                           //
      78              : //                                                                            //
      79              : //     ( code to initialize x )                                               //
      80              : //                                                                            //
      81              : //     y = Dawsons_Integral( x );                                             //
      82              : ////////////////////////////////////////////////////////////////////////////////
      83            0 : double libgrpp_Dawsons_Integral(double x) {
      84            0 :   return (double)xDawsons_Integral((long double)x);
      85              : }
      86              : 
      87              : ////////////////////////////////////////////////////////////////////////////////
      88              : // long double xDawsons_Integral( long double x )                             //
      89              : //                                                                            //
      90              : //  Description:                                                              //
      91              : //     Dawson's integral, Daw(x), is the integral with integrand              //
      92              : //                          exp(-x^2) exp(t^2) dt                             //
      93              : //     where the integral extends from 0 to x.                                //
      94              : //                                                                            //
      95              : //  Arguments:                                                                //
      96              : //     long double  x  The argument of Dawson's integral Daw().               //
      97              : //                                                                            //
      98              : //  Return Value:                                                             //
      99              : //     The value of Dawson's integral, Daw(), evaluated at x.                 //
     100              : //                                                                            //
     101              : //  Example:                                                                  //
     102              : //     long double y, x;                                                      //
     103              : //                                                                            //
     104              : //     ( code to initialize x )                                               //
     105              : //                                                                            //
     106              : //     y = xDawsons_Integral( x );                                            //
     107              : ////////////////////////////////////////////////////////////////////////////////
     108              : 
     109            0 : long double xDawsons_Integral(long double x) {
     110            0 :   long double abs_x = fabsl(x);
     111              : 
     112            0 :   if (abs_x <= 1.0L)
     113            0 :     return Dawson_Power_Series(x);
     114            0 :   if (abs_x <= 1.75L)
     115            0 :     return Dawson_Chebyshev_Expansion_1_175(x);
     116            0 :   if (abs_x <= 2.50L)
     117            0 :     return Dawson_Chebyshev_Expansion_175_250(x);
     118            0 :   if (abs_x <= 3.25L)
     119            0 :     return Dawson_Chebyshev_Expansion_250_325(x);
     120            0 :   if (abs_x <= 4.25L)
     121            0 :     return Dawson_Chebyshev_Expansion_325_425(x);
     122            0 :   if (abs_x <= 5.50L)
     123            0 :     return Dawson_Chebyshev_Expansion_425_550(x);
     124            0 :   if (abs_x <= 7.25L)
     125            0 :     return Dawson_Chebyshev_Expansion_550_725(x);
     126            0 :   return Dawson_Asymptotic_Expansion(x);
     127              : }
     128              : 
     129              : ////////////////////////////////////////////////////////////////////////////////
     130              : // static long double Dawson_Power_Series( long double x )                    //
     131              : //                                                                            //
     132              : //  Description:                                                              //
     133              : //     Evaluate Dawsons integral for -1 <= x <= 1 using the power series      //
     134              : //     expansion:                                                             //
     135              : //                  Daw(x) = x Sum [(-2x^2)^j / (2j + 1)!!,                   //
     136              : //     where the sum extends over j = 0, ... .                                //
     137              : //                                                                            //
     138              : //  Arguments:                                                                //
     139              : //     long double  x  The argument of Dawson's integral Daw(), where         //
     140              : //                     where |x| <= 1.                                        //
     141              : //                                                                            //
     142              : //  Return Value:                                                             //
     143              : //     The value of Dawson's integral, Daw(), evaluated at x where |x| <= 1.  //
     144              : //                                                                            //
     145              : //  Example:                                                                  //
     146              : //     long double y, x;                                                      //
     147              : //                                                                            //
     148              : //     ( code to initialize x )                                               //
     149              : //                                                                            //
     150              : //     y = Dawson_Power_Series(x);                                            //
     151              : ////////////////////////////////////////////////////////////////////////////////
     152              : 
     153            0 : static long double Dawson_Power_Series(long double x) {
     154            0 :   long double two_x2 = -2.0L * x * x;
     155            0 :   long double sum = 0.0;
     156            0 :   long double term = 1.0L;
     157            0 :   long double factorial = 1.0L;
     158            0 :   long double xn = 1.0L;
     159            0 :   const long double epsilon = LDBL_EPSILON / 2.0L;
     160            0 :   int y = 0;
     161              : 
     162            0 :   if (x == 0.0L)
     163              :     return 0.0L;
     164            0 :   do {
     165            0 :     sum += term;
     166            0 :     y += 1;
     167            0 :     factorial *= (long double)(y + y + 1);
     168            0 :     xn *= two_x2;
     169            0 :     term = xn / factorial;
     170            0 :   } while (fabsl(term) > epsilon * fabsl(sum));
     171            0 :   return x * sum;
     172              : }
     173              : 
     174              : ////////////////////////////////////////////////////////////////////////////////
     175              : // static long double Dawson_Chebyshev_Expansion_1_175( long double x )       //
     176              : //                                                                            //
     177              : //  Description:                                                              //
     178              : //     Evaluate Dawsons integral for 1 <= |x| <= 1.75 using the Chebyshev     //
     179              : //     expansion of Daw(x) for x in the interval [1,1.75].                    //
     180              : //                                                                            //
     181              : //  Arguments:                                                                //
     182              : //     long double  x  The argument of Dawson's integral Daw(), where         //
     183              : //                     where 1 <= |x| <= 1.75.                                //
     184              : //                                                                            //
     185              : //  Return Value:                                                             //
     186              : //     The value of Dawson's integral, Daw(), evaluated at x where            //
     187              : //     1 <= x <= 1.75.                                                        //
     188              : //                                                                            //
     189              : //  Example:                                                                  //
     190              : //     long double y, x;                                                      //
     191              : //                                                                            //
     192              : //     ( code to initialize x )                                               //
     193              : //                                                                            //
     194              : //     y = Dawson_Chebyshev_Expansion_1_175(x);                               //
     195              : ////////////////////////////////////////////////////////////////////////////////
     196              : 
     197            0 : static long double Dawson_Chebyshev_Expansion_1_175(long double x) {
     198            0 :   static long double c[] = {
     199              :       +4.563960711239483142081e-1L,  -9.268566100670767619861e-2L,
     200              :       -7.334392170021420220239e-3L,  +3.379523740404396755124e-3L,
     201              :       -3.085898448678595090813e-4L,  -1.519846724619319512311e-5L,
     202              :       +4.903955822454009397182e-6L,  -2.106910538629224721838e-7L,
     203              :       -2.930676220603996192089e-8L,  +3.326790071774057337673e-9L,
     204              :       +3.335593457695769191326e-11L, -2.279104036721012221982e-11L,
     205              :       +7.877561633156348806091e-13L, +9.173158167107974472228e-14L,
     206              :       -7.341175636102869400671e-15L, -1.763370444125849029511e-16L,
     207              :       +3.792946298506435014290e-17L, -4.251969162435936250171e-19L,
     208              :       -1.358295820818448686821e-19L, +5.268740962820224108235e-21L,
     209              :       +3.414939674304748094484e-22L};
     210              : 
     211            0 :   static const int degree = sizeof(c) / sizeof(long double) - 1;
     212            0 :   static const long double midpoint = (1.75L + 1.0L) / 2.0L;
     213            0 :   static const long double half_length = (1.75L - 1.0L) / 2.0L;
     214            0 :   long double daw =
     215            0 :       xChebyshev_Tn_Series((fabsl(x) - midpoint) / half_length, c, degree);
     216            0 :   return (x > 0.0L) ? daw : -daw;
     217              : }
     218              : 
     219              : ////////////////////////////////////////////////////////////////////////////////
     220              : // static long double Dawson_Chebyshev_Expansion_175_250( long double x )     //
     221              : //                                                                            //
     222              : //  Description:                                                              //
     223              : //     Evaluate Dawsons integral for 1.75 <= |x| <= 2.50 using the Chebyshev  //
     224              : //     expansion of Daw(x) for x in the interval [1.75,2.50].                 //
     225              : //                                                                            //
     226              : //  Arguments:                                                                //
     227              : //     long double  x  The argument of Dawson's integral Daw(), where         //
     228              : //                     where 1.75 <= |x| <= 2.50.                             //
     229              : //                                                                            //
     230              : //  Return Value:                                                             //
     231              : //     The value of Dawson's integral, Daw(), evaluated at x where            //
     232              : //     1.75 <= x <= 2.50.                                                     //
     233              : //                                                                            //
     234              : //  Example:                                                                  //
     235              : //     long double y, x;                                                      //
     236              : //                                                                            //
     237              : //     ( code to initialize x )                                               //
     238              : //                                                                            //
     239              : //     y = Dawson_Chebyshev_Expansion_175_250(x);                             //
     240              : ////////////////////////////////////////////////////////////////////////////////
     241              : 
     242            0 : static long double Dawson_Chebyshev_Expansion_175_250(long double x) {
     243            0 :   static long double c[] = {
     244              :       +2.843711194548592808550e-1L,  -6.791774139166808940530e-2L,
     245              :       +6.955211059379384327814e-3L,  -2.726366582146839486784e-4L,
     246              :       -6.516682485087925163874e-5L,  +1.404387911504935155228e-5L,
     247              :       -1.103288540946056915318e-6L,  -1.422154597293404846081e-8L,
     248              :       +1.102714664312839585330e-8L,  -8.659211557383544255053e-10L,
     249              :       -8.048589443963965285748e-12L, +6.092061709996351761426e-12L,
     250              :       -3.580977611213519234324e-13L, -1.085173558590137965737e-14L,
     251              :       +2.411707924175380740802e-15L, -7.760751294610276598631e-17L,
     252              :       -6.701490147030045891595e-18L, +6.350145841254563572100e-19L,
     253              :       -2.034625734538917052251e-21L, -2.260543651146274653910e-21L,
     254              :       +9.782419961387425633151e-23L};
     255              : 
     256            0 :   static const int degree = sizeof(c) / sizeof(long double) - 1;
     257            0 :   static const long double midpoint = (2.50L + 1.75L) / 2.0L;
     258            0 :   static const long double half_length = (2.50L - 1.75L) / 2.0;
     259            0 :   long double daw =
     260            0 :       xChebyshev_Tn_Series((fabsl(x) - midpoint) / half_length, c, degree);
     261            0 :   return (x > 0.0L) ? daw : -daw;
     262              : }
     263              : 
     264              : ////////////////////////////////////////////////////////////////////////////////
     265              : // static long double Dawson_Chebyshev_Expansion_250_325( long double x )     //
     266              : //                                                                            //
     267              : //  Description:                                                              //
     268              : //     Evaluate Dawsons integral for 2.5 <= |x| <= 3.25 using the Chebyshev   //
     269              : //     expansion of Daw(x) for x in the interval [2.50,3.25].                 //
     270              : //                                                                            //
     271              : //  Arguments:                                                                //
     272              : //     long double  x  The argument of Dawson's integral Daw(), where         //
     273              : //                     where 2.50 <= |x| <= 3.25.                             //
     274              : //                                                                            //
     275              : //  Return Value:                                                             //
     276              : //     The value of Dawson's integral, Daw(), evaluated at x where            //
     277              : //     2.50 <= x <= 3.25.                                                     //
     278              : //                                                                            //
     279              : //  Example:                                                                  //
     280              : //     long double y, x;                                                      //
     281              : //                                                                            //
     282              : //     ( code to initialize x )                                               //
     283              : //                                                                            //
     284              : //     y = Dawson_Chebyshev_Expansion_250_325(x);                             //
     285              : ////////////////////////////////////////////////////////////////////////////////
     286              : 
     287            0 : static long double Dawson_Chebyshev_Expansion_250_325(long double x) {
     288            0 :   static long double c[] = {
     289              :       +1.901351274204578126827e-1L,  -3.000575522193632460118e-2L,
     290              :       +2.672138524890489432579e-3L,  -2.498237548675235150519e-4L,
     291              :       +2.013483163459701593271e-5L,  -8.454663603108548182962e-7L,
     292              :       -8.036589636334016432368e-8L,  +2.055498509671357933537e-8L,
     293              :       -2.052151324060186596995e-9L,  +8.584315967075483822464e-11L,
     294              :       +5.062689357469596748991e-12L, -1.038671167196342609090e-12L,
     295              :       +6.367962851860231236238e-14L, +3.084688422647419767229e-16L,
     296              :       -3.417946142546575188490e-16L, +2.311567730100119302160e-17L,
     297              :       -6.170132546983726244716e-20L, -9.133176920944950460847e-20L,
     298              :       +5.712092431423316128728e-21L, +1.269641078369737220790e-23L,
     299              :       -2.072659711527711312699e-23L};
     300              : 
     301            0 :   static const int degree = sizeof(c) / sizeof(long double) - 1;
     302            0 :   static const long double midpoint = (3.25L + 2.50L) / 2.0L;
     303            0 :   static const long double half_length = (3.25L - 2.50L) / 2.0L;
     304            0 :   long double daw =
     305            0 :       xChebyshev_Tn_Series((fabsl(x) - midpoint) / half_length, c, degree);
     306            0 :   return (x > 0.0L) ? daw : -daw;
     307              : }
     308              : 
     309              : ////////////////////////////////////////////////////////////////////////////////
     310              : // static long double Dawson_Chebyshev_Expansion_325_425( long double x )     //
     311              : //                                                                            //
     312              : //  Description:                                                              //
     313              : //     Evaluate Dawsons integral for 3.25 <= |x| <= 4.25 using the Chebyshev  //
     314              : //     expansion of Daw(x) for x in the interval [3.25,4.75].                 //
     315              : //                                                                            //
     316              : //  Arguments:                                                                //
     317              : //     long double  x  The argument of Dawson's integral Daw(), where         //
     318              : //                     where 3.25 <= |x| <= 4.25.                             //
     319              : //                                                                            //
     320              : //  Return Value:                                                             //
     321              : //     The value of Dawson's integral, Daw(), evaluated at x where            //
     322              : //     3.25 <= x <= 4.25.                                                     //
     323              : //                                                                            //
     324              : //  Example:                                                                  //
     325              : //     long double y, x;                                                      //
     326              : //                                                                            //
     327              : //     ( code to initialize x )                                               //
     328              : //                                                                            //
     329              : //     y = Dawson_Chebyshev_Expansion_325_425(x);                             //
     330              : ////////////////////////////////////////////////////////////////////////////////
     331              : 
     332            0 : static long double Dawson_Chebyshev_Expansion_325_425(long double x) {
     333            0 :   static long double c[] = {
     334              :       +1.402884974484995678749e-1L,  -2.053975371995937033959e-2L,
     335              :       +1.595388628922920119352e-3L,  -1.336894584910985998203e-4L,
     336              :       +1.224903774178156286300e-5L,  -1.206856028658387948773e-6L,
     337              :       +1.187997233269528945503e-7L,  -1.012936061496824448259e-8L,
     338              :       +5.244408240062370605664e-10L, +2.901444759022254846562e-11L,
     339              :       -1.168987502493903926906e-11L, +1.640096995420504465839e-12L,
     340              :       -1.339190668554209618318e-13L, +3.643815972666851044790e-15L,
     341              :       +6.922486581126169160232e-16L, -1.158761251467106749752e-16L,
     342              :       +8.164320395639210093180e-18L, -5.397918405779863087588e-20L,
     343              :       -5.052069908100339242896e-20L, +5.322512674746973445361e-21L,
     344              :       -1.869294542789169825747e-22L};
     345              : 
     346            0 :   static const int degree = sizeof(c) / sizeof(long double) - 1;
     347              :   // static const long double lower_bound = 3.25L;
     348              :   // static const long double upper_bound = 4.25L;
     349            0 :   static const long double midpoint = (4.25L + 3.25L) / 2.0L;
     350            0 :   static const long double half_length = (4.25L - 3.25L) / 2.0L;
     351            0 :   long double daw =
     352            0 :       xChebyshev_Tn_Series((fabsl(x) - midpoint) / half_length, c, degree);
     353            0 :   return (x > 0.0L) ? daw : -daw;
     354              : }
     355              : 
     356              : ////////////////////////////////////////////////////////////////////////////////
     357              : // static long double Dawson_Chebyshev_Expansion_425_550( long double x )     //
     358              : //                                                                            //
     359              : //  Description:                                                              //
     360              : //     Evaluate Dawsons integral for 4.25 <= |x| <= 5.50 using the Chebyshev  //
     361              : //     expansion of Daw(x) for x in the interval [4.25,5.50].                 //
     362              : //                                                                            //
     363              : //  Arguments:                                                                //
     364              : //     long double  x  The argument of Dawson's integral Daw(), where         //
     365              : //                     where 4.25 <= |x| <= 5.50.                             //
     366              : //                                                                            //
     367              : //  Return Value:                                                             //
     368              : //     The value of Dawson's integral, Daw(), evaluated at x where            //
     369              : //     4.25 <= x <= 5.50.                                                     //
     370              : //                                                                            //
     371              : //  Example:                                                                  //
     372              : //     long double y, x;                                                      //
     373              : //                                                                            //
     374              : //     ( code to initialize x )                                               //
     375              : //                                                                            //
     376              : //     y = Dawson_Chebyshev_Expansion_425_550(x);                             //
     377              : ////////////////////////////////////////////////////////////////////////////////
     378              : 
     379            0 : static long double Dawson_Chebyshev_Expansion_425_550(long double x) {
     380            0 :   static long double c[] = {
     381              :       +1.058610209741581514157e-1L,  -1.429297757627935191694e-2L,
     382              :       +9.911301703835545472874e-4L,  -7.079903107876049846509e-5L,
     383              :       +5.229587914675267516134e-6L,  -4.016071345964089296212e-7L,
     384              :       +3.231734714422926453741e-8L,  -2.752870944370338482109e-9L,
     385              :       +2.503059741885009530630e-10L, -2.418699000594890423278e-11L,
     386              :       +2.410158905786160001792e-12L, -2.327254341132174000949e-13L,
     387              :       +1.958284411563056492727e-14L, -1.099893145048991004460e-15L,
     388              :       -2.959085292526991317697e-17L, +1.966366179276295203082e-17L,
     389              :       -3.314408783993662492621e-18L, +3.635520318133814622089e-19L,
     390              :       -2.550826919215104648800e-20L, +3.830090587178262542288e-22L,
     391              :       +1.836693763159216122739e-22L};
     392              : 
     393            0 :   static const int degree = sizeof(c) / sizeof(long double) - 1;
     394            0 :   static const long double midpoint = (5.50L + 4.25L) / 2.0L;
     395            0 :   static const long double half_length = (5.50L - 4.25L) / 2.0L;
     396            0 :   long double daw =
     397            0 :       xChebyshev_Tn_Series((fabsl(x) - midpoint) / half_length, c, degree);
     398            0 :   return (x > 0.0L) ? daw : -daw;
     399              : }
     400              : 
     401              : ////////////////////////////////////////////////////////////////////////////////
     402              : // static long double Dawson_Chebyshev_Expansion_550_725( long double x )     //
     403              : //                                                                            //
     404              : //  Description:                                                              //
     405              : //     Evaluate Dawsons integral for 5.50 <= |x| <= 7.25 using the Chebyshev  //
     406              : //     expansion of Daw(x) for x in the interval [5.50,7.25].                 //
     407              : //                                                                            //
     408              : //  Arguments:                                                                //
     409              : //     long double  x  The argument of Dawson's integral Daw(), where         //
     410              : //                     where 5.50 <= |x| <= 7.25.                             //
     411              : //                                                                            //
     412              : //  Return Value:                                                             //
     413              : //     The value of Dawson's integral, Daw(), evaluated at x where            //
     414              : //     5.50 <= x <= 7.25.                                                     //
     415              : //                                                                            //
     416              : //  Example:                                                                  //
     417              : //     long double y, x;                                                      //
     418              : //                                                                            //
     419              : //     ( code to initialize x )                                               //
     420              : //                                                                            //
     421              : //     y = Dawson_Chebyshev_Expansion_550_725(x);                             //
     422              : ////////////////////////////////////////////////////////////////////////////////
     423              : 
     424            0 : static long double Dawson_Chebyshev_Expansion_550_725(long double x) {
     425            0 :   static long double c[] = {+8.024637207807814739314e-2L,
     426              :                             -1.136614891549306029413e-2L,
     427              :                             +8.164249750628661856014e-4L,
     428              :                             -5.951964778701328943018e-5L,
     429              :                             +4.407349502747483429390e-6L,
     430              :                             -3.317746826184531133862e-7L,
     431              :                             +2.541483569880571680365e-8L,
     432              :                             -1.983391157250772649001e-9L,
     433              :                             +1.579050614491277335581e-10L,
     434              :                             -1.284592098551537518322e-11L,
     435              :                             +1.070070857004674207604e-12L,
     436              :                             -9.151832297362522251950e-14L,
     437              :                             +8.065447314948125338081e-15L,
     438              :                             -7.360105847607056315915e-16L,
     439              :                             +6.995966000187407197283e-17L,
     440              :                             -6.964349343411584120055e-18L,
     441              :                             +7.268789359189778223225e-19L,
     442              :                             -7.885125241947769024019e-20L,
     443              :                             +8.689022564130615225208e-21L,
     444              :                             -9.353211304381231554634e-22L +
     445              :                                 9.218280404899298404756e-23L};
     446              : 
     447            0 :   static const int degree = sizeof(c) / sizeof(long double) - 1;
     448              :   // static const long double lower_bound = 5.50L;
     449              :   // static const long double upper_bound = 7.25L;
     450            0 :   static const long double midpoint = (7.25L + 5.50L) / 2.0L;
     451            0 :   static const long double half_length = (7.25L - 5.50L) / 2.0L;
     452            0 :   long double daw =
     453            0 :       xChebyshev_Tn_Series((fabsl(x) - midpoint) / half_length, c, degree);
     454            0 :   return (x > 0.0L) ? daw : -daw;
     455              : }
     456              : 
     457              : ////////////////////////////////////////////////////////////////////////////////
     458              : // static long double Dawson_Asymptotic_Expansion( long double x )            //
     459              : //                                                                            //
     460              : //  Description:                                                              //
     461              : //     For a large magnitude of the argument x, Dawson's integral can be      //
     462              : //     expressed as the asymptotic series                                     //
     463              : //     Daw(x) ~ (1/2x) [ 1 + 1 / (2x^2) + ... + (2j - 1)!! / (2x^2)^j + ... ] //
     464              : //                                                                            //
     465              : //  Arguments:                                                                //
     466              : //     long double  x  The argument of Dawson's integral Daw(), where         //
     467              : //                     |x| > 7.                                               //
     468              : //                                                                            //
     469              : //  Return Value:                                                             //
     470              : //     The value of Dawson's integral, Daw(), evaluated at x where |x| > 7.   //
     471              : //                                                                            //
     472              : //  Example:                                                                  //
     473              : //     long double y, x;                                                      //
     474              : //                                                                            //
     475              : //     ( code to initialize x )                                               //
     476              : //                                                                            //
     477              : //     y = Dawson_Asymptotic_Expansion( x );                                  //
     478              : ////////////////////////////////////////////////////////////////////////////////
     479            0 : static long double Dawson_Asymptotic_Expansion(long double x) {
     480            0 :   long double term[Asymptotic_Expansion_Cutoff + 1];
     481            0 :   long double x2 = x * x;
     482            0 :   long double two_x = x + x;
     483            0 :   long double two_x2 = x2 + x2;
     484            0 :   long double xn = two_x2;
     485            0 :   long double Sn = 0.0L;
     486            0 :   long double factorial = 1.0L;
     487            0 :   int n;
     488              : 
     489            0 :   term[0] = 1.0L;
     490            0 :   term[1] = 1.0L / xn;
     491            0 :   for (n = 2; n <= Asymptotic_Expansion_Cutoff; n++) {
     492            0 :     xn *= two_x2;
     493            0 :     factorial *= (long double)(n + n - 1);
     494            0 :     term[n] = factorial / xn;
     495            0 :     if (term[n] < LDBL_EPSILON / 2.0L)
     496              :       break;
     497              :   }
     498              : 
     499            0 :   if (n > Asymptotic_Expansion_Cutoff)
     500              :     n = Asymptotic_Expansion_Cutoff;
     501            0 :   for (; n >= 0; n--)
     502            0 :     Sn += term[n];
     503            0 :   return Sn / two_x;
     504              : }
     505              : 
     506              : ////////////////////////////////////////////////////////////////////////////////
     507              : // File: xchebyshev_Tn_series.c                                               //
     508              : // Routine(s):                                                                //
     509              : //    xChebyshev_Tn_Series                                                    //
     510              : ////////////////////////////////////////////////////////////////////////////////
     511              : ////////////////////////////////////////////////////////////////////////////////
     512              : // long double xChebyshev_Tn_Series(long double x, long double a[],int degree)//
     513              : //                                                                            //
     514              : //  Description:                                                              //
     515              : //     This routine uses Clenshaw's recursion algorithm to evaluate a given   //
     516              : //     polynomial p(x) expressed as a linear combination of Chebyshev         //
     517              : //     polynomials of the first kind, Tn, at a point x,                       //
     518              : //       p(x) = a[0] + a[1]*T[1](x) + a[2]*T[2](x) + ... + a[deg]*T[deg](x).  //
     519              : //                                                                            //
     520              : //     Clenshaw's recursion formula applied to Chebyshev polynomials of the   //
     521              : //     first kind is:                                                         //
     522              : //     Set y[degree + 2] = 0, y[degree + 1] = 0, then for k = degree, ..., 1  //
     523              : //     set y[k] = 2 * x * y[k+1] - y[k+2] + a[k].  Finally                    //
     524              : //     set y[0] = x * y[1] - y[2] + a[0].  Then p(x) = y[0].                  //
     525              : //                                                                            //
     526              : //  Arguments:                                                                //
     527              : //     long double x                                                          //
     528              : //        The point at which to evaluate the polynomial.                      //
     529              : //     long double a[]                                                        //
     530              : //        The coefficients of the expansion in terms of Chebyshev polynomials,//
     531              : //        i.e. a[k] is the coefficient of T[k](x).  Note that in the calling  //
     532              : //        routine a must be defined double a[N] where N >= degree + 1.        //
     533              : //     int    degree                                                          //
     534              : //        The degree of the polynomial p(x).                                  //
     535              : //                                                                            //
     536              : //  Return Value:                                                             //
     537              : //     The value of the polynomial at x.                                      //
     538              : //     If degree is negative, then 0.0 is returned.                           //
     539              : //                                                                            //
     540              : //  Example:                                                                  //
     541              : //     long double x, a[N], p;                                                //
     542              : //     int    deg = N - 1;                                                    //
     543              : //                                                                            //
     544              : //     ( code to initialize x, and a[i] i = 0, ... , a[deg] )                 //
     545              : //                                                                            //
     546              : //     p = xChebyshev_Tn_Series(x, a, deg);                                   //
     547              : ////////////////////////////////////////////////////////////////////////////////
     548              : 
     549            0 : static long double xChebyshev_Tn_Series(long double x, long double a[],
     550              :                                         int degree) {
     551            0 :   long double yp2 = 0.0L;
     552            0 :   long double yp1 = 0.0L;
     553            0 :   long double y = 0.0L;
     554            0 :   long double two_x = x + x;
     555            0 :   int k;
     556              : 
     557              :   // Check that degree >= 0.  If not, then return 0. //
     558              : 
     559            0 :   if (degree < 0)
     560              :     return 0.0L;
     561              : 
     562              :   // Apply Clenshaw's recursion save the last iteration. //
     563              : 
     564            0 :   for (k = degree; k >= 1; k--, yp2 = yp1, yp1 = y)
     565            0 :     y = two_x * yp1 - yp2 + a[k];
     566              : 
     567              :   // Now apply the last iteration and return the result. //
     568              : 
     569            0 :   return x * yp1 - yp2 + a[0];
     570              : }
        

Generated by: LCOV version 2.0-1