C++ source code for compiled plugins (MEX files) to compute various error functions for complex arguments:
** Faddeeva_erf(z) -- the error function
** Faddeeva_erfc(z) = 1 - erf(z) -- complementary error function
** Faddeeva_erfi(z) = -i erf(iz) -- imaginary error function
** Faddeeva_erfcx(z) = exp(z^2) erfc(z) -- scaled complementary error function
** Faddeeva_w(z) = exp(-z^2) erfc(-iz) -- Faddeeva function
** Faddeeva_Dawson(z) = 0.5 sqrt(pi) exp(-z^2) erfi(z) -- Dawson function
From e.g. the Faddeeva function, one can also obtain the Voigt functions and other related functions.
Assuming you have a C++ compiler (and have configured it in MATLAB with mex -setup), compile by running the included Faddeeva_build.m script in MATLAB:
All of the functions have usage of the form:
w = Faddeeva_w(z)
or optionally Faddeeva_w(z, relerr), where relerr is a desired relative error (default: machine precision). z may be an array or matrix of complex or real numbers.
This code may also be downloaded from
along with documentation and other versions. As described in the source code, this implementation uses a combination of algorithms for the Faddeeva function: a continued-fraction expansion for large |z| [similar to G. P. M. Poppe and C. M. J. Wijers, "More efficient computation of the complex error function," ACM Trans. Math. Soft. 16 (1), pp. 38–46 (1990)], and a completely different algorithm for smaller |z| [Mofreh R. Zaghloul and Ahmed N. Ali, "Algorithm 916: Computing the Faddeyeva and Voigt Functions," ACM Trans. Math. Soft. 38 (2), 15 (2011).]. Given the Faddeeva function, we can then compute the other error functions, although we must switch to Taylor expansions and use other tricks in certain regions of the complex plane to avoid cancellation errors or other floating-point problems.
BTW, substitute Eq.5 from paper by Zaker, J Comp Phys 1969
in Faddeeva definition w(z)=exp(-z^2)*(1-erf(-i*z)) and isolate real and imaginary terms "to derive" in one line those approximations for smaller |z|. Too trivial actually...
I analysed this code and it's appeared to be nothing but a modified Poppe and Wijers algorithm. Only a tiny bit of origin's area for smaller |z| is computed by Salzer's approximations of the Faddeeva function. Rest is Poppe and Wijers, I guess. Aren't so, Steven?
Much faster than the symbolic erf function. Worked for me well on MATLAB 2018a in Windows 10 after following the instructions Andrew posted about MinGW.
So, how do you run this one?
I cannot run C++ files via Matlab! I followed all recommended instructions and could not do anything because of permanent errors. It's a headache and terrible frustration to adjust a computer to run these non-native C++ files from the Matlab environment. Could you please translate these C++ files to Matlab instead?
0.1905 + 1.3162i
which is different from
1.3162 + 0.1905i
Why? I make mex function using Mac.
Run with Matlab 2017a and compiled with MinGW64 Compiler (C++), it gets
Faddeeva.cc: In function 'cmplx Faddeeva::w(cmplx, double)':
Faddeeva.cc:970:54: error: '_copysign' was not declared in this scope (0.5*c)*copysign(sum5-sum4, creal(z)));
Faddeeva.cc:179:26: note: in definition of macro 'C' # define C(a,b) cmplx(a,b)
Is that problem with the MinGW64 Compiler or else?
I found another Faddeeva / Voigt function that is just as good (maybe better?), and already in MATLAB format (no need for compilers):
I have discovered that MinGW is not compatible with MATLAB R2015a.
Instead I was able to use SDK 7.1 on Windows 10.
To help others do this, If you install SDK 7.1 from this link:
and still have problems, such as typing into MATLAB
and then receiving the error:
No supported SDK or compiler was found on this computer.
For a list of supported compilers, see
This means that you need to follow the instructions on this page:
This worked for me with Windows 10 MATLAB 2015a.
Has anyone got a C++ compiler for this to work on:
MATLAB R2015a (22.214.171.124613)
If so, please tell me step by step instructions (I have spent a day trying to make this work, and really need to get fitting data for a publication that is under a review deadline.)
This is a fantastic implementation. This code works about 2000x faster for me (when tested with large multidimensional arrays) than the built-in Matlab erfi function.
Alternatively, the Symbolic Math Toolbox provides the error and dawson functions for complex inputs.
Take the error function for example:
1.3162 + 0.1905i
You could define an anonymous function to make it easier:
>> erfCmplx = @(x) double(erf(sym(x)))
1.3162 + 0.1905i
The Symbolic Math Toolbox functions are:
One update I would really like to see in this package is the derivative functions, at least for W(z). As pointed out in Zaghloul and Ali, the derivative functions of W(z) (equations 21-23) become numerically unstable near dV/dx = 0 (V=real(W(z)), at the peak of the Voigt function. This can cause problems when trying to compute analytical Jacobians for doing nonlinear fits of the Voigt function to optical spectra.
Since you are already using the Zaghloul and Ali algorithm in this region, it would be helpful to also use their method to output a function, say Faddeeva_dw(z) = dV/dx + i*dL/dx (L=imag(W(z)). The corresponding y derivatives can then be trivially computed.
Works as advertised and is extremely fast.
It won't work with lcc, since that is a C compiler, not a C++ compiler. The failure to compile with Visual C++ is a bug, which is fixed in the latest release on my web site (and which should appear on Matlab Central shortly).
Hello, Love this program. I have it up and running on my mac to simulate voigt broadening. Im trying to add this functionality to a lab computer running win32 matlab 7.12.0 (R2011a), but I cannot successfully compile with mex.
With Lcc-win32 C 2.4.1 in C:\PROGRA~1\MATLAB\R2011a\sys\lcc: lcc preprocessor error: .\Faddeeva.hh:30 .\Faddeeva_mex.cc:35 Faddeeva_w_mex.cc:3 Could not find include file complex
full verbose: http://pastebin.com/YyLYYe8C
With Microsoft Visual C++ 2010 Express in C:\Program Files\Microsoft Visual Studio 10.0: Faddeeva.cc Faddeeva.cc(184) : error C2124: divide or mod by zero Faddeeva.cc(822) : error C3861: 'copysign': identifier not found C:\PROGRA~1\MATLAB\R2011A\BIN\MEX.PL: Error: Compile of 'Faddeeva.cc' failed.
full verbose: http://pastebin.com/K4LPd9FN
The only instances of complex.h are in a pythonwx folder not related to matlab. I see that it was released for R2012a. Does the package need a specific C++ compiler?
portability fixes, slight accuracy improvements
Now includes separate plugins for all of the error functions.
note how to compute erfi using Faddeeva function
Improve accuracy in Re[w(z)] taken by itself.
Inspired: Voigt model fit