Numerical precision - dawson(x) vs erfcw(real(x+iy))
For the phase fit, I use the complex error function erfcw when both a doppler (pressure) and lorentzian (collision) component is present, and the Dawson integral when only a doppler component is expected.
I noticed that I don't get the same phase using erfcw or dawson for doppler-only lineshapes. Ideally (i.e. analytically),
dawson(x)*2/sqrt(pi) = imag(erfcw(cmplx(x,0))
I noticed that this relationship is only true for |x|<~5; this is shown in the attached graph created with the macro at the bottom. Can anyone tell me which calculation is more accurate for large x?
thanks,
Fabrizio
macro testIt()<br />
make/d/o/n=1000 Wdaw, Werf, delta; setscale/I x -50,50, Wdaw, Werf, delta<br />
Wdaw=2/sqrt(pi)*dawson(x)<br />
werf=imag(erfcw(cmplx(x,0)))<br />
delta=abs((wdaw-werf)/werf)<br />
display delta; ModifyGraph log(left)=1<br />
endmacro
Your macro uses the function erfcw() which is not in my version of IP (obviously my home copy needs an update).
The Dawson integral is computed from a series approximation. The erfc is usually computed from the Hyper-Geometric function which is, in general, a very messy series calculation. In other words both of these are not simple. IIRC the Dawson expression is going to be more accurate closer to zero. For large arguments I still expect the Dawson integral to be more accurate. There is a brief discussion of Dawson's accuracy in the reference provided in the IGOR help file.
If I had to guess (and if accuracy at large x really mattered to me) I'd use Dawson because it is a simpler and more straightforward calculation. If the built-in Dawson function does not provide sufficient accuracy one can look into using better expansions. Feel free to send details of your application and requirements to support@wavemetrics.com if you want us to help.
A.G.
WaveMetrics, Inc.
June 27, 2011 at 11:14 am - Permalink
After a bit more investigation here are some details:
The Dawson integral is evaluated from a series of 24 terms. When x is large (x>20) you are going to see some degradation in accuracy simply because the integrand becomes unstable numerically. Erfcw is said to have accuracy to about 14 digits. The primary expansion in this approach is relatively more stable for large x.
If accuracy is really important you can have a bit more control (at the cost of computation time) using the error function. Note that the Dawson integral can also be evaluated using
Function/c FF(zz)
Variable/C zz
return -cmplx(0,(sqrt(pi)/2))*exp(-zz*zz)*erf(cmplx(0,1)*zz)
End
The advantage here is that erf() in the last expression can take an accuracy parameter. A word of caution though is that for large arguments and decent accuracy the hypergeometric function 1F1() used to compute the erf() can take a long time to converge.
HTH,
A.G.
WaveMetrics, Inc.
June 27, 2011 at 12:04 pm - Permalink
I just had a chance to compare with matlab. In Matlab, I used the built-in Dawson function and implemented the complex error function (aka Faddeeva function) according to J. A. C Weideman, 'Computation of the Complex Error Function', SIAM Journal on Numerical Analysis, Vol. 31, No 5 (Oct. 1994), pp. 1497-1518, using 30 terms.
The Matlab dawson agrees very well with the Igor erfcw, and the Weideman complex error function in Matlab is still doing fairly well, however the Igor Dawson stands apart... (see attached figure). More specifically, the igor Dawson function converges faster (I assume too fast...) towards zero for |x|>5.
I use Igor 6.2.2.2 on windows XP; the erfcw function seems to be part of Igor and is also described in the online and pdf help ... ?
June 28, 2011 at 12:35 pm - Permalink
John Weeks
WaveMetrics, Inc.
support@wavemetrics.com
October 27, 2016 at 12:25 pm - Permalink
In honor of John's retirement, I shall resurrect this 10 yr old thread. (ha!) I have an option to choose between a Dawson integral form or an error function form of an expression in numerical calculations. My colleague prefers the former from a first-principled derivation perspective, and I prefer the latter both for ease in making a larger expression dimensionless by removing common factors and for commonality in numerical analysis (i.e. error functions are more "colloquial" than Dawson's integrals).
Just for my own information, I referenced the link below. I am interested in the D+ case.
https://en.wikipedia.org/wiki/Dawson_function
As near as I can now determine, for exact translation between the Dawson integral and error function forms, I must input a complex number to the erf(...) function in Igor Pro and pull off the imaginary component. Hence, the two functions below give the same report for any input.
My question is whether the second function can be written directly to "keep it all real"?? By example, just guessing, I tried the function below.
For additional background, I am interested in capturing the equivalence only in the range of positive, real kappa. And I am satisfied with a relative accuracy at the ppm level.
October 22, 2026 at 05:18 pm - Permalink
Hello JJ,
I wrote the original Dawson function using code that I wrote in the 1980's. It used quadrature to compute the integral over the range that was good enough for my PhD work. Some 20 years later JW replaced the code with a function from the Faddeeva package that boasts higher accuracy. You can read more about the package here: http://ab-initio.mit.edu/Faddeeva.
Igor's various error functions are calculated using different algorithms with varying levels of accuracy:
Function Argument Algorithm
erf real Incomplete gamma: P(1/2, x^2)
erfc real Incomplete gamma: Q(1/2, x^2), or 1+P(1/2, x^2) for x<0
erf complex (2z/sqrt(pi)) * 1F1(1/2; 3/2; -z^2)
erfc complex 1 - erf(z) via the hypergeometric series
erfcw complex Poppe & Wijers, ACM TOMS 16(1), 38-46 (1990)
erfcx real Polynomial approximation (fma-based)
For accuracy reasons I'd stay with Dawson based in the Faddeeva package especially in view of the fact that some of the hypergeometric functions are sometimes difficult to push to high accuracy.
HTH,
AG
October 23, 2026 at 12:30 pm - Permalink
Thanks AG. Just curious though. As near as I see, if I input a complex number to the error function, I am tapping into the Faddeeva routine just as in the Dawson function. So, the two functions that I report are equivalent ways in Igor Pro to calculate the same value and should exhibit nearly the same accuracy and speed??
Just for further background, my colleague arrived at the Dawson integral form using derivations by hand. The input was Z = sqrt(X) whereby X is constrained to be positive even though foundations require X to be negative. It seems perhaps that Dawson(Z(positive real)) = Dawson(-i*|Z|(negative complex)) (symmetry). My derivations with symbolic math (Maple in this case) resulted in the error function form, whereby Maple's error function input allowed X to be negative, resulting in a complex Z, resulting in a final agreement. I attach a report from within Maple showing three equivalent ways to obtain the same value in the function we are investigating.
Finally, had you asked me about three weeks ago whether I knew anything about Dawson's integral, I would have said ... Isn't there a TV show with that name? But, everyone in college calculus has been introduced to the error function. Hence my desire to provide future readers of our collaborative publication something that is familiar (error function) even as I now better respect the equivalence (and potential benefits) of using the Dawson's integral.
--
JJW
October 23, 2026 at 01:33 pm - Permalink
Hello JJ,
I think you misunderstood the table in my last comment. If you execute, e.g.,
Igor computes the erf() via the HyperGeometric function.
AG
October 23, 2026 at 02:41 pm - Permalink
Apologies. I mistook 1F1 as the Faddeeva package approach.
All is now clear.
Thanks!
October 23, 2026 at 05:53 pm - Permalink