Mercurial > octave-libgccjit
comparison liboctave/cruft/Faddeeva/Faddeeva.cc @ 15801:2e30a1aadff2
Merge new upstream Faddeeva release.
* Faddeeva.cc: Use numeric_limits for Inf and NaN, support C11 isnan/isinf,
use gnulib floor and copysign, convert tabs to spaces, slight accuracy
improvements to erf and dawson functions for |z| around 1e-2.
author | Steven G. Johnson <stevenj@alum.mit.edu> |
---|---|
date | Sat, 15 Dec 2012 14:12:47 -0500 |
parents | 2fac72a256ce |
children | 161ebb78ac1b |
comparison
equal
deleted
inserted
replaced
15793:06832c90ae7d | 15801:2e30a1aadff2 |
---|---|
1 // -*- mode:c++; tab-width:2; indent-tabs-mode:nil; -*- | |
2 | |
1 /* Copyright (c) 2012 Massachusetts Institute of Technology | 3 /* Copyright (c) 2012 Massachusetts Institute of Technology |
2 * | 4 * |
3 * Permission is hereby granted, free of charge, to any person obtaining | 5 * Permission is hereby granted, free of charge, to any person obtaining |
4 * a copy of this software and associated documentation files (the | 6 * a copy of this software and associated documentation files (the |
5 * "Software"), to deal in the Software without restriction, including | 7 * "Software"), to deal in the Software without restriction, including |
96 | 98 |
97 REVISION HISTORY: | 99 REVISION HISTORY: |
98 4 October 2012: Initial public release (SGJ) | 100 4 October 2012: Initial public release (SGJ) |
99 5 October 2012: Revised (SGJ) to fix spelling error, | 101 5 October 2012: Revised (SGJ) to fix spelling error, |
100 start summation for large x at round(x/a) (> 1) | 102 start summation for large x at round(x/a) (> 1) |
101 rather than ceil(x/a) as in the original | 103 rather than ceil(x/a) as in the original |
102 paper, which should slightly improve performance | 104 paper, which should slightly improve performance |
103 (and, apparently, slightly improves accuracy) | 105 (and, apparently, slightly improves accuracy) |
104 19 October 2012: Revised (SGJ) to fix bugs for large x, large -y, | 106 19 October 2012: Revised (SGJ) to fix bugs for large x, large -y, |
105 and 15<x<26. Performance improvements. Prototype | 107 and 15<x<26. Performance improvements. Prototype |
106 now supplies default value for relerr. | 108 now supplies default value for relerr. |
107 24 October 2012: Switch to continued-fraction expansion for | 109 24 October 2012: Switch to continued-fraction expansion for |
108 sufficiently large z, for performance reasons. | 110 sufficiently large z, for performance reasons. |
109 Also, avoid spurious overflow for |z| > 1e154. | 111 Also, avoid spurious overflow for |z| > 1e154. |
110 Set relerr argument to min(relerr,0.1). | 112 Set relerr argument to min(relerr,0.1). |
111 27 October 2012: Enhance accuracy in Re[w(z)] taken by itself, | 113 27 October 2012: Enhance accuracy in Re[w(z)] taken by itself, |
112 by switching to Alg. 916 in a region near | 114 by switching to Alg. 916 in a region near |
113 the real-z axis where continued fractions | 115 the real-z axis where continued fractions |
114 have poor relative accuracy in Re[w(z)]. Thanks | 116 have poor relative accuracy in Re[w(z)]. Thanks |
115 to M. Zaghloul for the tip. | 117 to M. Zaghloul for the tip. |
116 29 October 2012: Replace SLATEC-derived erfcx routine with | 118 29 October 2012: Replace SLATEC-derived erfcx routine with |
117 completely rewritten code by me, using a very | 119 completely rewritten code by me, using a very |
118 different algorithm which is much faster. | 120 different algorithm which is much faster. |
119 30 October 2012: Implemented special-case code for real z | 121 30 October 2012: Implemented special-case code for real z |
120 (where real part is exp(-x^2) and imag part is | 122 (where real part is exp(-x^2) and imag part is |
121 Dawson integral), using algorithm similar to erfx. | 123 Dawson integral), using algorithm similar to erfx. |
122 Export ImFaddeeva_w function to make Dawson's | 124 Export ImFaddeeva_w function to make Dawson's |
123 integral directly accessible. | 125 integral directly accessible. |
124 3 November 2012: Provide implementations of erf, erfc, erfcx, | 126 3 November 2012: Provide implementations of erf, erfc, erfcx, |
125 and Dawson functions in Faddeeva:: namespace, | 127 and Dawson functions in Faddeeva:: namespace, |
126 in addition to Faddeeva::w. Provide header | 128 in addition to Faddeeva::w. Provide header |
127 file Faddeeva.hh. | 129 file Faddeeva.hh. |
128 4 November 2012: Slightly faster erf for real arguments. | 130 4 November 2012: Slightly faster erf for real arguments. |
129 Updated MATLAB and Octave plugins. | 131 Updated MATLAB and Octave plugins. |
130 27 November 2012: Support compilation with either C++ or | 132 27 November 2012: Support compilation with either C++ or |
131 plain C (using C99 complex numbers). | 133 plain C (using C99 complex numbers). |
132 For real x, use standard-library erf(x) | 134 For real x, use standard-library erf(x) |
133 and erfc(x) if available (for C99 or C++11). | 135 and erfc(x) if available (for C99 or C++11). |
134 #include "config.h" if HAVE_CONFIG_H is #defined. | 136 #include "config.h" if HAVE_CONFIG_H is #defined. |
137 15 December 2012: Portability fixes (copysign, Inf/NaN creation), | |
138 use CMPLX/__builtin_complex if available in C, | |
139 slight accuracy improvements to erf and dawson | |
140 functions near the origin. Use gnulib functions | |
141 if GNULIB_NAMESPACE is defined. | |
135 */ | 142 */ |
136 | 143 |
137 ///////////////////////////////////////////////////////////////////////// | 144 ///////////////////////////////////////////////////////////////////////// |
138 /* If this file is compiled as a part of a larger project, | 145 /* If this file is compiled as a part of a larger project, |
139 support using an autoconf-style config.h header file | 146 support using an autoconf-style config.h header file |
143 #ifdef HAVE_CONFIG_H | 150 #ifdef HAVE_CONFIG_H |
144 # include "config.h" | 151 # include "config.h" |
145 #endif | 152 #endif |
146 | 153 |
147 ///////////////////////////////////////////////////////////////////////// | 154 ///////////////////////////////////////////////////////////////////////// |
148 // basic math stuff, C++ & C99 compatibility | 155 // macros to allow us to use either C++ or C (with C99 features) |
149 | |
150 #define Inf (1./0.) // infinity | |
151 #define NaN (0./0.) // NaN | |
152 | 156 |
153 #ifdef __cplusplus | 157 #ifdef __cplusplus |
154 | 158 |
155 # include "Faddeeva.hh" | 159 # include "Faddeeva.hh" |
156 | 160 |
157 # include <cfloat> | 161 # include <cfloat> |
158 # include <cmath> | 162 # include <cmath> |
163 # include <limits> | |
159 using namespace std; | 164 using namespace std; |
165 | |
166 // use std::numeric_limits, since 1./0. and 0./0. fail with some compilers (MS) | |
167 # define Inf numeric_limits<double>::infinity() | |
168 # define NaN numeric_limits<double>::quiet_NaN() | |
160 | 169 |
161 typedef complex<double> cmplx; | 170 typedef complex<double> cmplx; |
162 | 171 |
163 // Use C-like complex syntax, since the C syntax is more restrictive | 172 // Use C-like complex syntax, since the C syntax is more restrictive |
164 # define cexp(z) exp(z) | 173 # define cexp(z) exp(z) |
165 # define creal(z) real(z) | 174 # define creal(z) real(z) |
166 # define cimag(z) imag(z) | 175 # define cimag(z) imag(z) |
167 # define cpolar(r,t) polar(r,t) | 176 # define cpolar(r,t) polar(r,t) |
168 | 177 |
169 # define CMPLX(a,b) cmplx(a,b) | 178 # define C(a,b) cmplx(a,b) |
170 | 179 |
171 # define FADDEEVA(name) Faddeeva::name | 180 # define FADDEEVA(name) Faddeeva::name |
172 # define FADDEEVA_RE(name) Faddeeva::name | 181 # define FADDEEVA_RE(name) Faddeeva::name |
173 | 182 |
174 // isnan/isinf were introduced in C++11 | 183 // isnan/isinf were introduced in C++11 |
175 # if (__cplusplus < 201103L) && (!defined(HAVE_ISNAN) || !defined(HAVE_ISINF)) | 184 # if (__cplusplus < 201103L) && (!defined(HAVE_ISNAN) || !defined(HAVE_ISINF)) |
176 static inline bool my_isnan(double x) { return x != x; } | 185 static inline bool my_isnan(double x) { return x != x; } |
177 # define isnan my_isnan | 186 # define isnan my_isnan |
178 static inline bool my_isinf(double x) { return 1/x == 0.; } | 187 static inline bool my_isinf(double x) { return 1/x == 0.; } |
179 # define isinf my_isinf | 188 # define isinf my_isinf |
189 # elif (__cplusplus >= 201103L) | |
190 // g++ gets confused between the C and C++ isnan/isinf functions | |
191 # define isnan std::isnan | |
192 # define isinf std::isinf | |
180 # endif | 193 # endif |
181 | 194 |
195 // copysign was introduced in C++11 (and is also in POSIX and C99) | |
196 # if defined(_WIN32) || defined(__WIN32__) | |
197 # define copysign _copysign // of course MS had to be different | |
198 # elif defined(GNULIB_NAMESPACE) // we are using using gnulib <cmath> | |
199 # define copysign GNULIB_NAMESPACE::copysign | |
200 # elif (__cplusplus < 201103L) && !defined(HAVE_COPYSIGN) && !defined(__linux__) && !(defined(__APPLE__) && defined(__MACH__)) && !defined(_AIX) | |
201 static inline double my_copysign(double x, double y) { return y<0 ? -x : x; } | |
202 # define copysign my_copysign | |
203 # endif | |
204 | |
205 // If we are using the gnulib <cmath> (e.g. in the GNU Octave sources), | |
206 // gnulib generates a link warning if we use ::floor instead of gnulib::floor. | |
207 // This warning is completely innocuous because the only difference between | |
208 // gnulib::floor and the system ::floor (and only on ancient OSF systems) | |
209 // has to do with floor(-0), which doesn't occur in the usage below, but | |
210 // the Octave developers prefer that we silence the warning. | |
211 # ifdef GNULIB_NAMESPACE | |
212 # define floor GNULIB_NAMESPACE::floor | |
213 # endif | |
214 | |
182 #else // !__cplusplus, i.e. pure C (requires C99 features) | 215 #else // !__cplusplus, i.e. pure C (requires C99 features) |
183 | 216 |
184 # include "Faddeeva.h" | 217 # include "Faddeeva.h" |
218 | |
219 # define _GNU_SOURCE // enable GNU libc NAN extension if possible | |
185 | 220 |
186 # include <float.h> | 221 # include <float.h> |
187 # include <math.h> | 222 # include <math.h> |
188 | 223 |
189 typedef double complex cmplx; | 224 typedef double complex cmplx; |
190 | 225 |
191 # define CMPLX(a,b) ((a) + I*(b)) | 226 # define FADDEEVA(name) Faddeeva_ ## name |
227 # define FADDEEVA_RE(name) Faddeeva_ ## name ## _re | |
228 | |
229 /* Constructing complex numbers like 0+i*NaN is problematic in C99 | |
230 without the C11 CMPLX macro, because 0.+I*NAN may give NaN+i*NAN if | |
231 I is a complex (rather than imaginary) constant. For some reason, | |
232 however, it works fine in (pre-4.7) gcc if I define Inf and NaN as | |
233 1/0 and 0/0 (and only if I compile with optimization -O1 or more), | |
234 but not if I use the INFINITY or NAN macros. */ | |
235 | |
236 /* __builtin_complex was introduced in gcc 4.7, but the C11 CMPLX macro | |
237 may not be defined unless we are using a recent (2012) version of | |
238 glibc and compile with -std=c11... note that icc lies about being | |
239 gcc and probably doesn't have this builtin(?), so exclude icc explicitly */ | |
240 # if !defined(CMPLX) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)) && !(defined(__ICC) || defined(__INTEL_COMPILER)) | |
241 # define CMPLX(a,b) __builtin_complex((double) (a), (double) (b)) | |
242 # endif | |
243 | |
244 # ifdef CMPLX // C11 | |
245 # define C(a,b) CMPLX(a,b) | |
246 # define Inf INFINITY // C99 infinity | |
247 # ifdef NAN // GNU libc extension | |
248 # define NaN NAN | |
249 # else | |
250 # define NaN (0./0.) // NaN | |
251 # endif | |
252 # else | |
253 # define C(a,b) ((a) + I*(b)) | |
254 # define Inf (1./0.) | |
255 # define NaN (0./0.) | |
256 # endif | |
192 | 257 |
193 static inline cmplx cpolar(double r, double t) | 258 static inline cmplx cpolar(double r, double t) |
194 { | 259 { |
195 if (r == 0.0 && !isnan(t)) | 260 if (r == 0.0 && !isnan(t)) |
196 return 0.0; | 261 return 0.0; |
197 else | 262 else |
198 return CMPLX(r * cos(t), r * sin(t)); | 263 return C(r * cos(t), r * sin(t)); |
199 } | 264 } |
200 | 265 |
201 # define FADDEEVA(name) Faddeeva_ ## name | 266 #endif // !__cplusplus, i.e. pure C (requires C99 features) |
202 # define FADDEEVA_RE(name) Faddeeva_ ## name ## _re | |
203 | |
204 #endif | |
205 | 267 |
206 ///////////////////////////////////////////////////////////////////////// | 268 ///////////////////////////////////////////////////////////////////////// |
207 // Auxiliary routines to compute other special functions based on w(z) | 269 // Auxiliary routines to compute other special functions based on w(z) |
208 | 270 |
209 // compute erfcx(z) = exp(z^2) erfz(z) | 271 // compute erfcx(z) = exp(z^2) erfz(z) |
210 cmplx FADDEEVA(erfcx)(cmplx z, double relerr) | 272 cmplx FADDEEVA(erfcx)(cmplx z, double relerr) |
211 { | 273 { |
212 return FADDEEVA(w)(CMPLX(-cimag(z), creal(z)), relerr); | 274 return FADDEEVA(w)(C(-cimag(z), creal(z)), relerr); |
213 } | 275 } |
214 | 276 |
215 // compute the error function erf(x) | 277 // compute the error function erf(x) |
216 double FADDEEVA_RE(erf)(double x) | 278 double FADDEEVA_RE(erf)(double x) |
217 { | 279 { |
223 double mx2 = -x*x; | 285 double mx2 = -x*x; |
224 if (mx2 < -750) // underflow | 286 if (mx2 < -750) // underflow |
225 return (x >= 0 ? 1.0 : -1.0); | 287 return (x >= 0 ? 1.0 : -1.0); |
226 | 288 |
227 if (x >= 0) { | 289 if (x >= 0) { |
228 if (x < 5e-3) goto taylor; | 290 if (x < 8e-2) goto taylor; |
229 return 1.0 - exp(mx2) * FADDEEVA_RE(erfcx)(x); | 291 return 1.0 - exp(mx2) * FADDEEVA_RE(erfcx)(x); |
230 } | 292 } |
231 else { // x < 0 | 293 else { // x < 0 |
232 if (x > -5e-3) goto taylor; | 294 if (x > -8e-2) goto taylor; |
233 return exp(mx2) * FADDEEVA_RE(erfcx)(-x) - 1.0; | 295 return exp(mx2) * FADDEEVA_RE(erfcx)(-x) - 1.0; |
234 } | 296 } |
235 | 297 |
236 // Use Taylor series for small |x|, to avoid cancellation inaccuracy | 298 // Use Taylor series for small |x|, to avoid cancellation inaccuracy |
237 // erf(x) = 2/sqrt(pi) * x * (1 - x^2/3 + x^4/10 - ...) | 299 // erf(x) = 2/sqrt(pi) * x * (1 - x^2/3 + x^4/10 - x^6/42 + x^8/216 + ...) |
238 taylor: | 300 taylor: |
239 return x * (1.1283791670955125739 | 301 return x * (1.1283791670955125739 |
240 + mx2 * (0.37612638903183752464 | 302 + mx2 * (0.37612638903183752464 |
241 + mx2 * 0.11283791670955125739)); | 303 + mx2 * (0.11283791670955125739 |
304 + mx2 * (0.026866170645131251760 | |
305 + mx2 * 0.0052239776254421878422)))); | |
242 #endif | 306 #endif |
243 } | 307 } |
244 | 308 |
245 // compute the error function erf(z) | 309 // compute the error function erf(z) |
246 cmplx FADDEEVA(erf)(cmplx z, double relerr) | 310 cmplx FADDEEVA(erf)(cmplx z, double relerr) |
247 { | 311 { |
248 double x = creal(z), y = cimag(z); | 312 double x = creal(z), y = cimag(z); |
249 | 313 |
250 if (y == 0) | 314 if (y == 0) |
251 return CMPLX(FADDEEVA_RE(erf)(x), | 315 return C(FADDEEVA_RE(erf)(x), |
252 y); // preserve sign of 0 | 316 y); // preserve sign of 0 |
253 if (x == 0) // handle separately for speed & handling of y = Inf or NaN | 317 if (x == 0) // handle separately for speed & handling of y = Inf or NaN |
254 return CMPLX(x, // preserve sign of 0 | 318 return C(x, // preserve sign of 0 |
255 /* handle y -> Inf limit manually, since | 319 /* handle y -> Inf limit manually, since |
256 exp(y^2) -> Inf but Im[w(y)] -> 0, so | 320 exp(y^2) -> Inf but Im[w(y)] -> 0, so |
257 IEEE will give us a NaN when it should be Inf */ | 321 IEEE will give us a NaN when it should be Inf */ |
258 y*y > 720 ? (y > 0 ? Inf : -Inf) | 322 y*y > 720 ? (y > 0 ? Inf : -Inf) |
259 : exp(y*y) * FADDEEVA(w_im)(y)); | 323 : exp(y*y) * FADDEEVA(w_im)(y)); |
260 | 324 |
261 double mRe_z2 = (y - x) * (x + y); // Re(-z^2), being careful of overflow | 325 double mRe_z2 = (y - x) * (x + y); // Re(-z^2), being careful of overflow |
262 double mIm_z2 = -2*x*y; // Im(-z^2) | 326 double mIm_z2 = -2*x*y; // Im(-z^2) |
263 if (mRe_z2 < -750) // underflow | 327 if (mRe_z2 < -750) // underflow |
264 return (x >= 0 ? 1.0 : -1.0); | 328 return (x >= 0 ? 1.0 : -1.0); |
265 | 329 |
266 /* Handle positive and negative x via different formulas, | 330 /* Handle positive and negative x via different formulas, |
267 using the mirror symmetries of w, to avoid overflow/underflow | 331 using the mirror symmetries of w, to avoid overflow/underflow |
268 problems from multiplying exponentially large and small quantities. */ | 332 problems from multiplying exponentially large and small quantities. */ |
269 if (x >= 0) { | 333 if (x >= 0) { |
270 if (x < 5e-3) { | 334 if (x < 8e-2) { |
271 if (fabs(y) < 5e-3) | 335 if (fabs(y) < 1e-2) |
272 goto taylor; | 336 goto taylor; |
273 else if (fabs(mIm_z2) < 5e-3) | 337 else if (fabs(mIm_z2) < 5e-3 && x < 5e-3) |
274 goto taylor_erfi; | 338 goto taylor_erfi; |
275 } | 339 } |
276 /* don't use complex exp function, since that will produce spurious NaN | 340 /* don't use complex exp function, since that will produce spurious NaN |
277 values when multiplying w in an overflow situation. */ | 341 values when multiplying w in an overflow situation. */ |
278 return 1.0 - exp(mRe_z2) * | 342 return 1.0 - exp(mRe_z2) * |
279 (CMPLX(cos(mIm_z2), sin(mIm_z2)) | 343 (C(cos(mIm_z2), sin(mIm_z2)) |
280 * FADDEEVA(w)(CMPLX(-y,x), relerr)); | 344 * FADDEEVA(w)(C(-y,x), relerr)); |
281 } | 345 } |
282 else { // x < 0 | 346 else { // x < 0 |
283 if (x > -5e-3) { // duplicate from above to avoid fabs(x) call | 347 if (x > -8e-2) { // duplicate from above to avoid fabs(x) call |
284 if (fabs(y) < 5e-3) | 348 if (fabs(y) < 1e-2) |
285 goto taylor; | 349 goto taylor; |
286 else if (fabs(mIm_z2) < 5e-3) | 350 else if (fabs(mIm_z2) < 5e-3 && x > -5e-3) |
287 goto taylor_erfi; | 351 goto taylor_erfi; |
288 } | 352 } |
289 else if (isnan(x)) | 353 else if (isnan(x)) |
290 return CMPLX(NaN, y == 0 ? 0 : NaN); | 354 return C(NaN, y == 0 ? 0 : NaN); |
291 /* don't use complex exp function, since that will produce spurious NaN | 355 /* don't use complex exp function, since that will produce spurious NaN |
292 values when multiplying w in an overflow situation. */ | 356 values when multiplying w in an overflow situation. */ |
293 return exp(mRe_z2) * | 357 return exp(mRe_z2) * |
294 (CMPLX(cos(mIm_z2), sin(mIm_z2)) | 358 (C(cos(mIm_z2), sin(mIm_z2)) |
295 * FADDEEVA(w)(CMPLX(y,-x), relerr)) - 1.0; | 359 * FADDEEVA(w)(C(y,-x), relerr)) - 1.0; |
296 } | 360 } |
297 | 361 |
298 // Use Taylor series for small |z|, to avoid cancellation inaccuracy | 362 // Use Taylor series for small |z|, to avoid cancellation inaccuracy |
299 // erf(z) = 2/sqrt(pi) * z * (1 - z^2/3 + z^4/10 - ...) | 363 // erf(z) = 2/sqrt(pi) * z * (1 - z^2/3 + z^4/10 - z^6/42 + z^8/216 + ...) |
300 taylor: | 364 taylor: |
301 { | 365 { |
302 cmplx mz2 = CMPLX(mRe_z2, mIm_z2); // -z^2 | 366 cmplx mz2 = C(mRe_z2, mIm_z2); // -z^2 |
303 return z * (1.1283791670955125739 | 367 return z * (1.1283791670955125739 |
304 + mz2 * (0.37612638903183752464 | 368 + mz2 * (0.37612638903183752464 |
305 + mz2 * 0.11283791670955125739)); | 369 + mz2 * (0.11283791670955125739 |
370 + mz2 * (0.026866170645131251760 | |
371 + mz2 * 0.0052239776254421878422)))); | |
306 } | 372 } |
307 | 373 |
308 /* for small |x| and small |xy|, | 374 /* for small |x| and small |xy|, |
309 use Taylor series to avoid cancellation inaccuracy: | 375 use Taylor series to avoid cancellation inaccuracy: |
310 erf(x+iy) = erf(iy) | 376 erf(x+iy) = erf(iy) |
311 + 2*exp(y^2)/sqrt(pi) * | 377 + 2*exp(y^2)/sqrt(pi) * |
312 [ x * (1 - x^2 * (1+2y^2)/3 + x^4 * (3+12y^2+4y^4)/30 + ... | 378 [ x * (1 - x^2 * (1+2y^2)/3 + x^4 * (3+12y^2+4y^4)/30 + ... |
313 - i * x^2 * y * (1 - x^2 * (3+2y^2)/6 + ...) ] | 379 - i * x^2 * y * (1 - x^2 * (3+2y^2)/6 + ...) ] |
314 where: | 380 where: |
315 erf(iy) = exp(y^2) * Im[w(y)] | 381 erf(iy) = exp(y^2) * Im[w(y)] |
316 */ | 382 */ |
317 taylor_erfi: | 383 taylor_erfi: |
318 { | 384 { |
319 double x2 = x*x, y2 = y*y; | 385 double x2 = x*x, y2 = y*y; |
320 double expy2 = exp(y2); | 386 double expy2 = exp(y2); |
321 return CMPLX | 387 return C |
322 (expy2 * x * (1.1283791670955125739 | 388 (expy2 * x * (1.1283791670955125739 |
323 - x2 * (0.37612638903183752464 | 389 - x2 * (0.37612638903183752464 |
324 + 0.75225277806367504925*y2) | 390 + 0.75225277806367504925*y2) |
325 + x2*x2 * (0.11283791670955125739 | 391 + x2*x2 * (0.11283791670955125739 |
326 + y2 * (0.45135166683820502956 | 392 + y2 * (0.45135166683820502956 |
327 + 0.15045055561273500986*y2))), | 393 + 0.15045055561273500986*y2))), |
328 expy2 * (FADDEEVA(w_im)(y) | 394 expy2 * (FADDEEVA(w_im)(y) |
329 - x2*y * (1.1283791670955125739 | 395 - x2*y * (1.1283791670955125739 |
330 - x2 * (0.56418958354775628695 | 396 - x2 * (0.56418958354775628695 |
331 + 0.37612638903183752464*y2)))); | 397 + 0.37612638903183752464*y2)))); |
332 } | 398 } |
333 } | 399 } |
334 | 400 |
335 // erfi(z) = -i erf(iz) | 401 // erfi(z) = -i erf(iz) |
336 cmplx FADDEEVA(erfi)(cmplx z, double relerr) | 402 cmplx FADDEEVA(erfi)(cmplx z, double relerr) |
337 { | 403 { |
338 cmplx e = FADDEEVA(erf)(CMPLX(-cimag(z),creal(z)), relerr); | 404 cmplx e = FADDEEVA(erf)(C(-cimag(z),creal(z)), relerr); |
339 return CMPLX(cimag(e), -creal(e)); | 405 return C(cimag(e), -creal(e)); |
340 } | 406 } |
341 | 407 |
342 // erfi(x) = -i erf(ix) | 408 // erfi(x) = -i erf(ix) |
343 double FADDEEVA_RE(erfi)(double x) | 409 double FADDEEVA_RE(erfi)(double x) |
344 { | 410 { |
365 cmplx FADDEEVA(erfc)(cmplx z, double relerr) | 431 cmplx FADDEEVA(erfc)(cmplx z, double relerr) |
366 { | 432 { |
367 double x = creal(z), y = cimag(z); | 433 double x = creal(z), y = cimag(z); |
368 | 434 |
369 if (x == 0.) | 435 if (x == 0.) |
370 return CMPLX(1, | 436 return C(1, |
371 /* handle y -> Inf limit manually, since | 437 /* handle y -> Inf limit manually, since |
372 exp(y^2) -> Inf but Im[w(y)] -> 0, so | 438 exp(y^2) -> Inf but Im[w(y)] -> 0, so |
373 IEEE will give us a NaN when it should be Inf */ | 439 IEEE will give us a NaN when it should be Inf */ |
374 y*y > 720 ? (y > 0 ? -Inf : Inf) | 440 y*y > 720 ? (y > 0 ? -Inf : Inf) |
375 : -exp(y*y) * FADDEEVA(w_im)(y)); | 441 : -exp(y*y) * FADDEEVA(w_im)(y)); |
376 if (y == 0.) { | 442 if (y == 0.) { |
377 if (x*x > 750) // underflow | 443 if (x*x > 750) // underflow |
378 return CMPLX(x >= 0 ? 0.0 : 2.0, | 444 return C(x >= 0 ? 0.0 : 2.0, |
379 -y); // preserve sign of 0 | 445 -y); // preserve sign of 0 |
380 return CMPLX(x >= 0 ? exp(-x*x) * FADDEEVA_RE(erfcx)(x) | 446 return C(x >= 0 ? exp(-x*x) * FADDEEVA_RE(erfcx)(x) |
381 : 2. - exp(-x*x) * FADDEEVA_RE(erfcx)(-x), | 447 : 2. - exp(-x*x) * FADDEEVA_RE(erfcx)(-x), |
382 -y); // preserve sign of zero | 448 -y); // preserve sign of zero |
383 } | 449 } |
384 | 450 |
385 double mRe_z2 = (y - x) * (x + y); // Re(-z^2), being careful of overflow | 451 double mRe_z2 = (y - x) * (x + y); // Re(-z^2), being careful of overflow |
386 double mIm_z2 = -2*x*y; // Im(-z^2) | 452 double mIm_z2 = -2*x*y; // Im(-z^2) |
387 if (mRe_z2 < -750) // underflow | 453 if (mRe_z2 < -750) // underflow |
388 return (x >= 0 ? 0.0 : 2.0); | 454 return (x >= 0 ? 0.0 : 2.0); |
389 | 455 |
390 if (x >= 0) | 456 if (x >= 0) |
391 return cexp(CMPLX(mRe_z2, mIm_z2)) | 457 return cexp(C(mRe_z2, mIm_z2)) |
392 * FADDEEVA(w)(CMPLX(-y,x), relerr); | 458 * FADDEEVA(w)(C(-y,x), relerr); |
393 else | 459 else |
394 return 2.0 - cexp(CMPLX(mRe_z2, mIm_z2)) | 460 return 2.0 - cexp(C(mRe_z2, mIm_z2)) |
395 * FADDEEVA(w)(CMPLX(y,-x), relerr); | 461 * FADDEEVA(w)(C(y,-x), relerr); |
396 } | 462 } |
397 | 463 |
398 // compute Dawson(x) = sqrt(pi)/2 * exp(-x^2) * erfi(x) | 464 // compute Dawson(x) = sqrt(pi)/2 * exp(-x^2) * erfi(x) |
399 double FADDEEVA_RE(Dawson)(double x) | 465 double FADDEEVA_RE(Dawson)(double x) |
400 { | 466 { |
408 const double spi2 = 0.8862269254527580136490837416705725913990; // sqrt(pi)/2 | 474 const double spi2 = 0.8862269254527580136490837416705725913990; // sqrt(pi)/2 |
409 double x = creal(z), y = cimag(z); | 475 double x = creal(z), y = cimag(z); |
410 | 476 |
411 // handle axes separately for speed & proper handling of x or y = Inf or NaN | 477 // handle axes separately for speed & proper handling of x or y = Inf or NaN |
412 if (y == 0) | 478 if (y == 0) |
413 return CMPLX(spi2 * FADDEEVA(w_im)(x), | 479 return C(spi2 * FADDEEVA(w_im)(x), |
414 -y); // preserve sign of 0 | 480 -y); // preserve sign of 0 |
415 if (x == 0) { | 481 if (x == 0) { |
416 double y2 = y*y; | 482 double y2 = y*y; |
417 if (y2 < 2.5e-5) { // Taylor expansion | 483 if (y2 < 2.5e-5) { // Taylor expansion |
418 return CMPLX(x, // preserve sign of 0 | 484 return C(x, // preserve sign of 0 |
419 y * (1. | 485 y * (1. |
420 + y2 * (0.6666666666666666666666666666666666666667 | 486 + y2 * (0.6666666666666666666666666666666666666667 |
421 + y2 * 0.2666666666666666666666666666666666666667))); | 487 + y2 * 0.26666666666666666666666666666666666667))); |
422 } | 488 } |
423 return CMPLX(x, // preserve sign of 0 | 489 return C(x, // preserve sign of 0 |
424 spi2 * (y >= 0 | 490 spi2 * (y >= 0 |
425 ? exp(y2) - FADDEEVA_RE(erfcx)(y) | 491 ? exp(y2) - FADDEEVA_RE(erfcx)(y) |
426 : FADDEEVA_RE(erfcx)(-y) - exp(y2))); | 492 : FADDEEVA_RE(erfcx)(-y) - exp(y2))); |
427 } | 493 } |
428 | 494 |
429 double mRe_z2 = (y - x) * (x + y); // Re(-z^2), being careful of overflow | 495 double mRe_z2 = (y - x) * (x + y); // Re(-z^2), being careful of overflow |
430 double mIm_z2 = -2*x*y; // Im(-z^2) | 496 double mIm_z2 = -2*x*y; // Im(-z^2) |
431 cmplx mz2 = CMPLX(mRe_z2, mIm_z2); // -z^2 | 497 cmplx mz2 = C(mRe_z2, mIm_z2); // -z^2 |
432 | 498 |
433 /* Handle positive and negative x via different formulas, | 499 /* Handle positive and negative x via different formulas, |
434 using the mirror symmetries of w, to avoid overflow/underflow | 500 using the mirror symmetries of w, to avoid overflow/underflow |
435 problems from multiplying exponentially large and small quantities. */ | 501 problems from multiplying exponentially large and small quantities. */ |
436 if (y >= 0) { | 502 if (y >= 0) { |
437 if (y < 5e-3) { | 503 if (y < 5e-3) { |
438 if (fabs(x) < 5e-3) | 504 if (fabs(x) < 5e-3) |
439 goto taylor; | 505 goto taylor; |
440 else if (fabs(mIm_z2) < 5e-3) | 506 else if (fabs(mIm_z2) < 5e-3) |
441 goto taylor_realaxis; | 507 goto taylor_realaxis; |
442 } | 508 } |
443 cmplx res = cexp(mz2) - FADDEEVA(w)(z, relerr); | 509 cmplx res = cexp(mz2) - FADDEEVA(w)(z, relerr); |
444 return spi2 * CMPLX(-cimag(res), creal(res)); | 510 return spi2 * C(-cimag(res), creal(res)); |
445 } | 511 } |
446 else { // y < 0 | 512 else { // y < 0 |
447 if (y > -5e-3) { // duplicate from above to avoid fabs(x) call | 513 if (y > -5e-3) { // duplicate from above to avoid fabs(x) call |
448 if (fabs(x) < 5e-3) | 514 if (fabs(x) < 5e-3) |
449 goto taylor; | 515 goto taylor; |
450 else if (fabs(mIm_z2) < 5e-3) | 516 else if (fabs(mIm_z2) < 5e-3) |
451 goto taylor_realaxis; | 517 goto taylor_realaxis; |
452 } | 518 } |
453 else if (isnan(y)) | 519 else if (isnan(y)) |
454 return CMPLX(x == 0 ? 0 : NaN, NaN); | 520 return C(x == 0 ? 0 : NaN, NaN); |
455 cmplx res = FADDEEVA(w)(-z, relerr) - cexp(mz2); | 521 cmplx res = FADDEEVA(w)(-z, relerr) - cexp(mz2); |
456 return spi2 * CMPLX(-cimag(res), creal(res)); | 522 return spi2 * C(-cimag(res), creal(res)); |
457 } | 523 } |
458 | 524 |
459 // Use Taylor series for small |z|, to avoid cancellation inaccuracy | 525 // Use Taylor series for small |z|, to avoid cancellation inaccuracy |
460 // dawson(z) = z - 2/3 z^3 + 4/15 z^5 + ... | 526 // dawson(z) = z - 2/3 z^3 + 4/15 z^5 + ... |
461 taylor: | 527 taylor: |
462 return z * (1. | 528 return z * (1. |
463 + mz2 * (0.6666666666666666666666666666666666666667 | 529 + mz2 * (0.6666666666666666666666666666666666666667 |
464 + mz2 * 0.2666666666666666666666666666666666666667)); | 530 + mz2 * 0.2666666666666666666666666666666666666667)); |
465 | 531 |
466 /* for small |y| and small |xy|, | 532 /* for small |y| and small |xy|, |
467 use Taylor series to avoid cancellation inaccuracy: | 533 use Taylor series to avoid cancellation inaccuracy: |
468 dawson(x + iy) | 534 dawson(x + iy) |
469 = D + y^2 (D + x - 2Dx^2) | 535 = D + y^2 (D + x - 2Dx^2) |
500 { | 566 { |
501 double x2 = x*x; | 567 double x2 = x*x; |
502 if (x2 > 1600) { // |x| > 40 | 568 if (x2 > 1600) { // |x| > 40 |
503 double y2 = y*y; | 569 double y2 = y*y; |
504 if (x2 > 25e14) {// |x| > 5e7 | 570 if (x2 > 25e14) {// |x| > 5e7 |
505 double xy2 = (x*y)*(x*y); | 571 double xy2 = (x*y)*(x*y); |
506 return CMPLX((0.5 + y2 * (0.5 + 0.25*y2 | 572 return C((0.5 + y2 * (0.5 + 0.25*y2 |
507 - 0.16666666666666666667*xy2)) / x, | 573 - 0.16666666666666666667*xy2)) / x, |
508 y * (-1 + y2 * (-0.66666666666666666667 | 574 y * (-1 + y2 * (-0.66666666666666666667 |
509 + 0.13333333333333333333*xy2 | 575 + 0.13333333333333333333*xy2 |
510 - 0.26666666666666666667*y2)) | 576 - 0.26666666666666666667*y2)) |
511 / (2*x2 - 1)); | 577 / (2*x2 - 1)); |
512 } | 578 } |
513 return (1. / (-15 + x2*(90 + x2*(-60 + 8*x2)))) * | 579 return (1. / (-15 + x2*(90 + x2*(-60 + 8*x2)))) * |
514 CMPLX(x * (33 + x2 * (-28 + 4*x2) | 580 C(x * (33 + x2 * (-28 + 4*x2) |
515 + y2 * (18 - 4*x2 + 4*y2)), | 581 + y2 * (18 - 4*x2 + 4*y2)), |
516 y * (-15 + x2 * (24 - 4*x2) | 582 y * (-15 + x2 * (24 - 4*x2) |
517 + y2 * (4*x2 - 10 - 4*y2))); | 583 + y2 * (4*x2 - 10 - 4*y2))); |
518 } | 584 } |
519 else { | 585 else { |
520 double D = spi2 * FADDEEVA(w_im)(x); | 586 double D = spi2 * FADDEEVA(w_im)(x); |
521 double x2 = x*x, y2 = y*y; | 587 double x2 = x*x, y2 = y*y; |
522 return CMPLX | 588 return C |
523 (D + y2 * (D + x - 2*D*x2) | 589 (D + y2 * (D + x - 2*D*x2) |
524 + y2*y2 * (D * (0.5 - x2 * (2 - 0.66666666666666666667*x2)) | 590 + y2*y2 * (D * (0.5 - x2 * (2 - 0.66666666666666666667*x2)) |
525 + x * (0.83333333333333333333 | 591 + x * (0.83333333333333333333 |
526 - 0.33333333333333333333 * x2)), | 592 - 0.33333333333333333333 * x2)), |
527 y * (1 - 2*D*x | 593 y * (1 - 2*D*x |
528 + y2 * 0.66666666666666666667 * (1 - x2 - D*x * (3 - 2*x2)) | 594 + y2 * 0.66666666666666666667 * (1 - x2 - D*x * (3 - 2*x2)) |
529 + y2*y2 * (0.26666666666666666667 - | 595 + y2*y2 * (0.26666666666666666667 - |
530 x2 * (0.6 - 0.13333333333333333333 * x2) | 596 x2 * (0.6 - 0.13333333333333333333 * x2) |
531 - D*x * (1 - x2 * (1.3333333333333333333 | 597 - D*x * (1 - x2 * (1.3333333333333333333 |
532 - 0.26666666666666666667 * x2))))); | 598 - 0.26666666666666666667 * x2))))); |
533 } | 599 } |
534 } | 600 } |
535 } | 601 } |
536 | 602 |
537 ///////////////////////////////////////////////////////////////////////// | 603 ///////////////////////////////////////////////////////////////////////// |
543 } | 609 } |
544 | 610 |
545 // sinh(x) via Taylor series, accurate to machine precision for |x| < 1e-2 | 611 // sinh(x) via Taylor series, accurate to machine precision for |x| < 1e-2 |
546 static inline double sinh_taylor(double x) { | 612 static inline double sinh_taylor(double x) { |
547 return x * (1 + (x*x) * (0.1666666666666666666667 | 613 return x * (1 + (x*x) * (0.1666666666666666666667 |
548 + 0.00833333333333333333333 * (x*x))); | 614 + 0.00833333333333333333333 * (x*x))); |
549 } | 615 } |
550 | 616 |
551 static inline double sqr(double x) { return x*x; } | 617 static inline double sqr(double x) { return x*x; } |
552 | 618 |
553 // precomputed table of expa2n2[n-1] = exp(-a2*n*n) | 619 // precomputed table of expa2n2[n-1] = exp(-a2*n*n) |
610 ///////////////////////////////////////////////////////////////////////// | 676 ///////////////////////////////////////////////////////////////////////// |
611 | 677 |
612 cmplx FADDEEVA(w)(cmplx z, double relerr) | 678 cmplx FADDEEVA(w)(cmplx z, double relerr) |
613 { | 679 { |
614 if (creal(z) == 0.0) | 680 if (creal(z) == 0.0) |
615 return CMPLX(FADDEEVA_RE(erfcx)(cimag(z)), | 681 return C(FADDEEVA_RE(erfcx)(cimag(z)), |
616 creal(z)); // give correct sign of 0 in cimag(w) | 682 creal(z)); // give correct sign of 0 in cimag(w) |
617 else if (cimag(z) == 0) | 683 else if (cimag(z) == 0) |
618 return CMPLX(exp(-sqr(creal(z))), | 684 return C(exp(-sqr(creal(z))), |
619 FADDEEVA(w_im)(creal(z))); | 685 FADDEEVA(w_im)(creal(z))); |
620 | 686 |
621 double a, a2, c; | 687 double a, a2, c; |
622 if (relerr <= DBL_EPSILON) { | 688 if (relerr <= DBL_EPSILON) { |
623 relerr = DBL_EPSILON; | 689 relerr = DBL_EPSILON; |
624 a = 0.518321480430085929872; // pi / sqrt(-log(eps*0.5)) | 690 a = 0.518321480430085929872; // pi / sqrt(-log(eps*0.5)) |
641 | 707 |
642 #define USE_CONTINUED_FRACTION 1 // 1 to use continued fraction for large |z| | 708 #define USE_CONTINUED_FRACTION 1 // 1 to use continued fraction for large |z| |
643 | 709 |
644 #if USE_CONTINUED_FRACTION | 710 #if USE_CONTINUED_FRACTION |
645 if (ya > 7 || (x > 6 // continued fraction is faster | 711 if (ya > 7 || (x > 6 // continued fraction is faster |
646 /* As pointed out by M. Zaghloul, the continued | 712 /* As pointed out by M. Zaghloul, the continued |
647 fraction seems to give a large relative error in | 713 fraction seems to give a large relative error in |
648 Re w(z) for |x| ~ 6 and small |y|, so use | 714 Re w(z) for |x| ~ 6 and small |y|, so use |
649 algorithm 816 in this region: */ | 715 algorithm 816 in this region: */ |
650 && (ya > 0.1 || (x > 8 && ya > 1e-10) || x > 28))) { | 716 && (ya > 0.1 || (x > 8 && ya > 1e-10) || x > 28))) { |
651 | 717 |
652 /* Poppe & Wijers suggest using a number of terms | 718 /* Poppe & Wijers suggest using a number of terms |
653 nu = 3 + 1442 / (26*rho + 77) | 719 nu = 3 + 1442 / (26*rho + 77) |
654 where rho = sqrt((x/x0)^2 + (y/y0)^2) where x0=6.3, y0=4.4. | 720 where rho = sqrt((x/x0)^2 + (y/y0)^2) where x0=6.3, y0=4.4. |
655 (They only use this expansion for rho >= 1, but rho a little less | 721 (They only use this expansion for rho >= 1, but rho a little less |
661 I also separate the regions where nu == 2 and nu == 1. */ | 727 I also separate the regions where nu == 2 and nu == 1. */ |
662 const double ispi = 0.56418958354775628694807945156; // 1 / sqrt(pi) | 728 const double ispi = 0.56418958354775628694807945156; // 1 / sqrt(pi) |
663 double xs = y < 0 ? -creal(z) : creal(z); // compute for -z if y < 0 | 729 double xs = y < 0 ? -creal(z) : creal(z); // compute for -z if y < 0 |
664 if (x + ya > 4000) { // nu <= 2 | 730 if (x + ya > 4000) { // nu <= 2 |
665 if (x + ya > 1e7) { // nu == 1, w(z) = i/sqrt(pi) / z | 731 if (x + ya > 1e7) { // nu == 1, w(z) = i/sqrt(pi) / z |
666 // scale to avoid overflow | 732 // scale to avoid overflow |
667 if (x > ya) { | 733 if (x > ya) { |
668 double yax = ya / xs; | 734 double yax = ya / xs; |
669 double denom = ispi / (xs + yax*ya); | 735 double denom = ispi / (xs + yax*ya); |
670 ret = CMPLX(denom*yax, denom); | 736 ret = C(denom*yax, denom); |
671 } | 737 } |
672 else if (isinf(ya)) | 738 else if (isinf(ya)) |
673 return ((isnan(x) || y < 0) | 739 return ((isnan(x) || y < 0) |
674 ? CMPLX(NaN,NaN) : CMPLX(0,0)); | 740 ? C(NaN,NaN) : C(0,0)); |
675 else { | 741 else { |
676 double xya = xs / ya; | 742 double xya = xs / ya; |
677 double denom = ispi / (xya*xs + ya); | 743 double denom = ispi / (xya*xs + ya); |
678 ret = CMPLX(denom, denom*xya); | 744 ret = C(denom, denom*xya); |
679 } | 745 } |
680 } | 746 } |
681 else { // nu == 2, w(z) = i/sqrt(pi) * z / (z*z - 0.5) | 747 else { // nu == 2, w(z) = i/sqrt(pi) * z / (z*z - 0.5) |
682 double dr = xs*xs - ya*ya - 0.5, di = 2*xs*ya; | 748 double dr = xs*xs - ya*ya - 0.5, di = 2*xs*ya; |
683 double denom = ispi / (dr*dr + di*di); | 749 double denom = ispi / (dr*dr + di*di); |
684 ret = CMPLX(denom * (xs*di-ya*dr), denom * (xs*dr+ya*di)); | 750 ret = C(denom * (xs*di-ya*dr), denom * (xs*dr+ya*di)); |
685 } | 751 } |
686 } | 752 } |
687 else { // compute nu(z) estimate and do general continued fraction | 753 else { // compute nu(z) estimate and do general continued fraction |
688 const double c0=3.9, c1=11.398, c2=0.08254, c3=0.1421, c4=0.2023; // fit | 754 const double c0=3.9, c1=11.398, c2=0.08254, c3=0.1421, c4=0.2023; // fit |
689 double nu = floor(c0 + c1 / (c2*x + c3*ya + c4)); | 755 double nu = floor(c0 + c1 / (c2*x + c3*ya + c4)); |
690 double wr = xs, wi = ya; | 756 double wr = xs, wi = ya; |
691 for (nu = 0.5 * (nu - 1); nu > 0.4; nu -= 0.5) { | 757 for (nu = 0.5 * (nu - 1); nu > 0.4; nu -= 0.5) { |
692 // w <- z - nu/w: | 758 // w <- z - nu/w: |
693 double denom = nu / (wr*wr + wi*wi); | 759 double denom = nu / (wr*wr + wi*wi); |
694 wr = xs - wr * denom; | 760 wr = xs - wr * denom; |
695 wi = ya + wi * denom; | 761 wi = ya + wi * denom; |
696 } | 762 } |
697 { // w(z) = i/sqrt(pi) / w: | 763 { // w(z) = i/sqrt(pi) / w: |
698 double denom = ispi / (wr*wr + wi*wi); | 764 double denom = ispi / (wr*wr + wi*wi); |
699 ret = CMPLX(denom*wi, denom*wr); | 765 ret = C(denom*wi, denom*wr); |
700 } | 766 } |
701 } | 767 } |
702 if (y < 0) { | 768 if (y < 0) { |
703 // use w(z) = 2.0*exp(-z*z) - w(-z), | 769 // use w(z) = 2.0*exp(-z*z) - w(-z), |
704 // but be careful of overflow in exp(-z*z) | 770 // but be careful of overflow in exp(-z*z) |
705 // = exp(-(xs*xs-ya*ya) -2*i*xs*ya) | 771 // = exp(-(xs*xs-ya*ya) -2*i*xs*ya) |
706 return 2.0*cexp(CMPLX((ya-xs)*(xs+ya), 2*xs*y)) - ret; | 772 return 2.0*cexp(C((ya-xs)*(xs+ya), 2*xs*y)) - ret; |
707 } | 773 } |
708 else | 774 else |
709 return ret; | 775 return ret; |
710 } | 776 } |
711 #else // !USE_CONTINUED_FRACTION | 777 #else // !USE_CONTINUED_FRACTION |
714 double xs = y < 0 ? -creal(z) : creal(z); // compute for -z if y < 0 | 780 double xs = y < 0 ? -creal(z) : creal(z); // compute for -z if y < 0 |
715 // scale to avoid overflow | 781 // scale to avoid overflow |
716 if (x > ya) { | 782 if (x > ya) { |
717 double yax = ya / xs; | 783 double yax = ya / xs; |
718 double denom = ispi / (xs + yax*ya); | 784 double denom = ispi / (xs + yax*ya); |
719 ret = CMPLX(denom*yax, denom); | 785 ret = C(denom*yax, denom); |
720 } | 786 } |
721 else { | 787 else { |
722 double xya = xs / ya; | 788 double xya = xs / ya; |
723 double denom = ispi / (xya*xs + ya); | 789 double denom = ispi / (xya*xs + ya); |
724 ret = CMPLX(denom, denom*xya); | 790 ret = C(denom, denom*xya); |
725 } | 791 } |
726 if (y < 0) { | 792 if (y < 0) { |
727 // use w(z) = 2.0*exp(-z*z) - w(-z), | 793 // use w(z) = 2.0*exp(-z*z) - w(-z), |
728 // but be careful of overflow in exp(-z*z) | 794 // but be careful of overflow in exp(-z*z) |
729 // = exp(-(xs*xs-ya*ya) -2*i*xs*ya) | 795 // = exp(-(xs*xs-ya*ya) -2*i*xs*ya) |
730 return 2.0*cexp(CMPLX((ya-xs)*(xs+ya), 2*xs*y)) - ret; | 796 return 2.0*cexp(C((ya-xs)*(xs+ya), 2*xs*y)) - ret; |
731 } | 797 } |
732 else | 798 else |
733 return ret; | 799 return ret; |
734 } | 800 } |
735 #endif // !USE_CONTINUED_FRACTION | 801 #endif // !USE_CONTINUED_FRACTION |
749 else if (x < 10) { | 815 else if (x < 10) { |
750 double prod2ax = 1, prodm2ax = 1; | 816 double prod2ax = 1, prodm2ax = 1; |
751 double expx2; | 817 double expx2; |
752 | 818 |
753 if (isnan(y)) | 819 if (isnan(y)) |
754 return CMPLX(y,y); | 820 return C(y,y); |
755 | 821 |
756 /* Somewhat ugly copy-and-paste duplication here, but I see significant | 822 /* Somewhat ugly copy-and-paste duplication here, but I see significant |
757 speedups from using the special-case code with the precomputed | 823 speedups from using the special-case code with the precomputed |
758 exponential, and the x < 5e-4 special case is needed for accuracy. */ | 824 exponential, and the x < 5e-4 special case is needed for accuracy. */ |
759 | 825 |
760 if (relerr == DBL_EPSILON) { // use precomputed exp(-a2*(n*n)) table | 826 if (relerr == DBL_EPSILON) { // use precomputed exp(-a2*(n*n)) table |
761 if (x < 5e-4) { // compute sum4 and sum5 together as sum5-sum4 | 827 if (x < 5e-4) { // compute sum4 and sum5 together as sum5-sum4 |
762 const double x2 = x*x; | 828 const double x2 = x*x; |
763 expx2 = 1 - x2 * (1 - 0.5*x2); // exp(-x*x) via Taylor | 829 expx2 = 1 - x2 * (1 - 0.5*x2); // exp(-x*x) via Taylor |
764 // compute exp(2*a*x) and exp(-2*a*x) via Taylor, to double precision | 830 // compute exp(2*a*x) and exp(-2*a*x) via Taylor, to double precision |
765 const double ax2 = 1.036642960860171859744*x; // 2*a*x | 831 const double ax2 = 1.036642960860171859744*x; // 2*a*x |
766 const double exp2ax = | 832 const double exp2ax = |
767 1 + ax2 * (1 + ax2 * (0.5 + 0.166666666666666666667*ax2)); | 833 1 + ax2 * (1 + ax2 * (0.5 + 0.166666666666666666667*ax2)); |
768 const double expm2ax = | 834 const double expm2ax = |
769 1 - ax2 * (1 - ax2 * (0.5 - 0.166666666666666666667*ax2)); | 835 1 - ax2 * (1 - ax2 * (0.5 - 0.166666666666666666667*ax2)); |
770 for (int n = 1; 1; ++n) { | 836 for (int n = 1; 1; ++n) { |
771 const double coef = expa2n2[n-1] * expx2 / (a2*(n*n) + y*y); | 837 const double coef = expa2n2[n-1] * expx2 / (a2*(n*n) + y*y); |
772 prod2ax *= exp2ax; | 838 prod2ax *= exp2ax; |
773 prodm2ax *= expm2ax; | 839 prodm2ax *= expm2ax; |
774 sum1 += coef; | 840 sum1 += coef; |
775 sum2 += coef * prodm2ax; | 841 sum2 += coef * prodm2ax; |
776 sum3 += coef * prod2ax; | 842 sum3 += coef * prod2ax; |
777 | 843 |
778 // really = sum5 - sum4 | 844 // really = sum5 - sum4 |
779 sum5 += coef * (2*a) * n * sinh_taylor((2*a)*n*x); | 845 sum5 += coef * (2*a) * n * sinh_taylor((2*a)*n*x); |
780 | 846 |
781 // test convergence via sum3 | 847 // test convergence via sum3 |
782 if (coef * prod2ax < relerr * sum3) break; | 848 if (coef * prod2ax < relerr * sum3) break; |
783 } | 849 } |
784 } | 850 } |
785 else { // x > 5e-4, compute sum4 and sum5 separately | 851 else { // x > 5e-4, compute sum4 and sum5 separately |
786 expx2 = exp(-x*x); | 852 expx2 = exp(-x*x); |
787 const double exp2ax = exp((2*a)*x), expm2ax = 1 / exp2ax; | 853 const double exp2ax = exp((2*a)*x), expm2ax = 1 / exp2ax; |
788 for (int n = 1; 1; ++n) { | 854 for (int n = 1; 1; ++n) { |
789 const double coef = expa2n2[n-1] * expx2 / (a2*(n*n) + y*y); | 855 const double coef = expa2n2[n-1] * expx2 / (a2*(n*n) + y*y); |
790 prod2ax *= exp2ax; | 856 prod2ax *= exp2ax; |
791 prodm2ax *= expm2ax; | 857 prodm2ax *= expm2ax; |
792 sum1 += coef; | 858 sum1 += coef; |
793 sum2 += coef * prodm2ax; | 859 sum2 += coef * prodm2ax; |
794 sum4 += (coef * prodm2ax) * (a*n); | 860 sum4 += (coef * prodm2ax) * (a*n); |
795 sum3 += coef * prod2ax; | 861 sum3 += coef * prod2ax; |
796 sum5 += (coef * prod2ax) * (a*n); | 862 sum5 += (coef * prod2ax) * (a*n); |
797 // test convergence via sum5, since this sum has the slowest decay | 863 // test convergence via sum5, since this sum has the slowest decay |
798 if ((coef * prod2ax) * (a*n) < relerr * sum5) break; | 864 if ((coef * prod2ax) * (a*n) < relerr * sum5) break; |
799 } | 865 } |
800 } | 866 } |
801 } | 867 } |
802 else { // relerr != DBL_EPSILON, compute exp(-a2*(n*n)) on the fly | 868 else { // relerr != DBL_EPSILON, compute exp(-a2*(n*n)) on the fly |
803 const double exp2ax = exp((2*a)*x), expm2ax = 1 / exp2ax; | 869 const double exp2ax = exp((2*a)*x), expm2ax = 1 / exp2ax; |
804 if (x < 5e-4) { // compute sum4 and sum5 together as sum5-sum4 | 870 if (x < 5e-4) { // compute sum4 and sum5 together as sum5-sum4 |
805 const double x2 = x*x; | 871 const double x2 = x*x; |
806 expx2 = 1 - x2 * (1 - 0.5*x2); // exp(-x*x) via Taylor | 872 expx2 = 1 - x2 * (1 - 0.5*x2); // exp(-x*x) via Taylor |
807 for (int n = 1; 1; ++n) { | 873 for (int n = 1; 1; ++n) { |
808 const double coef = exp(-a2*(n*n)) * expx2 / (a2*(n*n) + y*y); | 874 const double coef = exp(-a2*(n*n)) * expx2 / (a2*(n*n) + y*y); |
809 prod2ax *= exp2ax; | 875 prod2ax *= exp2ax; |
810 prodm2ax *= expm2ax; | 876 prodm2ax *= expm2ax; |
811 sum1 += coef; | 877 sum1 += coef; |
812 sum2 += coef * prodm2ax; | 878 sum2 += coef * prodm2ax; |
813 sum3 += coef * prod2ax; | 879 sum3 += coef * prod2ax; |
814 | 880 |
815 // really = sum5 - sum4 | 881 // really = sum5 - sum4 |
816 sum5 += coef * (2*a) * n * sinh_taylor((2*a)*n*x); | 882 sum5 += coef * (2*a) * n * sinh_taylor((2*a)*n*x); |
817 | 883 |
818 // test convergence via sum3 | 884 // test convergence via sum3 |
819 if (coef * prod2ax < relerr * sum3) break; | 885 if (coef * prod2ax < relerr * sum3) break; |
820 } | 886 } |
821 } | 887 } |
822 else { // x > 5e-4, compute sum4 and sum5 separately | 888 else { // x > 5e-4, compute sum4 and sum5 separately |
823 expx2 = exp(-x*x); | 889 expx2 = exp(-x*x); |
824 for (int n = 1; 1; ++n) { | 890 for (int n = 1; 1; ++n) { |
825 const double coef = exp(-a2*(n*n)) * expx2 / (a2*(n*n) + y*y); | 891 const double coef = exp(-a2*(n*n)) * expx2 / (a2*(n*n) + y*y); |
826 prod2ax *= exp2ax; | 892 prod2ax *= exp2ax; |
827 prodm2ax *= expm2ax; | 893 prodm2ax *= expm2ax; |
828 sum1 += coef; | 894 sum1 += coef; |
829 sum2 += coef * prodm2ax; | 895 sum2 += coef * prodm2ax; |
830 sum4 += (coef * prodm2ax) * (a*n); | 896 sum4 += (coef * prodm2ax) * (a*n); |
831 sum3 += coef * prod2ax; | 897 sum3 += coef * prod2ax; |
832 sum5 += (coef * prod2ax) * (a*n); | 898 sum5 += (coef * prod2ax) * (a*n); |
833 // test convergence via sum5, since this sum has the slowest decay | 899 // test convergence via sum5, since this sum has the slowest decay |
834 if ((coef * prod2ax) * (a*n) < relerr * sum5) break; | 900 if ((coef * prod2ax) * (a*n) < relerr * sum5) break; |
835 } | 901 } |
836 } | 902 } |
837 } | 903 } |
838 const double expx2erfcxy = // avoid spurious overflow for large negative y | 904 const double expx2erfcxy = // avoid spurious overflow for large negative y |
839 y > -6 // for y < -6, erfcx(y) = 2*exp(y*y) to double precision | 905 y > -6 // for y < -6, erfcx(y) = 2*exp(y*y) to double precision |
840 ? expx2*FADDEEVA_RE(erfcx)(y) : 2*exp(y*y-x*x); | 906 ? expx2*FADDEEVA_RE(erfcx)(y) : 2*exp(y*y-x*x); |
841 if (y > 5) { // imaginary terms cancel | 907 if (y > 5) { // imaginary terms cancel |
842 const double sinxy = sin(x*y); | 908 const double sinxy = sin(x*y); |
843 ret = (expx2erfcxy - c*y*sum1) * cos(2*x*y) | 909 ret = (expx2erfcxy - c*y*sum1) * cos(2*x*y) |
844 + (c*x*expx2) * sinxy * sinc(x*y, sinxy); | 910 + (c*x*expx2) * sinxy * sinc(x*y, sinxy); |
845 } | 911 } |
846 else { | 912 else { |
847 double xs = creal(z); | 913 double xs = creal(z); |
848 const double sinxy = sin(xs*y); | 914 const double sinxy = sin(xs*y); |
849 const double sin2xy = sin(2*xs*y), cos2xy = cos(2*xs*y); | 915 const double sin2xy = sin(2*xs*y), cos2xy = cos(2*xs*y); |
850 const double coef1 = expx2erfcxy - c*y*sum1; | 916 const double coef1 = expx2erfcxy - c*y*sum1; |
851 const double coef2 = c*xs*expx2; | 917 const double coef2 = c*xs*expx2; |
852 ret = CMPLX(coef1 * cos2xy + coef2 * sinxy * sinc(xs*y, sinxy), | 918 ret = C(coef1 * cos2xy + coef2 * sinxy * sinc(xs*y, sinxy), |
853 coef2 * sinc(2*xs*y, sin2xy) - coef1 * sin2xy); | 919 coef2 * sinc(2*xs*y, sin2xy) - coef1 * sin2xy); |
854 } | 920 } |
855 } | 921 } |
856 else { // x large: only sum3 & sum5 contribute (see above note) | 922 else { // x large: only sum3 & sum5 contribute (see above note) |
857 if (isnan(x)) | 923 if (isnan(x)) |
858 return CMPLX(x,x); | 924 return C(x,x); |
859 if (isnan(y)) | 925 if (isnan(y)) |
860 return CMPLX(y,y); | 926 return C(y,y); |
861 | 927 |
862 #if USE_CONTINUED_FRACTION | 928 #if USE_CONTINUED_FRACTION |
863 ret = exp(-x*x); // |y| < 1e-10, so we only need exp(-x*x) term | 929 ret = exp(-x*x); // |y| < 1e-10, so we only need exp(-x*x) term |
864 #else | 930 #else |
865 if (y < 0) { | 931 if (y < 0) { |
866 /* erfcx(y) ~ 2*exp(y*y) + (< 1) if y < 0, so | 932 /* erfcx(y) ~ 2*exp(y*y) + (< 1) if y < 0, so |
867 erfcx(y)*exp(-x*x) ~ 2*exp(y*y-x*x) term may not be negligible | 933 erfcx(y)*exp(-x*x) ~ 2*exp(y*y-x*x) term may not be negligible |
868 if y*y - x*x > -36 or so. So, compute this term just in case. | 934 if y*y - x*x > -36 or so. So, compute this term just in case. |
869 We also need the -exp(-x*x) term to compute Re[w] accurately | 935 We also need the -exp(-x*x) term to compute Re[w] accurately |
870 in the case where y is very small. */ | 936 in the case where y is very small. */ |
871 ret = cpolar(2*exp(y*y-x*x) - exp(-x*x), -2*creal(z)*y); | 937 ret = cpolar(2*exp(y*y-x*x) - exp(-x*x), -2*creal(z)*y); |
872 } | 938 } |
873 else | 939 else |
874 ret = exp(-x*x); // not negligible in real part if y very small | 940 ret = exp(-x*x); // not negligible in real part if y very small |
875 #endif | 941 #endif |
897 sum5 += a * np * tp; | 963 sum5 += a * np * tp; |
898 if (a * np * tp < relerr * sum5) goto finish; | 964 if (a * np * tp < relerr * sum5) goto finish; |
899 } | 965 } |
900 } | 966 } |
901 finish: | 967 finish: |
902 return ret + CMPLX((0.5*c)*y*(sum2+sum3), | 968 return ret + C((0.5*c)*y*(sum2+sum3), |
903 (0.5*c)*copysign(sum5-sum4, creal(z))); | 969 (0.5*c)*copysign(sum5-sum4, creal(z))); |
904 } | 970 } |
905 | 971 |
906 ///////////////////////////////////////////////////////////////////////// | 972 ///////////////////////////////////////////////////////////////////////// |
907 | 973 |
908 /* erfcx(x) = exp(x^2) erfc(x) function, for real x, written by | 974 /* erfcx(x) = exp(x^2) erfc(x) function, for real x, written by |
916 Second, for 0 <= x <= 50, it uses Chebyshev polynomial approximations, | 982 Second, for 0 <= x <= 50, it uses Chebyshev polynomial approximations, |
917 but with two twists: | 983 but with two twists: |
918 | 984 |
919 a) It maps x to y = 4 / (4+x) in [0,1]. This simple transformation, | 985 a) It maps x to y = 4 / (4+x) in [0,1]. This simple transformation, |
920 inspired by a similar transformation in the octave-forge/specfun | 986 inspired by a similar transformation in the octave-forge/specfun |
921 erfcx by Soren Hauberg, results in much faster Chebyshev convergence | 987 erfcx by Soren Hauberg, results in much faster Chebyshev convergence |
922 than other simple transformations I have examined. | 988 than other simple transformations I have examined. |
923 | 989 |
924 b) Instead of using a single Chebyshev polynomial for the entire | 990 b) Instead of using a single Chebyshev polynomial for the entire |
925 [0,1] y interval, we break the interval up into 100 equal | 991 [0,1] y interval, we break the interval up into 100 equal |
926 subintervals, with a switch/lookup table, and use much lower | 992 subintervals, with a switch/lookup table, and use much lower |
927 degree Chebyshev polynomials in each subinterval. This greatly | 993 degree Chebyshev polynomials in each subinterval. This greatly |
928 improves performance in my tests. | 994 improves performance in my tests. |
929 | 995 |
930 For x < 0, we use the relationship erfcx(-x) = 2 exp(x^2) - erfc(x), | 996 For x < 0, we use the relationship erfcx(-x) = 2 exp(x^2) - erfc(x), |
931 with the usual checks for overflow etcetera. | 997 with the usual checks for overflow etcetera. |
932 | 998 |
933 Performance-wise, it seems to be substantially faster than either | 999 Performance-wise, it seems to be substantially faster than either |
1355 { | 1421 { |
1356 if (x >= 0) { | 1422 if (x >= 0) { |
1357 if (x > 50) { // continued-fraction expansion is faster | 1423 if (x > 50) { // continued-fraction expansion is faster |
1358 const double ispi = 0.56418958354775628694807945156; // 1 / sqrt(pi) | 1424 const double ispi = 0.56418958354775628694807945156; // 1 / sqrt(pi) |
1359 if (x > 5e7) // 1-term expansion, important to avoid overflow | 1425 if (x > 5e7) // 1-term expansion, important to avoid overflow |
1360 return ispi / x; | 1426 return ispi / x; |
1361 /* 5-term expansion (rely on compiler for CSE), simplified from: | 1427 /* 5-term expansion (rely on compiler for CSE), simplified from: |
1362 ispi / (x+0.5/(x+1/(x+1.5/(x+2/x)))) */ | 1428 ispi / (x+0.5/(x+1/(x+1.5/(x+2/x)))) */ |
1363 return ispi*((x*x) * (x*x+4.5) + 2) / (x * ((x*x) * (x*x+5) + 3.75)); | 1429 return ispi*((x*x) * (x*x+4.5) + 2) / (x * ((x*x) * (x*x+5) + 3.75)); |
1364 } | 1430 } |
1365 return erfcx_y100(400/(4+x)); | 1431 return erfcx_y100(400/(4+x)); |
1366 } | 1432 } |
1367 else | 1433 else |
1368 return x < -26.7 ? HUGE_VAL : (x < -6.1 ? 2*exp(x*x) | 1434 return x < -26.7 ? HUGE_VAL : (x < -6.1 ? 2*exp(x*x) |
1369 : 2*exp(x*x) - erfcx_y100(400/(4-x))); | 1435 : 2*exp(x*x) - erfcx_y100(400/(4-x))); |
1370 } | 1436 } |
1371 | 1437 |
1372 ///////////////////////////////////////////////////////////////////////// | 1438 ///////////////////////////////////////////////////////////////////////// |
1373 /* Compute a scaled Dawson integral | 1439 /* Compute a scaled Dawson integral |
1374 FADDEEVA(w_im)(x) = 2*Dawson(x)/sqrt(pi) | 1440 FADDEEVA(w_im)(x) = 2*Dawson(x)/sqrt(pi) |
1775 } | 1841 } |
1776 case 96: { | 1842 case 96: { |
1777 double t = 2*y100 - 193; | 1843 double t = 2*y100 - 193; |
1778 return 0.40889797115352738582e-1 + (-0.60426484889413678200e-2 + (0.28953496450191694606e-4 + (-0.21982952021823718400e-7 + (-0.11044169117553026211e-8 + (0.13344562332430552171e-10 - 0.10091231402844444444e-12 * t) * t) * t) * t) * t) * t; | 1844 return 0.40889797115352738582e-1 + (-0.60426484889413678200e-2 + (0.28953496450191694606e-4 + (-0.21982952021823718400e-7 + (-0.11044169117553026211e-8 + (0.13344562332430552171e-10 - 0.10091231402844444444e-12 * t) * t) * t) * t) * t) * t; |
1779 } | 1845 } |
1780 case 97: { | 1846 case 97: case 98: |
1781 double t = 2*y100 - 195; | 1847 case 99: case 100: { // use Taylor expansion for small x (|x| <= 0.0309...) |
1782 return 0.28920121009594899986e-1 + (-0.59271325915413781788e-2 + (0.28796136372768177423e-4 + (-0.30300382596279568642e-7 + (-0.97688275022802329749e-9 + (0.12179215701512592356e-10 - 0.93380988481777777779e-13 * t) * t) * t) * t) * t) * t; | 1848 // (2/sqrt(pi)) * (x - 2/3 x^3 + 4/15 x^5 - 8/105 x^7 + 16/945 x^9) |
1783 } | |
1784 case 98: { | |
1785 double t = 2*y100 - 197; | |
1786 return 0.17180782722617876655e-1 + (-0.58123419543161127769e-2 + (0.28591841095380959666e-4 + (-0.37642963496443667043e-7 + (-0.86055809047367300024e-9 + (0.11101709356762665578e-10 - 0.86272947493333333334e-13 * t) * t) * t) * t) * t) * t; | |
1787 } | |
1788 case 99: case 100: { // use Taylor expansion for small x (|x| <= 0.010101...) | |
1789 // (2/sqrt(pi)) * (x - 2/3 x^3 + 4/15 x^5 - 8/105 x^7) | |
1790 double x2 = x*x; | 1849 double x2 = x*x; |
1791 return x * (1.1283791670955125739 | 1850 return x * (1.1283791670955125739 |
1792 - x2 * (0.75225277806367504925 | 1851 - x2 * (0.75225277806367504925 |
1793 - x2 * (0.30090111122547001970 | 1852 - x2 * (0.30090111122547001970 |
1794 - x2 * 0.085971746064420005629))); | 1853 - x2 * (0.085971746064420005629 |
1854 - x2 * 0.016931216931216931217)))); | |
1795 } | 1855 } |
1796 } | 1856 } |
1797 /* Since 0 <= y100 < 101, this is only reached if x is NaN, | 1857 /* Since 0 <= y100 < 101, this is only reached if x is NaN, |
1798 in which case we should return NaN. */ | 1858 in which case we should return NaN. */ |
1799 return NaN; | 1859 return NaN; |
1803 { | 1863 { |
1804 if (x >= 0) { | 1864 if (x >= 0) { |
1805 if (x > 45) { // continued-fraction expansion is faster | 1865 if (x > 45) { // continued-fraction expansion is faster |
1806 const double ispi = 0.56418958354775628694807945156; // 1 / sqrt(pi) | 1866 const double ispi = 0.56418958354775628694807945156; // 1 / sqrt(pi) |
1807 if (x > 5e7) // 1-term expansion, important to avoid overflow | 1867 if (x > 5e7) // 1-term expansion, important to avoid overflow |
1808 return ispi / x; | 1868 return ispi / x; |
1809 /* 5-term expansion (rely on compiler for CSE), simplified from: | 1869 /* 5-term expansion (rely on compiler for CSE), simplified from: |
1810 ispi / (x-0.5/(x-1/(x-1.5/(x-2/x)))) */ | 1870 ispi / (x-0.5/(x-1/(x-1.5/(x-2/x)))) */ |
1811 return ispi*((x*x) * (x*x-4.5) + 2) / (x * ((x*x) * (x*x-5) + 3.75)); | 1871 return ispi*((x*x) * (x*x-4.5) + 2) / (x * ((x*x) * (x*x-5) + 3.75)); |
1812 } | 1872 } |
1813 return w_im_y100(100/(1+x), x); | 1873 return w_im_y100(100/(1+x), x); |
1814 } | 1874 } |
1815 else { // = -FADDEEVA(w_im)(-x) | 1875 else { // = -FADDEEVA(w_im)(-x) |
1816 if (x < -45) { // continued-fraction expansion is faster | 1876 if (x < -45) { // continued-fraction expansion is faster |
1817 const double ispi = 0.56418958354775628694807945156; // 1 / sqrt(pi) | 1877 const double ispi = 0.56418958354775628694807945156; // 1 / sqrt(pi) |
1818 if (x < -5e7) // 1-term expansion, important to avoid overflow | 1878 if (x < -5e7) // 1-term expansion, important to avoid overflow |
1819 return ispi / x; | 1879 return ispi / x; |
1820 /* 5-term expansion (rely on compiler for CSE), simplified from: | 1880 /* 5-term expansion (rely on compiler for CSE), simplified from: |
1821 ispi / (x-0.5/(x-1/(x-1.5/(x-2/x)))) */ | 1881 ispi / (x-0.5/(x-1/(x-1.5/(x-2/x)))) */ |
1822 return ispi*((x*x) * (x*x-4.5) + 2) / (x * ((x*x) * (x*x-5) + 3.75)); | 1882 return ispi*((x*x) * (x*x-4.5) + 2) / (x * ((x*x) * (x*x-5) + 3.75)); |
1823 } | 1883 } |
1824 return -w_im_y100(100/(1-x), -x); | 1884 return -w_im_y100(100/(1-x), -x); |
1825 } | 1885 } |
1826 } | 1886 } |
1838 | 1898 |
1839 // compute relative error |b-a|/|a|, handling case of NaN and Inf, | 1899 // compute relative error |b-a|/|a|, handling case of NaN and Inf, |
1840 static double relerr(double a, double b) { | 1900 static double relerr(double a, double b) { |
1841 if (isnan(a) || isnan(b) || isinf(a) || isinf(b)) { | 1901 if (isnan(a) || isnan(b) || isinf(a) || isinf(b)) { |
1842 if ((isnan(a) && !isnan(b)) || (!isnan(a) && isnan(b)) || | 1902 if ((isnan(a) && !isnan(b)) || (!isnan(a) && isnan(b)) || |
1843 (isinf(a) && !isinf(b)) || (!isinf(a) && isinf(b)) || | 1903 (isinf(a) && !isinf(b)) || (!isinf(a) && isinf(b)) || |
1844 (isinf(a) && isinf(b) && a*b < 0)) | 1904 (isinf(a) && isinf(b) && a*b < 0)) |
1845 return Inf; // "infinite" error | 1905 return Inf; // "infinite" error |
1846 return 0; // matching infinity/nan results counted as zero error | 1906 return 0; // matching infinity/nan results counted as zero error |
1847 } | 1907 } |
1848 if (a == 0) | 1908 if (a == 0) |
1849 return b == 0 ? 0 : Inf; | 1909 return b == 0 ? 0 : Inf; |
1855 double errmax_all = 0; | 1915 double errmax_all = 0; |
1856 { | 1916 { |
1857 printf("############# w(z) tests #############\n"); | 1917 printf("############# w(z) tests #############\n"); |
1858 #define NTST 57 // define instead of const for C compatibility | 1918 #define NTST 57 // define instead of const for C compatibility |
1859 cmplx z[NTST] = { | 1919 cmplx z[NTST] = { |
1860 CMPLX(624.2,-0.26123), | 1920 C(624.2,-0.26123), |
1861 CMPLX(-0.4,3.), | 1921 C(-0.4,3.), |
1862 CMPLX(0.6,2.), | 1922 C(0.6,2.), |
1863 CMPLX(-1.,1.), | 1923 C(-1.,1.), |
1864 CMPLX(-1.,-9.), | 1924 C(-1.,-9.), |
1865 CMPLX(-1.,9.), | 1925 C(-1.,9.), |
1866 CMPLX(-0.0000000234545,1.1234), | 1926 C(-0.0000000234545,1.1234), |
1867 CMPLX(-3.,5.1), | 1927 C(-3.,5.1), |
1868 CMPLX(-53,30.1), | 1928 C(-53,30.1), |
1869 CMPLX(0.0,0.12345), | 1929 C(0.0,0.12345), |
1870 CMPLX(11,1), | 1930 C(11,1), |
1871 CMPLX(-22,-2), | 1931 C(-22,-2), |
1872 CMPLX(9,-28), | 1932 C(9,-28), |
1873 CMPLX(21,-33), | 1933 C(21,-33), |
1874 CMPLX(1e5,1e5), | 1934 C(1e5,1e5), |
1875 CMPLX(1e14,1e14), | 1935 C(1e14,1e14), |
1876 CMPLX(-3001,-1000), | 1936 C(-3001,-1000), |
1877 CMPLX(1e160,-1e159), | 1937 C(1e160,-1e159), |
1878 CMPLX(-6.01,0.01), | 1938 C(-6.01,0.01), |
1879 CMPLX(-0.7,-0.7), | 1939 C(-0.7,-0.7), |
1880 CMPLX(2.611780000000000e+01, 4.540909610972489e+03), | 1940 C(2.611780000000000e+01, 4.540909610972489e+03), |
1881 CMPLX(0.8e7,0.3e7), | 1941 C(0.8e7,0.3e7), |
1882 CMPLX(-20,-19.8081), | 1942 C(-20,-19.8081), |
1883 CMPLX(1e-16,-1.1e-16), | 1943 C(1e-16,-1.1e-16), |
1884 CMPLX(2.3e-8,1.3e-8), | 1944 C(2.3e-8,1.3e-8), |
1885 CMPLX(6.3,-1e-13), | 1945 C(6.3,-1e-13), |
1886 CMPLX(6.3,1e-20), | 1946 C(6.3,1e-20), |
1887 CMPLX(1e-20,6.3), | 1947 C(1e-20,6.3), |
1888 CMPLX(1e-20,16.3), | 1948 C(1e-20,16.3), |
1889 CMPLX(9,1e-300), | 1949 C(9,1e-300), |
1890 CMPLX(6.01,0.11), | 1950 C(6.01,0.11), |
1891 CMPLX(8.01,1.01e-10), | 1951 C(8.01,1.01e-10), |
1892 CMPLX(28.01,1e-300), | 1952 C(28.01,1e-300), |
1893 CMPLX(10.01,1e-200), | 1953 C(10.01,1e-200), |
1894 CMPLX(10.01,-1e-200), | 1954 C(10.01,-1e-200), |
1895 CMPLX(10.01,0.99e-10), | 1955 C(10.01,0.99e-10), |
1896 CMPLX(10.01,-0.99e-10), | 1956 C(10.01,-0.99e-10), |
1897 CMPLX(1e-20,7.01), | 1957 C(1e-20,7.01), |
1898 CMPLX(-1,7.01), | 1958 C(-1,7.01), |
1899 CMPLX(5.99,7.01), | 1959 C(5.99,7.01), |
1900 CMPLX(1,0), | 1960 C(1,0), |
1901 CMPLX(55,0), | 1961 C(55,0), |
1902 CMPLX(-0.1,0), | 1962 C(-0.1,0), |
1903 CMPLX(1e-20,0), | 1963 C(1e-20,0), |
1904 CMPLX(0,5e-14), | 1964 C(0,5e-14), |
1905 CMPLX(0,51), | 1965 C(0,51), |
1906 CMPLX(Inf,0), | 1966 C(Inf,0), |
1907 CMPLX(-Inf,0), | 1967 C(-Inf,0), |
1908 CMPLX(0,Inf), | 1968 C(0,Inf), |
1909 CMPLX(0,-Inf), | 1969 C(0,-Inf), |
1910 CMPLX(Inf,Inf), | 1970 C(Inf,Inf), |
1911 CMPLX(Inf,-Inf), | 1971 C(Inf,-Inf), |
1912 CMPLX(NaN,NaN), | 1972 C(NaN,NaN), |
1913 CMPLX(NaN,0), | 1973 C(NaN,0), |
1914 CMPLX(0,NaN), | 1974 C(0,NaN), |
1915 CMPLX(NaN,Inf), | 1975 C(NaN,Inf), |
1916 CMPLX(Inf,NaN) | 1976 C(Inf,NaN) |
1917 }; | 1977 }; |
1918 cmplx w[NTST] = { /* w(z), computed with WolframAlpha | 1978 cmplx w[NTST] = { /* w(z), computed with WolframAlpha |
1919 ... note that WolframAlpha is problematic | 1979 ... note that WolframAlpha is problematic |
1920 some of the above inputs, so I had to | 1980 some of the above inputs, so I had to |
1921 use the continued-fraction expansion | 1981 use the continued-fraction expansion |
1922 in WolframAlpha in some cases, or switch | 1982 in WolframAlpha in some cases, or switch |
1923 to Maple */ | 1983 to Maple */ |
1924 CMPLX(-3.78270245518980507452677445620103199303131110e-7, | 1984 C(-3.78270245518980507452677445620103199303131110e-7, |
1925 0.000903861276433172057331093754199933411710053155), | 1985 0.000903861276433172057331093754199933411710053155), |
1926 CMPLX(0.1764906227004816847297495349730234591778719532788, | 1986 C(0.1764906227004816847297495349730234591778719532788, |
1927 -0.02146550539468457616788719893991501311573031095617), | 1987 -0.02146550539468457616788719893991501311573031095617), |
1928 CMPLX(0.2410250715772692146133539023007113781272362309451, | 1988 C(0.2410250715772692146133539023007113781272362309451, |
1929 0.06087579663428089745895459735240964093522265589350), | 1989 0.06087579663428089745895459735240964093522265589350), |
1930 CMPLX(0.30474420525691259245713884106959496013413834051768, | 1990 C(0.30474420525691259245713884106959496013413834051768, |
1931 -0.20821893820283162728743734725471561394145872072738), | 1991 -0.20821893820283162728743734725471561394145872072738), |
1932 CMPLX(7.317131068972378096865595229600561710140617977e34, | 1992 C(7.317131068972378096865595229600561710140617977e34, |
1933 8.321873499714402777186848353320412813066170427e34), | 1993 8.321873499714402777186848353320412813066170427e34), |
1934 CMPLX(0.0615698507236323685519612934241429530190806818395, | 1994 C(0.0615698507236323685519612934241429530190806818395, |
1935 -0.00676005783716575013073036218018565206070072304635), | 1995 -0.00676005783716575013073036218018565206070072304635), |
1936 CMPLX(0.3960793007699874918961319170187598400134746631, | 1996 C(0.3960793007699874918961319170187598400134746631, |
1937 -5.593152259116644920546186222529802777409274656e-9), | 1997 -5.593152259116644920546186222529802777409274656e-9), |
1938 CMPLX(0.08217199226739447943295069917990417630675021771804, | 1998 C(0.08217199226739447943295069917990417630675021771804, |
1939 -0.04701291087643609891018366143118110965272615832184), | 1999 -0.04701291087643609891018366143118110965272615832184), |
1940 CMPLX(0.00457246000350281640952328010227885008541748668738, | 2000 C(0.00457246000350281640952328010227885008541748668738, |
1941 -0.00804900791411691821818731763401840373998654987934), | 2001 -0.00804900791411691821818731763401840373998654987934), |
1942 CMPLX(0.8746342859608052666092782112565360755791467973338452, | 2002 C(0.8746342859608052666092782112565360755791467973338452, |
1943 0.), | 2003 0.), |
1944 CMPLX(0.00468190164965444174367477874864366058339647648741, | 2004 C(0.00468190164965444174367477874864366058339647648741, |
1945 0.0510735563901306197993676329845149741675029197050), | 2005 0.0510735563901306197993676329845149741675029197050), |
1946 CMPLX(-0.0023193175200187620902125853834909543869428763219, | 2006 C(-0.0023193175200187620902125853834909543869428763219, |
1947 -0.025460054739731556004902057663500272721780776336), | 2007 -0.025460054739731556004902057663500272721780776336), |
1948 CMPLX(9.11463368405637174660562096516414499772662584e304, | 2008 C(9.11463368405637174660562096516414499772662584e304, |
1949 3.97101807145263333769664875189354358563218932e305), | 2009 3.97101807145263333769664875189354358563218932e305), |
1950 CMPLX(-4.4927207857715598976165541011143706155432296e281, | 2010 C(-4.4927207857715598976165541011143706155432296e281, |
1951 -2.8019591213423077494444700357168707775769028e281), | 2011 -2.8019591213423077494444700357168707775769028e281), |
1952 CMPLX(2.820947917809305132678577516325951485807107151e-6, | 2012 C(2.820947917809305132678577516325951485807107151e-6, |
1953 2.820947917668257736791638444590253942253354058e-6), | 2013 2.820947917668257736791638444590253942253354058e-6), |
1954 CMPLX(2.82094791773878143474039725787438662716372268e-15, | 2014 C(2.82094791773878143474039725787438662716372268e-15, |
1955 2.82094791773878143474039725773333923127678361e-15), | 2015 2.82094791773878143474039725773333923127678361e-15), |
1956 CMPLX(-0.0000563851289696244350147899376081488003110150498, | 2016 C(-0.0000563851289696244350147899376081488003110150498, |
1957 -0.000169211755126812174631861529808288295454992688), | 2017 -0.000169211755126812174631861529808288295454992688), |
1958 CMPLX(-5.586035480670854326218608431294778077663867e-162, | 2018 C(-5.586035480670854326218608431294778077663867e-162, |
1959 5.586035480670854326218608431294778077663867e-161), | 2019 5.586035480670854326218608431294778077663867e-161), |
1960 CMPLX(0.00016318325137140451888255634399123461580248456, | 2020 C(0.00016318325137140451888255634399123461580248456, |
1961 -0.095232456573009287370728788146686162555021209999), | 2021 -0.095232456573009287370728788146686162555021209999), |
1962 CMPLX(0.69504753678406939989115375989939096800793577783885, | 2022 C(0.69504753678406939989115375989939096800793577783885, |
1963 -1.8916411171103639136680830887017670616339912024317), | 2023 -1.8916411171103639136680830887017670616339912024317), |
1964 CMPLX(0.0001242418269653279656612334210746733213167234822, | 2024 C(0.0001242418269653279656612334210746733213167234822, |
1965 7.145975826320186888508563111992099992116786763e-7), | 2025 7.145975826320186888508563111992099992116786763e-7), |
1966 CMPLX(2.318587329648353318615800865959225429377529825e-8, | 2026 C(2.318587329648353318615800865959225429377529825e-8, |
1967 6.182899545728857485721417893323317843200933380e-8), | 2027 6.182899545728857485721417893323317843200933380e-8), |
1968 CMPLX(-0.0133426877243506022053521927604277115767311800303, | 2028 C(-0.0133426877243506022053521927604277115767311800303, |
1969 -0.0148087097143220769493341484176979826888871576145), | 2029 -0.0148087097143220769493341484176979826888871576145), |
1970 CMPLX(1.00000000000000012412170838050638522857747934, | 2030 C(1.00000000000000012412170838050638522857747934, |
1971 1.12837916709551279389615890312156495593616433e-16), | 2031 1.12837916709551279389615890312156495593616433e-16), |
1972 CMPLX(0.9999999853310704677583504063775310832036830015, | 2032 C(0.9999999853310704677583504063775310832036830015, |
1973 2.595272024519678881897196435157270184030360773e-8), | 2033 2.595272024519678881897196435157270184030360773e-8), |
1974 CMPLX(-1.4731421795638279504242963027196663601154624e-15, | 2034 C(-1.4731421795638279504242963027196663601154624e-15, |
1975 0.090727659684127365236479098488823462473074709), | 2035 0.090727659684127365236479098488823462473074709), |
1976 CMPLX(5.79246077884410284575834156425396800754409308e-18, | 2036 C(5.79246077884410284575834156425396800754409308e-18, |
1977 0.0907276596841273652364790985059772809093822374), | 2037 0.0907276596841273652364790985059772809093822374), |
1978 CMPLX(0.0884658993528521953466533278764830881245144368, | 2038 C(0.0884658993528521953466533278764830881245144368, |
1979 1.37088352495749125283269718778582613192166760e-22), | 2039 1.37088352495749125283269718778582613192166760e-22), |
1980 CMPLX(0.0345480845419190424370085249304184266813447878, | 2040 C(0.0345480845419190424370085249304184266813447878, |
1981 2.11161102895179044968099038990446187626075258e-23), | 2041 2.11161102895179044968099038990446187626075258e-23), |
1982 CMPLX(6.63967719958073440070225527042829242391918213e-36, | 2042 C(6.63967719958073440070225527042829242391918213e-36, |
1983 0.0630820900592582863713653132559743161572639353), | 2043 0.0630820900592582863713653132559743161572639353), |
1984 CMPLX(0.00179435233208702644891092397579091030658500743634, | 2044 C(0.00179435233208702644891092397579091030658500743634, |
1985 0.0951983814805270647939647438459699953990788064762), | 2045 0.0951983814805270647939647438459699953990788064762), |
1986 CMPLX(9.09760377102097999924241322094863528771095448e-13, | 2046 C(9.09760377102097999924241322094863528771095448e-13, |
1987 0.0709979210725138550986782242355007611074966717), | 2047 0.0709979210725138550986782242355007611074966717), |
1988 CMPLX(7.2049510279742166460047102593255688682910274423e-304, | 2048 C(7.2049510279742166460047102593255688682910274423e-304, |
1989 0.0201552956479526953866611812593266285000876784321), | 2049 0.0201552956479526953866611812593266285000876784321), |
1990 CMPLX(3.04543604652250734193622967873276113872279682e-44, | 2050 C(3.04543604652250734193622967873276113872279682e-44, |
1991 0.0566481651760675042930042117726713294607499165), | 2051 0.0566481651760675042930042117726713294607499165), |
1992 CMPLX(3.04543604652250734193622967873276113872279682e-44, | 2052 C(3.04543604652250734193622967873276113872279682e-44, |
1993 0.0566481651760675042930042117726713294607499165), | 2053 0.0566481651760675042930042117726713294607499165), |
1994 CMPLX(0.5659928732065273429286988428080855057102069081e-12, | 2054 C(0.5659928732065273429286988428080855057102069081e-12, |
1995 0.056648165176067504292998527162143030538756683302), | 2055 0.056648165176067504292998527162143030538756683302), |
1996 CMPLX(-0.56599287320652734292869884280802459698927645e-12, | 2056 C(-0.56599287320652734292869884280802459698927645e-12, |
1997 0.0566481651760675042929985271621430305387566833029), | 2057 0.0566481651760675042929985271621430305387566833029), |
1998 CMPLX(0.0796884251721652215687859778119964009569455462, | 2058 C(0.0796884251721652215687859778119964009569455462, |
1999 1.11474461817561675017794941973556302717225126e-22), | 2059 1.11474461817561675017794941973556302717225126e-22), |
2000 CMPLX(0.07817195821247357458545539935996687005781943386550, | 2060 C(0.07817195821247357458545539935996687005781943386550, |
2001 -0.01093913670103576690766705513142246633056714279654), | 2061 -0.01093913670103576690766705513142246633056714279654), |
2002 CMPLX(0.04670032980990449912809326141164730850466208439937, | 2062 C(0.04670032980990449912809326141164730850466208439937, |
2003 0.03944038961933534137558064191650437353429669886545), | 2063 0.03944038961933534137558064191650437353429669886545), |
2004 CMPLX(0.36787944117144232159552377016146086744581113103176, | 2064 C(0.36787944117144232159552377016146086744581113103176, |
2005 0.60715770584139372911503823580074492116122092866515), | 2065 0.60715770584139372911503823580074492116122092866515), |
2006 CMPLX(0, | 2066 C(0, |
2007 0.010259688805536830986089913987516716056946786526145), | 2067 0.010259688805536830986089913987516716056946786526145), |
2008 CMPLX(0.99004983374916805357390597718003655777207908125383, | 2068 C(0.99004983374916805357390597718003655777207908125383, |
2009 -0.11208866436449538036721343053869621153527769495574), | 2069 -0.11208866436449538036721343053869621153527769495574), |
2010 CMPLX(0.99999999999999999999999999999999999999990000, | 2070 C(0.99999999999999999999999999999999999999990000, |
2011 1.12837916709551257389615890312154517168802603e-20), | 2071 1.12837916709551257389615890312154517168802603e-20), |
2012 CMPLX(0.999999999999943581041645226871305192054749891144158, | 2072 C(0.999999999999943581041645226871305192054749891144158, |
2013 0), | 2073 0), |
2014 CMPLX(0.0110604154853277201542582159216317923453996211744250, | 2074 C(0.0110604154853277201542582159216317923453996211744250, |
2015 0), | 2075 0), |
2016 CMPLX(0,0), | 2076 C(0,0), |
2017 CMPLX(0,0), | 2077 C(0,0), |
2018 CMPLX(0,0), | 2078 C(0,0), |
2019 CMPLX(Inf,0), | 2079 C(Inf,0), |
2020 CMPLX(0,0), | 2080 C(0,0), |
2021 CMPLX(NaN,NaN), | 2081 C(NaN,NaN), |
2022 CMPLX(NaN,NaN), | 2082 C(NaN,NaN), |
2023 CMPLX(NaN,NaN), | 2083 C(NaN,NaN), |
2024 CMPLX(NaN,0), | 2084 C(NaN,0), |
2025 CMPLX(NaN,NaN), | 2085 C(NaN,NaN), |
2026 CMPLX(NaN,NaN) | 2086 C(NaN,NaN) |
2027 }; | 2087 }; |
2028 double errmax = 0; | 2088 double errmax = 0; |
2029 for (int i = 0; i < NTST; ++i) { | 2089 for (int i = 0; i < NTST; ++i) { |
2030 cmplx fw = FADDEEVA(w)(z[i],0.); | 2090 cmplx fw = FADDEEVA(w)(z[i],0.); |
2031 double re_err = relerr(creal(w[i]), creal(fw)); | 2091 double re_err = relerr(creal(w[i]), creal(fw)); |
2032 double im_err = relerr(cimag(w[i]), cimag(fw)); | 2092 double im_err = relerr(cimag(w[i]), cimag(fw)); |
2033 printf("w(%g%+gi) = %g%+gi (vs. %g%+gi), re/im rel. err. = %0.2g/%0.2g)\n", | 2093 printf("w(%g%+gi) = %g%+gi (vs. %g%+gi), re/im rel. err. = %0.2g/%0.2g)\n", |
2034 creal(z[i]),cimag(z[i]), creal(fw),cimag(fw), creal(w[i]),cimag(w[i]), | 2094 creal(z[i]),cimag(z[i]), creal(fw),cimag(fw), creal(w[i]),cimag(w[i]), |
2035 re_err, im_err); | 2095 re_err, im_err); |
2036 if (re_err > errmax) errmax = re_err; | 2096 if (re_err > errmax) errmax = re_err; |
2037 if (im_err > errmax) errmax = im_err; | 2097 if (im_err > errmax) errmax = im_err; |
2038 } | 2098 } |
2039 if (errmax > 1e-13) { | 2099 if (errmax > 1e-13) { |
2040 printf("FAILURE -- relative error %g too large!\n", errmax); | 2100 printf("FAILURE -- relative error %g too large!\n", errmax); |
2043 printf("SUCCESS (max relative error = %g)\n", errmax); | 2103 printf("SUCCESS (max relative error = %g)\n", errmax); |
2044 if (errmax > errmax_all) errmax_all = errmax; | 2104 if (errmax > errmax_all) errmax_all = errmax; |
2045 } | 2105 } |
2046 { | 2106 { |
2047 #undef NTST | 2107 #undef NTST |
2048 #define NTST 33 // define instead of const for C compatibility | 2108 #define NTST 41 // define instead of const for C compatibility |
2049 cmplx z[NTST] = { | 2109 cmplx z[NTST] = { |
2050 CMPLX(1,2), | 2110 C(1,2), |
2051 CMPLX(-1,2), | 2111 C(-1,2), |
2052 CMPLX(1,-2), | 2112 C(1,-2), |
2053 CMPLX(-1,-2), | 2113 C(-1,-2), |
2054 CMPLX(9,-28), | 2114 C(9,-28), |
2055 CMPLX(21,-33), | 2115 C(21,-33), |
2056 CMPLX(1e3,1e3), | 2116 C(1e3,1e3), |
2057 CMPLX(-3001,-1000), | 2117 C(-3001,-1000), |
2058 CMPLX(1e160,-1e159), | 2118 C(1e160,-1e159), |
2059 CMPLX(5.1e-3, 1e-8), | 2119 C(5.1e-3, 1e-8), |
2060 CMPLX(-4.9e-3, 4.95e-3), | 2120 C(-4.9e-3, 4.95e-3), |
2061 CMPLX(4.9e-3, 0.5), | 2121 C(4.9e-3, 0.5), |
2062 CMPLX(4.9e-4, -0.5e1), | 2122 C(4.9e-4, -0.5e1), |
2063 CMPLX(-4.9e-5, -0.5e2), | 2123 C(-4.9e-5, -0.5e2), |
2064 CMPLX(5.1e-3, 0.5), | 2124 C(5.1e-3, 0.5), |
2065 CMPLX(5.1e-4, -0.5e1), | 2125 C(5.1e-4, -0.5e1), |
2066 CMPLX(-5.1e-5, -0.5e2), | 2126 C(-5.1e-5, -0.5e2), |
2067 CMPLX(1e-6,2e-6), | 2127 C(1e-6,2e-6), |
2068 CMPLX(0,2e-6), | 2128 C(0,2e-6), |
2069 CMPLX(0,2), | 2129 C(0,2), |
2070 CMPLX(0,20), | 2130 C(0,20), |
2071 CMPLX(0,200), | 2131 C(0,200), |
2072 CMPLX(Inf,0), | 2132 C(Inf,0), |
2073 CMPLX(-Inf,0), | 2133 C(-Inf,0), |
2074 CMPLX(0,Inf), | 2134 C(0,Inf), |
2075 CMPLX(0,-Inf), | 2135 C(0,-Inf), |
2076 CMPLX(Inf,Inf), | 2136 C(Inf,Inf), |
2077 CMPLX(Inf,-Inf), | 2137 C(Inf,-Inf), |
2078 CMPLX(NaN,NaN), | 2138 C(NaN,NaN), |
2079 CMPLX(NaN,0), | 2139 C(NaN,0), |
2080 CMPLX(0,NaN), | 2140 C(0,NaN), |
2081 CMPLX(NaN,Inf), | 2141 C(NaN,Inf), |
2082 CMPLX(Inf,NaN) | 2142 C(Inf,NaN), |
2143 C(1e-3,NaN), | |
2144 C(7e-2,7e-2), | |
2145 C(7e-2,-7e-4), | |
2146 C(-9e-2,7e-4), | |
2147 C(-9e-2,9e-2), | |
2148 C(-7e-4,9e-2), | |
2149 C(7e-2,0.9e-2), | |
2150 C(7e-2,1.1e-2) | |
2083 }; | 2151 }; |
2084 cmplx w[NTST] = { // erf(z[i]), evaluated with Maple | 2152 cmplx w[NTST] = { // erf(z[i]), evaluated with Maple |
2085 CMPLX(-0.5366435657785650339917955593141927494421, | 2153 C(-0.5366435657785650339917955593141927494421, |
2086 -5.049143703447034669543036958614140565553), | 2154 -5.049143703447034669543036958614140565553), |
2087 CMPLX(0.5366435657785650339917955593141927494421, | 2155 C(0.5366435657785650339917955593141927494421, |
2088 -5.049143703447034669543036958614140565553), | 2156 -5.049143703447034669543036958614140565553), |
2089 CMPLX(-0.5366435657785650339917955593141927494421, | 2157 C(-0.5366435657785650339917955593141927494421, |
2090 5.049143703447034669543036958614140565553), | 2158 5.049143703447034669543036958614140565553), |
2091 CMPLX(0.5366435657785650339917955593141927494421, | 2159 C(0.5366435657785650339917955593141927494421, |
2092 5.049143703447034669543036958614140565553), | 2160 5.049143703447034669543036958614140565553), |
2093 CMPLX(0.3359473673830576996788000505817956637777e304, | 2161 C(0.3359473673830576996788000505817956637777e304, |
2094 -0.1999896139679880888755589794455069208455e304), | 2162 -0.1999896139679880888755589794455069208455e304), |
2095 CMPLX(0.3584459971462946066523939204836760283645e278, | 2163 C(0.3584459971462946066523939204836760283645e278, |
2096 0.3818954885257184373734213077678011282505e280), | 2164 0.3818954885257184373734213077678011282505e280), |
2097 CMPLX(0.9996020422657148639102150147542224526887, | 2165 C(0.9996020422657148639102150147542224526887, |
2098 0.00002801044116908227889681753993542916894856), | 2166 0.00002801044116908227889681753993542916894856), |
2099 CMPLX(-1, 0), | 2167 C(-1, 0), |
2100 CMPLX(1, 0), | 2168 C(1, 0), |
2101 CMPLX(0.005754683859034800134412990541076554934877, | 2169 C(0.005754683859034800134412990541076554934877, |
2102 0.1128349818335058741511924929801267822634e-7), | 2170 0.1128349818335058741511924929801267822634e-7), |
2103 CMPLX(-0.005529149142341821193633460286828381876955, | 2171 C(-0.005529149142341821193633460286828381876955, |
2104 0.005585388387864706679609092447916333443570), | 2172 0.005585388387864706679609092447916333443570), |
2105 CMPLX(0.007099365669981359632319829148438283865814, | 2173 C(0.007099365669981359632319829148438283865814, |
2106 0.6149347012854211635026981277569074001219), | 2174 0.6149347012854211635026981277569074001219), |
2107 CMPLX(0.3981176338702323417718189922039863062440e8, | 2175 C(0.3981176338702323417718189922039863062440e8, |
2108 -0.8298176341665249121085423917575122140650e10), | 2176 -0.8298176341665249121085423917575122140650e10), |
2109 CMPLX(-Inf, | 2177 C(-Inf, |
2110 -Inf), | 2178 -Inf), |
2111 CMPLX(0.007389128308257135427153919483147229573895, | 2179 C(0.007389128308257135427153919483147229573895, |
2112 0.6149332524601658796226417164791221815139), | 2180 0.6149332524601658796226417164791221815139), |
2113 CMPLX(0.4143671923267934479245651547534414976991e8, | 2181 C(0.4143671923267934479245651547534414976991e8, |
2114 -0.8298168216818314211557046346850921446950e10), | 2182 -0.8298168216818314211557046346850921446950e10), |
2115 CMPLX(-Inf, | 2183 C(-Inf, |
2116 -Inf), | 2184 -Inf), |
2117 CMPLX(0.1128379167099649964175513742247082845155e-5, | 2185 C(0.1128379167099649964175513742247082845155e-5, |
2118 0.2256758334191777400570377193451519478895e-5), | 2186 0.2256758334191777400570377193451519478895e-5), |
2119 CMPLX(0, | 2187 C(0, |
2120 0.2256758334194034158904576117253481476197e-5), | 2188 0.2256758334194034158904576117253481476197e-5), |
2121 CMPLX(0, | 2189 C(0, |
2122 18.56480241457555259870429191324101719886), | 2190 18.56480241457555259870429191324101719886), |
2123 CMPLX(0, | 2191 C(0, |
2124 0.1474797539628786202447733153131835124599e173), | 2192 0.1474797539628786202447733153131835124599e173), |
2125 CMPLX(0, | 2193 C(0, |
2126 Inf), | 2194 Inf), |
2127 CMPLX(1,0), | 2195 C(1,0), |
2128 CMPLX(-1,0), | 2196 C(-1,0), |
2129 CMPLX(0,Inf), | 2197 C(0,Inf), |
2130 CMPLX(0,-Inf), | 2198 C(0,-Inf), |
2131 CMPLX(NaN,NaN), | 2199 C(NaN,NaN), |
2132 CMPLX(NaN,NaN), | 2200 C(NaN,NaN), |
2133 CMPLX(NaN,NaN), | 2201 C(NaN,NaN), |
2134 CMPLX(NaN,0), | 2202 C(NaN,0), |
2135 CMPLX(0,NaN), | 2203 C(0,NaN), |
2136 CMPLX(NaN,NaN), | 2204 C(NaN,NaN), |
2137 CMPLX(NaN,NaN) | 2205 C(NaN,NaN), |
2206 C(NaN,NaN), | |
2207 C(0.07924380404615782687930591956705225541145, | |
2208 0.07872776218046681145537914954027729115247), | |
2209 C(0.07885775828512276968931773651224684454495, | |
2210 -0.0007860046704118224342390725280161272277506), | |
2211 C(-0.1012806432747198859687963080684978759881, | |
2212 0.0007834934747022035607566216654982820299469), | |
2213 C(-0.1020998418798097910247132140051062512527, | |
2214 0.1010030778892310851309082083238896270340), | |
2215 C(-0.0007962891763147907785684591823889484764272, | |
2216 0.1018289385936278171741809237435404896152), | |
2217 C(0.07886408666470478681566329888615410479530, | |
2218 0.01010604288780868961492224347707949372245), | |
2219 C(0.07886723099940260286824654364807981336591, | |
2220 0.01235199327873258197931147306290916629654) | |
2138 }; | 2221 }; |
2139 #define TST(f,isc) \ | 2222 #define TST(f,isc) \ |
2140 printf("############# " #f "(z) tests #############\n"); \ | 2223 printf("############# " #f "(z) tests #############\n"); \ |
2141 double errmax = 0; \ | 2224 double errmax = 0; \ |
2142 for (int i = 0; i < NTST; ++i) { \ | 2225 for (int i = 0; i < NTST; ++i) { \ |
2143 cmplx fw = FADDEEVA(f)(z[i],0.); \ | 2226 cmplx fw = FADDEEVA(f)(z[i],0.); \ |
2144 double re_err = relerr(creal(w[i]), creal(fw)); \ | 2227 double re_err = relerr(creal(w[i]), creal(fw)); \ |
2145 double im_err = relerr(cimag(w[i]), cimag(fw)); \ | 2228 double im_err = relerr(cimag(w[i]), cimag(fw)); \ |
2146 printf(#f "(%g%+gi) = %g%+gi (vs. %g%+gi), re/im rel. err. = %0.2g/%0.2g)\n", \ | 2229 printf(#f "(%g%+gi) = %g%+gi (vs. %g%+gi), re/im rel. err. = %0.2g/%0.2g)\n", \ |
2147 creal(z[i]),cimag(z[i]), creal(fw),cimag(fw), creal(w[i]),cimag(w[i]), \ | 2230 creal(z[i]),cimag(z[i]), creal(fw),cimag(fw), creal(w[i]),cimag(w[i]), \ |
2148 re_err, im_err); \ | 2231 re_err, im_err); \ |
2149 if (re_err > errmax) errmax = re_err; \ | 2232 if (re_err > errmax) errmax = re_err; \ |
2150 if (im_err > errmax) errmax = im_err; \ | 2233 if (im_err > errmax) errmax = im_err; \ |
2151 } \ | 2234 } \ |
2152 if (errmax > 1e-13) { \ | 2235 if (errmax > 1e-13) { \ |
2153 printf("FAILURE -- relative error %g too large!\n", errmax); \ | 2236 printf("FAILURE -- relative error %g too large!\n", errmax); \ |
2154 return 1; \ | 2237 return 1; \ |
2155 } \ | 2238 } \ |
2156 printf("Checking " #f "(x) special case...\n"); \ | 2239 printf("Checking " #f "(x) special case...\n"); \ |
2157 for (int i = 0; i < 10000; ++i) { \ | 2240 for (int i = 0; i < 10000; ++i) { \ |
2158 double x = pow(10., -300. + i * 600. / (10000 - 1)); \ | 2241 double x = pow(10., -300. + i * 600. / (10000 - 1)); \ |
2159 double re_err = relerr(FADDEEVA_RE(f)(x), \ | 2242 double re_err = relerr(FADDEEVA_RE(f)(x), \ |
2160 creal(FADDEEVA(f)(CMPLX(x,x*isc),0.))); \ | 2243 creal(FADDEEVA(f)(C(x,x*isc),0.))); \ |
2161 if (re_err > errmax) errmax = re_err; \ | 2244 if (re_err > errmax) errmax = re_err; \ |
2162 re_err = relerr(FADDEEVA_RE(f)(-x), \ | 2245 re_err = relerr(FADDEEVA_RE(f)(-x), \ |
2163 creal(FADDEEVA(f)(CMPLX(-x,x*isc),0.))); \ | 2246 creal(FADDEEVA(f)(C(-x,x*isc),0.))); \ |
2164 if (re_err > errmax) errmax = re_err; \ | 2247 if (re_err > errmax) errmax = re_err; \ |
2165 } \ | 2248 } \ |
2166 { \ | 2249 { \ |
2167 double re_err = relerr(FADDEEVA_RE(f)(Inf), \ | 2250 double re_err = relerr(FADDEEVA_RE(f)(Inf), \ |
2168 creal(FADDEEVA(f)(CMPLX(Inf,0.),0.))); \ | 2251 creal(FADDEEVA(f)(C(Inf,0.),0.))); \ |
2169 if (re_err > errmax) errmax = re_err; \ | 2252 if (re_err > errmax) errmax = re_err; \ |
2170 re_err = relerr(FADDEEVA_RE(f)(-Inf), \ | 2253 re_err = relerr(FADDEEVA_RE(f)(-Inf), \ |
2171 creal(FADDEEVA(f)(CMPLX(-Inf,0.),0.))); \ | 2254 creal(FADDEEVA(f)(C(-Inf,0.),0.))); \ |
2172 if (re_err > errmax) errmax = re_err; \ | 2255 if (re_err > errmax) errmax = re_err; \ |
2173 re_err = relerr(FADDEEVA_RE(f)(NaN), \ | 2256 re_err = relerr(FADDEEVA_RE(f)(NaN), \ |
2174 creal(FADDEEVA(f)(CMPLX(NaN,0.),0.))); \ | 2257 creal(FADDEEVA(f)(C(NaN,0.),0.))); \ |
2175 if (re_err > errmax) errmax = re_err; \ | 2258 if (re_err > errmax) errmax = re_err; \ |
2176 } \ | 2259 } \ |
2177 if (errmax > 1e-13) { \ | 2260 if (errmax > 1e-13) { \ |
2178 printf("FAILURE -- relative error %g too large!\n", errmax); \ | 2261 printf("FAILURE -- relative error %g too large!\n", errmax); \ |
2179 return 1; \ | 2262 return 1; \ |
2180 } \ | 2263 } \ |
2181 printf("SUCCESS (max relative error = %g)\n", errmax); \ | 2264 printf("SUCCESS (max relative error = %g)\n", errmax); \ |
2182 if (errmax > errmax_all) errmax_all = errmax | 2265 if (errmax > errmax_all) errmax_all = errmax |
2183 | 2266 |
2184 TST(erf, 1e-20); | 2267 TST(erf, 1e-20); |
2185 } | 2268 } |
2186 { | 2269 { |
2187 // since erfi just calls through to erf, just one test should | 2270 // since erfi just calls through to erf, just one test should |
2188 // be sufficient to make sure I didn't screw up the signs or something | 2271 // be sufficient to make sure I didn't screw up the signs or something |
2189 #undef NTST | 2272 #undef NTST |
2190 #define NTST 1 // define instead of const for C compatibility | 2273 #define NTST 1 // define instead of const for C compatibility |
2191 cmplx z[NTST] = { CMPLX(1.234,0.5678) }; | 2274 cmplx z[NTST] = { C(1.234,0.5678) }; |
2192 cmplx w[NTST] = { // erfi(z[i]), computed with Maple | 2275 cmplx w[NTST] = { // erfi(z[i]), computed with Maple |
2193 CMPLX(1.081032284405373149432716643834106923212, | 2276 C(1.081032284405373149432716643834106923212, |
2194 1.926775520840916645838949402886591180834) | 2277 1.926775520840916645838949402886591180834) |
2195 }; | 2278 }; |
2196 TST(erfi, 0); | 2279 TST(erfi, 0); |
2197 } | 2280 } |
2198 { | 2281 { |
2199 // since erfcx just calls through to w, just one test should | 2282 // since erfcx just calls through to w, just one test should |
2200 // be sufficient to make sure I didn't screw up the signs or something | 2283 // be sufficient to make sure I didn't screw up the signs or something |
2201 #undef NTST | 2284 #undef NTST |
2202 #define NTST 1 // define instead of const for C compatibility | 2285 #define NTST 1 // define instead of const for C compatibility |
2203 cmplx z[NTST] = { CMPLX(1.234,0.5678) }; | 2286 cmplx z[NTST] = { C(1.234,0.5678) }; |
2204 cmplx w[NTST] = { // erfcx(z[i]), computed with Maple | 2287 cmplx w[NTST] = { // erfcx(z[i]), computed with Maple |
2205 CMPLX(0.3382187479799972294747793561190487832579, | 2288 C(0.3382187479799972294747793561190487832579, |
2206 -0.1116077470811648467464927471872945833154) | 2289 -0.1116077470811648467464927471872945833154) |
2207 }; | 2290 }; |
2208 TST(erfcx, 0); | 2291 TST(erfcx, 0); |
2209 } | 2292 } |
2210 { | 2293 { |
2211 #undef NTST | 2294 #undef NTST |
2212 #define NTST 30 // define instead of const for C compatibility | 2295 #define NTST 30 // define instead of const for C compatibility |
2213 cmplx z[NTST] = { | 2296 cmplx z[NTST] = { |
2214 CMPLX(1,2), | 2297 C(1,2), |
2215 CMPLX(-1,2), | 2298 C(-1,2), |
2216 CMPLX(1,-2), | 2299 C(1,-2), |
2217 CMPLX(-1,-2), | 2300 C(-1,-2), |
2218 CMPLX(9,-28), | 2301 C(9,-28), |
2219 CMPLX(21,-33), | 2302 C(21,-33), |
2220 CMPLX(1e3,1e3), | 2303 C(1e3,1e3), |
2221 CMPLX(-3001,-1000), | 2304 C(-3001,-1000), |
2222 CMPLX(1e160,-1e159), | 2305 C(1e160,-1e159), |
2223 CMPLX(5.1e-3, 1e-8), | 2306 C(5.1e-3, 1e-8), |
2224 CMPLX(0,2e-6), | 2307 C(0,2e-6), |
2225 CMPLX(0,2), | 2308 C(0,2), |
2226 CMPLX(0,20), | 2309 C(0,20), |
2227 CMPLX(0,200), | 2310 C(0,200), |
2228 CMPLX(2e-6,0), | 2311 C(2e-6,0), |
2229 CMPLX(2,0), | 2312 C(2,0), |
2230 CMPLX(20,0), | 2313 C(20,0), |
2231 CMPLX(200,0), | 2314 C(200,0), |
2232 CMPLX(Inf,0), | 2315 C(Inf,0), |
2233 CMPLX(-Inf,0), | 2316 C(-Inf,0), |
2234 CMPLX(0,Inf), | 2317 C(0,Inf), |
2235 CMPLX(0,-Inf), | 2318 C(0,-Inf), |
2236 CMPLX(Inf,Inf), | 2319 C(Inf,Inf), |
2237 CMPLX(Inf,-Inf), | 2320 C(Inf,-Inf), |
2238 CMPLX(NaN,NaN), | 2321 C(NaN,NaN), |
2239 CMPLX(NaN,0), | 2322 C(NaN,0), |
2240 CMPLX(0,NaN), | 2323 C(0,NaN), |
2241 CMPLX(NaN,Inf), | 2324 C(NaN,Inf), |
2242 CMPLX(Inf,NaN), | 2325 C(Inf,NaN), |
2243 CMPLX(88,0) | 2326 C(88,0) |
2244 }; | 2327 }; |
2245 cmplx w[NTST] = { // erfc(z[i]), evaluated with Maple | 2328 cmplx w[NTST] = { // erfc(z[i]), evaluated with Maple |
2246 CMPLX(1.536643565778565033991795559314192749442, | 2329 C(1.536643565778565033991795559314192749442, |
2247 5.049143703447034669543036958614140565553), | 2330 5.049143703447034669543036958614140565553), |
2248 CMPLX(0.4633564342214349660082044406858072505579, | 2331 C(0.4633564342214349660082044406858072505579, |
2249 5.049143703447034669543036958614140565553), | 2332 5.049143703447034669543036958614140565553), |
2250 CMPLX(1.536643565778565033991795559314192749442, | 2333 C(1.536643565778565033991795559314192749442, |
2251 -5.049143703447034669543036958614140565553), | 2334 -5.049143703447034669543036958614140565553), |
2252 CMPLX(0.4633564342214349660082044406858072505579, | 2335 C(0.4633564342214349660082044406858072505579, |
2253 -5.049143703447034669543036958614140565553), | 2336 -5.049143703447034669543036958614140565553), |
2254 CMPLX(-0.3359473673830576996788000505817956637777e304, | 2337 C(-0.3359473673830576996788000505817956637777e304, |
2255 0.1999896139679880888755589794455069208455e304), | 2338 0.1999896139679880888755589794455069208455e304), |
2256 CMPLX(-0.3584459971462946066523939204836760283645e278, | 2339 C(-0.3584459971462946066523939204836760283645e278, |
2257 -0.3818954885257184373734213077678011282505e280), | 2340 -0.3818954885257184373734213077678011282505e280), |
2258 CMPLX(0.0003979577342851360897849852457775473112748, | 2341 C(0.0003979577342851360897849852457775473112748, |
2259 -0.00002801044116908227889681753993542916894856), | 2342 -0.00002801044116908227889681753993542916894856), |
2260 CMPLX(2, 0), | 2343 C(2, 0), |
2261 CMPLX(0, 0), | 2344 C(0, 0), |
2262 CMPLX(0.9942453161409651998655870094589234450651, | 2345 C(0.9942453161409651998655870094589234450651, |
2263 -0.1128349818335058741511924929801267822634e-7), | 2346 -0.1128349818335058741511924929801267822634e-7), |
2264 CMPLX(1, | 2347 C(1, |
2265 -0.2256758334194034158904576117253481476197e-5), | 2348 -0.2256758334194034158904576117253481476197e-5), |
2266 CMPLX(1, | 2349 C(1, |
2267 -18.56480241457555259870429191324101719886), | 2350 -18.56480241457555259870429191324101719886), |
2268 CMPLX(1, | 2351 C(1, |
2269 -0.1474797539628786202447733153131835124599e173), | 2352 -0.1474797539628786202447733153131835124599e173), |
2270 CMPLX(1, -Inf), | 2353 C(1, -Inf), |
2271 CMPLX(0.9999977432416658119838633199332831406314, | 2354 C(0.9999977432416658119838633199332831406314, |
2272 0), | 2355 0), |
2273 CMPLX(0.004677734981047265837930743632747071389108, | 2356 C(0.004677734981047265837930743632747071389108, |
2274 0), | 2357 0), |
2275 CMPLX(0.5395865611607900928934999167905345604088e-175, | 2358 C(0.5395865611607900928934999167905345604088e-175, |
2276 0), | 2359 0), |
2277 CMPLX(0, 0), | 2360 C(0, 0), |
2278 CMPLX(0, 0), | 2361 C(0, 0), |
2279 CMPLX(2, 0), | 2362 C(2, 0), |
2280 CMPLX(1, -Inf), | 2363 C(1, -Inf), |
2281 CMPLX(1, Inf), | 2364 C(1, Inf), |
2282 CMPLX(NaN, NaN), | 2365 C(NaN, NaN), |
2283 CMPLX(NaN, NaN), | 2366 C(NaN, NaN), |
2284 CMPLX(NaN, NaN), | 2367 C(NaN, NaN), |
2285 CMPLX(NaN, 0), | 2368 C(NaN, 0), |
2286 CMPLX(1, NaN), | 2369 C(1, NaN), |
2287 CMPLX(NaN, NaN), | 2370 C(NaN, NaN), |
2288 CMPLX(NaN, NaN), | 2371 C(NaN, NaN), |
2289 CMPLX(0,0) | 2372 C(0,0) |
2290 }; | 2373 }; |
2291 TST(erfc, 1e-20); | 2374 TST(erfc, 1e-20); |
2292 } | 2375 } |
2293 { | 2376 { |
2294 #undef NTST | 2377 #undef NTST |
2295 #define NTST 47 // define instead of const for C compatibility | 2378 #define NTST 48 // define instead of const for C compatibility |
2296 cmplx z[NTST] = { | 2379 cmplx z[NTST] = { |
2297 CMPLX(2,1), | 2380 C(2,1), |
2298 CMPLX(-2,1), | 2381 C(-2,1), |
2299 CMPLX(2,-1), | 2382 C(2,-1), |
2300 CMPLX(-2,-1), | 2383 C(-2,-1), |
2301 CMPLX(-28,9), | 2384 C(-28,9), |
2302 CMPLX(33,-21), | 2385 C(33,-21), |
2303 CMPLX(1e3,1e3), | 2386 C(1e3,1e3), |
2304 CMPLX(-1000,-3001), | 2387 C(-1000,-3001), |
2305 CMPLX(1e-8, 5.1e-3), | 2388 C(1e-8, 5.1e-3), |
2306 CMPLX(4.95e-3, -4.9e-3), | 2389 C(4.95e-3, -4.9e-3), |
2307 CMPLX(0.5, 4.9e-3), | 2390 C(5.1e-3, 5.1e-3), |
2308 CMPLX(-0.5e1, 4.9e-4), | 2391 C(0.5, 4.9e-3), |
2309 CMPLX(-0.5e2, -4.9e-5), | 2392 C(-0.5e1, 4.9e-4), |
2310 CMPLX(0.5e3, 4.9e-6), | 2393 C(-0.5e2, -4.9e-5), |
2311 CMPLX(0.5, 5.1e-3), | 2394 C(0.5e3, 4.9e-6), |
2312 CMPLX(-0.5e1, 5.1e-4), | 2395 C(0.5, 5.1e-3), |
2313 CMPLX(-0.5e2, -5.1e-5), | 2396 C(-0.5e1, 5.1e-4), |
2314 CMPLX(1e-6,2e-6), | 2397 C(-0.5e2, -5.1e-5), |
2315 CMPLX(2e-6,0), | 2398 C(1e-6,2e-6), |
2316 CMPLX(2,0), | 2399 C(2e-6,0), |
2317 CMPLX(20,0), | 2400 C(2,0), |
2318 CMPLX(200,0), | 2401 C(20,0), |
2319 CMPLX(0,4.9e-3), | 2402 C(200,0), |
2320 CMPLX(0,-5.1e-3), | 2403 C(0,4.9e-3), |
2321 CMPLX(0,2e-6), | 2404 C(0,-5.1e-3), |
2322 CMPLX(0,-2), | 2405 C(0,2e-6), |
2323 CMPLX(0,20), | 2406 C(0,-2), |
2324 CMPLX(0,-200), | 2407 C(0,20), |
2325 CMPLX(Inf,0), | 2408 C(0,-200), |
2326 CMPLX(-Inf,0), | 2409 C(Inf,0), |
2327 CMPLX(0,Inf), | 2410 C(-Inf,0), |
2328 CMPLX(0,-Inf), | 2411 C(0,Inf), |
2329 CMPLX(Inf,Inf), | 2412 C(0,-Inf), |
2330 CMPLX(Inf,-Inf), | 2413 C(Inf,Inf), |
2331 CMPLX(NaN,NaN), | 2414 C(Inf,-Inf), |
2332 CMPLX(NaN,0), | 2415 C(NaN,NaN), |
2333 CMPLX(0,NaN), | 2416 C(NaN,0), |
2334 CMPLX(NaN,Inf), | 2417 C(0,NaN), |
2335 CMPLX(Inf,NaN), | 2418 C(NaN,Inf), |
2336 CMPLX(39, 6.4e-5), | 2419 C(Inf,NaN), |
2337 CMPLX(41, 6.09e-5), | 2420 C(39, 6.4e-5), |
2338 CMPLX(4.9e7, 5e-11), | 2421 C(41, 6.09e-5), |
2339 CMPLX(5.1e7, 4.8e-11), | 2422 C(4.9e7, 5e-11), |
2340 CMPLX(1e9, 2.4e-12), | 2423 C(5.1e7, 4.8e-11), |
2341 CMPLX(1e11, 2.4e-14), | 2424 C(1e9, 2.4e-12), |
2342 CMPLX(1e13, 2.4e-16), | 2425 C(1e11, 2.4e-14), |
2343 CMPLX(1e300, 2.4e-303) | 2426 C(1e13, 2.4e-16), |
2427 C(1e300, 2.4e-303) | |
2344 }; | 2428 }; |
2345 cmplx w[NTST] = { // dawson(z[i]), evaluated with Maple | 2429 cmplx w[NTST] = { // dawson(z[i]), evaluated with Maple |
2346 CMPLX(0.1635394094345355614904345232875688576839, | 2430 C(0.1635394094345355614904345232875688576839, |
2347 -0.1531245755371229803585918112683241066853), | 2431 -0.1531245755371229803585918112683241066853), |
2348 CMPLX(-0.1635394094345355614904345232875688576839, | 2432 C(-0.1635394094345355614904345232875688576839, |
2349 -0.1531245755371229803585918112683241066853), | 2433 -0.1531245755371229803585918112683241066853), |
2350 CMPLX(0.1635394094345355614904345232875688576839, | 2434 C(0.1635394094345355614904345232875688576839, |
2351 0.1531245755371229803585918112683241066853), | 2435 0.1531245755371229803585918112683241066853), |
2352 CMPLX(-0.1635394094345355614904345232875688576839, | 2436 C(-0.1635394094345355614904345232875688576839, |
2353 0.1531245755371229803585918112683241066853), | 2437 0.1531245755371229803585918112683241066853), |
2354 CMPLX(-0.01619082256681596362895875232699626384420, | 2438 C(-0.01619082256681596362895875232699626384420, |
2355 -0.005210224203359059109181555401330902819419), | 2439 -0.005210224203359059109181555401330902819419), |
2356 CMPLX(0.01078377080978103125464543240346760257008, | 2440 C(0.01078377080978103125464543240346760257008, |
2357 0.006866888783433775382193630944275682670599), | 2441 0.006866888783433775382193630944275682670599), |
2358 CMPLX(-0.5808616819196736225612296471081337245459, | 2442 C(-0.5808616819196736225612296471081337245459, |
2359 0.6688593905505562263387760667171706325749), | 2443 0.6688593905505562263387760667171706325749), |
2360 CMPLX(Inf, | 2444 C(Inf, |
2361 -Inf), | 2445 -Inf), |
2362 CMPLX(0.1000052020902036118082966385855563526705e-7, | 2446 C(0.1000052020902036118082966385855563526705e-7, |
2363 0.005100088434920073153418834680320146441685), | 2447 0.005100088434920073153418834680320146441685), |
2364 CMPLX(0.004950156837581592745389973960217444687524, | 2448 C(0.004950156837581592745389973960217444687524, |
2365 -0.004899838305155226382584756154100963570500), | 2449 -0.004899838305155226382584756154100963570500), |
2366 CMPLX(0.4244534840871830045021143490355372016428, | 2450 C(0.005100176864319675957314822982399286703798, |
2367 0.002820278933186814021399602648373095266538), | 2451 0.005099823128319785355949825238269336481254), |
2368 CMPLX(-0.1021340733271046543881236523269967674156, | 2452 C(0.4244534840871830045021143490355372016428, |
2369 -0.00001045696456072005761498961861088944159916), | 2453 0.002820278933186814021399602648373095266538), |
2370 CMPLX(-0.01000200120119206748855061636187197886859, | 2454 C(-0.1021340733271046543881236523269967674156, |
2371 0.9805885888237419500266621041508714123763e-8), | 2455 -0.00001045696456072005761498961861088944159916), |
2372 CMPLX(0.001000002000012000023960527532953151819595, | 2456 C(-0.01000200120119206748855061636187197886859, |
2373 -0.9800058800588007290937355024646722133204e-11), | 2457 0.9805885888237419500266621041508714123763e-8), |
2374 CMPLX(0.4244549085628511778373438768121222815752, | 2458 C(0.001000002000012000023960527532953151819595, |
2375 0.002935393851311701428647152230552122898291), | 2459 -0.9800058800588007290937355024646722133204e-11), |
2376 CMPLX(-0.1021340732357117208743299813648493928105, | 2460 C(0.4244549085628511778373438768121222815752, |
2377 -0.00001088377943049851799938998805451564893540), | 2461 0.002935393851311701428647152230552122898291), |
2378 CMPLX(-0.01000200120119126652710792390331206563616, | 2462 C(-0.1021340732357117208743299813648493928105, |
2379 0.1020612612857282306892368985525393707486e-7), | 2463 -0.00001088377943049851799938998805451564893540), |
2380 CMPLX(0.1000000000007333333333344266666666664457e-5, | 2464 C(-0.01000200120119126652710792390331206563616, |
2381 0.2000000000001333333333323199999999978819e-5), | 2465 0.1020612612857282306892368985525393707486e-7), |
2382 CMPLX(0.1999999999994666666666675199999999990248e-5, | 2466 C(0.1000000000007333333333344266666666664457e-5, |
2383 0), | 2467 0.2000000000001333333333323199999999978819e-5), |
2384 CMPLX(0.3013403889237919660346644392864226952119, | 2468 C(0.1999999999994666666666675199999999990248e-5, |
2385 0), | 2469 0), |
2386 CMPLX(0.02503136792640367194699495234782353186858, | 2470 C(0.3013403889237919660346644392864226952119, |
2387 0), | 2471 0), |
2388 CMPLX(0.002500031251171948248596912483183760683918, | 2472 C(0.02503136792640367194699495234782353186858, |
2389 0), | 2473 0), |
2390 CMPLX(0,0.004900078433419939164774792850907128053308), | 2474 C(0.002500031251171948248596912483183760683918, |
2391 CMPLX(0,-0.005100088434920074173454208832365950009419), | 2475 0), |
2392 CMPLX(0,0.2000000000005333333333341866666666676419e-5), | 2476 C(0,0.004900078433419939164774792850907128053308), |
2393 CMPLX(0,-48.16001211429122974789822893525016528191), | 2477 C(0,-0.005100088434920074173454208832365950009419), |
2394 CMPLX(0,0.4627407029504443513654142715903005954668e174), | 2478 C(0,0.2000000000005333333333341866666666676419e-5), |
2395 CMPLX(0,-Inf), | 2479 C(0,-48.16001211429122974789822893525016528191), |
2396 CMPLX(0,0), | 2480 C(0,0.4627407029504443513654142715903005954668e174), |
2397 CMPLX(-0,0), | 2481 C(0,-Inf), |
2398 CMPLX(0, Inf), | 2482 C(0,0), |
2399 CMPLX(0, -Inf), | 2483 C(-0,0), |
2400 CMPLX(NaN, NaN), | 2484 C(0, Inf), |
2401 CMPLX(NaN, NaN), | 2485 C(0, -Inf), |
2402 CMPLX(NaN, NaN), | 2486 C(NaN, NaN), |
2403 CMPLX(NaN, 0), | 2487 C(NaN, NaN), |
2404 CMPLX(0, NaN), | 2488 C(NaN, NaN), |
2405 CMPLX(NaN, NaN), | 2489 C(NaN, 0), |
2406 CMPLX(NaN, NaN), | 2490 C(0, NaN), |
2407 CMPLX(0.01282473148489433743567240624939698290584, | 2491 C(NaN, NaN), |
2408 -0.2105957276516618621447832572909153498104e-7), | 2492 C(NaN, NaN), |
2409 CMPLX(0.01219875253423634378984109995893708152885, | 2493 C(0.01282473148489433743567240624939698290584, |
2410 -0.1813040560401824664088425926165834355953e-7), | 2494 -0.2105957276516618621447832572909153498104e-7), |
2411 CMPLX(0.1020408163265306334945473399689037886997e-7, | 2495 C(0.01219875253423634378984109995893708152885, |
2412 -0.1041232819658476285651490827866174985330e-25), | 2496 -0.1813040560401824664088425926165834355953e-7), |
2413 CMPLX(0.9803921568627452865036825956835185367356e-8, | 2497 C(0.1020408163265306334945473399689037886997e-7, |
2414 -0.9227220299884665067601095648451913375754e-26), | 2498 -0.1041232819658476285651490827866174985330e-25), |
2415 CMPLX(0.5000000000000000002500000000000000003750e-9, | 2499 C(0.9803921568627452865036825956835185367356e-8, |
2416 -0.1200000000000000001800000188712838420241e-29), | 2500 -0.9227220299884665067601095648451913375754e-26), |
2417 CMPLX(5.00000000000000000000025000000000000000000003e-12, | 2501 C(0.5000000000000000002500000000000000003750e-9, |
2418 -1.20000000000000000000018000000000000000000004e-36), | 2502 -0.1200000000000000001800000188712838420241e-29), |
2419 CMPLX(5.00000000000000000000000002500000000000000000e-14, | 2503 C(5.00000000000000000000025000000000000000000003e-12, |
2420 -1.20000000000000000000000001800000000000000000e-42), | 2504 -1.20000000000000000000018000000000000000000004e-36), |
2421 CMPLX(5e-301, 0) | 2505 C(5.00000000000000000000000002500000000000000000e-14, |
2506 -1.20000000000000000000000001800000000000000000e-42), | |
2507 C(5e-301, 0) | |
2422 }; | 2508 }; |
2423 TST(Dawson, 1e-20); | 2509 TST(Dawson, 1e-20); |
2424 } | 2510 } |
2425 printf("#####################################\n"); | 2511 printf("#####################################\n"); |
2426 printf("SUCCESS (max relative error = %g)\n", errmax_all); | 2512 printf("SUCCESS (max relative error = %g)\n", errmax_all); |