star-line

Structure for accelerating line importance sampling
git clone git://git.meso-star.com/star-line.git
Log | Files | Refs | README | LICENSE

sln_faddeeva.c (5264B)


      1 /* Copyright (C) 2022, 2026 |Méso|Star> (contact@meso-star.com)
      2  * Copyright (C) 2026 Université de Lorraine
      3  * Copyright (C) 2022 Centre National de la Recherche Scientifique
      4  * Copyright (C) 2022 Université Paul Sabatier
      5  *
      6  * This file is part of Star-Line.
      7  *
      8  * This program is free software: you can redistribute it and/or modify
      9  * it under the terms of the GNU General Public License as published by
     10  * the Free Software Foundation, either version 3 of the License, or
     11  * (at your option) any later version.
     12  *
     13  * This program is distributed in the hope that it will be useful,
     14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
     16  * GNU General Public License for more details.
     17  *
     18  * You should have received a copy of the GNU General Public License
     19  * along with this program. If not, see <http://www.gnu.org/licenses/>. */
     20 
     21 #include "sln.h"
     22 
     23 /*******************************************************************************
     24  * Exported function
     25  ******************************************************************************/
     26 double
     27 sln_faddeeva(const double x, const double Y)
     28 {
     29   /* Constants */
     30   const double RRTPI = 0.56418958;
     31 
     32   /* For CPF12 algorithm */
     33   const double Y0 = 1.5;
     34   const double Y0PY0 = Y0+Y0;
     35   const double Y0Q = Y0*Y0;
     36 
     37   const double C[6] = {
     38     1.0117281,
     39     -0.75197147,
     40     0.012557727,
     41     0.010022008,
     42     -0.00024206814,
     43     0.00000050084806
     44   };
     45   const double S[6] = {
     46     1.393237,
     47     0.23115241,
     48     -0.15535147,
     49     0.0062183662,
     50     0.000091908299,
     51     -0.00000062752596
     52   };
     53   const double T[6] = {
     54     0.31424038,
     55     0.94778839,
     56     1.5976826,
     57     2.2795071,
     58     3.0206370,
     59     3.8897249
     60   };
     61 
     62   double ABX, XQ, YQ, YRRTPI;
     63   double XLIM0, XLIM1, XLIM2, XLIM3, XLIM4;
     64   double A0, D0, D2, E0, E2, E4, H0, H2, H4, H6;
     65   double P0, P2, P4, P6, P8, Z0, Z2, Z4, Z6, Z8;
     66   double XP[6], XM[6], YP[6], YM[6];
     67   double MQ[6], PQ[6], MF[6], PF[6];
     68   double D, YF, YPY0, YPY0Q;
     69 
     70   /* Output */
     71   double k = 0;
     72 
     73   int i;
     74   int RG1, RG2, RG3;
     75 
     76   YQ = Y*Y;
     77   YRRTPI = Y*RRTPI;
     78 
     79   if(Y >= 70.55) {
     80     XQ = x*x;
     81     k=YRRTPI/(XQ+YQ);
     82     return k;
     83   }
     84 
     85   RG1 = RG2 = RG3 = 1;
     86 
     87   XLIM0 = sqrt(15100.0 + Y*(40.0 - Y*3.6));
     88   if(Y >= 8.425){
     89     XLIM1 = 0.0;
     90   } else {
     91     XLIM1 = sqrt(164.0 - Y*(4.3 + Y*1.8));
     92   }
     93 
     94   XLIM2 = 6.8-Y;
     95   XLIM3 = 2.4*Y;
     96   XLIM4 = 18.1*Y+1.65;
     97 
     98   if(Y<=1.0e-6) {
     99     XLIM1=XLIM0;
    100     XLIM2=XLIM0;
    101   }
    102 
    103   ABX = sqrt(x*x);
    104   XQ = ABX*ABX;
    105   if(ABX >= XLIM0) {
    106     k = YRRTPI/(XQ + YQ);
    107   } else if (ABX >= XLIM1) {
    108     if(RG1 != 0) {
    109       RG1 = 0;
    110       A0 = YQ + 0.5;
    111       D0 = A0*A0;
    112       D2 = YQ + YQ - 1.0;
    113     }
    114     D = RRTPI/(D0 + XQ*(D2 + XQ));
    115     k = D*Y*(A0 + XQ);
    116 
    117   } else if (ABX > XLIM2) {
    118     if(RG2 != 0) {
    119       RG2 = 0;
    120       H0 = 0.5625 + YQ*(4.5 + YQ*(10.5 + YQ*(6.0 + YQ)));
    121       H2 = -4.5 + YQ*(9.0 + YQ*(6.0 + YQ*4.0));
    122       H4 = 10.5 - YQ*(6.0 - YQ*6.0);
    123       H6 = -6.0 + YQ*4.0;
    124       E0 = 1.875 + YQ*(8.25 + YQ*(5.5+YQ));
    125       E2 = 5.25 + YQ*(1.0 + YQ*3.0);
    126       E4 = 0.75*H6;
    127     }
    128     D = RRTPI/(H0 + XQ*(H2 + XQ*(H4 + XQ*(H6 + XQ))));
    129     k = D*Y*(E0 + XQ*(E2 + XQ*(E4 + XQ)));
    130 
    131   } else if (ABX<XLIM3) {
    132     if(RG3 != 0) {
    133       RG3 = 0;
    134       Z0 = 272.1014
    135          + Y*(1280.829 + Y*(2802.870 + Y*(3764.966
    136          + Y*(3447.629 + Y*(2256.981 + Y*(1074.409
    137          + Y*(369.1989 + Y*(88.26741 + Y*(13.39880 + Y)))))))));
    138       Z2 = 211.678
    139          + Y*(902.3066 + Y*(1758.336 + Y*(2037.310
    140          + Y*(1549.675 + Y*(793.4273 + Y*(266.2987
    141          + Y*(53.59518 + Y*5.0)))))));
    142       Z4 = 78.86585
    143          + Y*(308.1852 + Y*(497.3014 + Y*(479.2576
    144          + Y*(269.2916 + Y*(80.39278 + Y*10.0)))));
    145       Z6 = 22.03523
    146          + Y*(55.02933 + Y*(92.75679 + Y*(53.59518 + Y*10.0)));
    147       Z8 = 1.496460
    148          + Y*(13.39880 + Y*5.0);
    149       P0 = 153.5168
    150          + Y*(549.3954 + Y*(919.4955 + Y*(946.8970
    151          + Y*(662.8097 + Y*(328.2151 + Y*(115.3772
    152          + Y*(27.93941 + Y*(4.264678 + Y*0.3183291))))))));
    153       P2 = -34.16955
    154          + Y*(-1.322256+ Y*(124.5975 + Y*(189.7730
    155          + Y*(139.4665 + Y*(56.81652 + Y*(12.79458 + Y*1.2733163))))));
    156       P4 = 2.584042
    157          + Y*(10.46332 + Y*(24.01655 + Y*(29.81482
    158          + Y*(12.79568 + Y*1.9099744))));
    159       P6 = -0.07272979
    160          + Y*(0.9377051 + Y*(4.266322 + Y*1.273316));
    161       P8 = 0.0005480304
    162          + Y*0.3183291;
    163     }
    164     D = 1.7724538/(Z0 + XQ*(Z2 + XQ*(Z4 + XQ*(Z6 + XQ*(Z8 + XQ)))));
    165     k = D*(P0 + XQ*(P2 + XQ*(P4 + XQ*(P6 + XQ*P8))));
    166 
    167   } else {
    168     YPY0 = Y+Y0;
    169     YPY0Q = YPY0*YPY0;
    170     k=0.0;
    171 
    172     FOR_EACH(i, 0, 6) {
    173       D = x - T[i];
    174       MQ[i] = D*D;
    175       MF[i] = 1.0/(MQ[i] + YPY0Q);
    176       XM[i] = MF[i]*D;
    177       YM[i] = MF[i]*YPY0;
    178 
    179       D = x + T[i];
    180       PQ[i] = D*D;
    181       PF[i] = 1.0/(PQ[i] + YPY0Q);
    182       XP[i] = PF[i]*D;
    183       YP[i] = PF[i]*YPY0;
    184     }
    185 
    186     if(ABX <= XLIM4) {
    187       FOR_EACH(i, 0, 6) {
    188         k = k + C[i]*(YM[i] + YP[i]) - S[i]*(XM[i] - XP[i]);
    189       }
    190     } else {
    191       YF = Y+Y0PY0;
    192       FOR_EACH(i, 0, 6) {
    193         k = k
    194           + (C[i]*(MQ[i]*MF[i] - Y0*YM[i]) + S[i]*YF*XM[i])/(MQ[i] + Y0Q)
    195           + (C[i]*(PQ[i]*PF[i] - Y0*YP[i]) - S[i]*YF*XP[i])/(PQ[i] + Y0Q);
    196       }
    197       k = Y*k + exp(-XQ);
    198     }
    199   }
    200   return k;
    201 }