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 }