## errorfunctions

Pure Rust package to compute the error function, Dawson's function, and Faddeeva's function for real and complex arguments

### 3 unstable releases

 0.2.0 Oct 25, 2022 Oct 14, 2022 Oct 14, 2022

#492 in Math

145KB
1.5K SLoC

This crate allows to compute:

1. The error function erf(z) for complex and real arguments z:

$${\rm erf}(z) = \frac{2}{\sqrt{\pi}} \int_0^z e^{-t^2} dt$$

1. The complementary error function erfc(z)for complex and real arguments z:

$${\rm erfc}(z) = 1 - {\rm erf}(z)$$

1. The imaginary error function erfi(z) for complex and real arguments z:

$${\rm erfi}(z) = -i\ {\rm erf}(i z) = \frac{2}{\sqrt{\pi}} \int_0^z e^{t^2} dt$$

1. Dawson's function dawson(z) for complex and real arguments z:

$${\rm dawson}(z) = \frac{\sqrt{\pi}}{2} \ e^{-z^2} \ {\rm erfi}(z) = e^{-z^2} \int_0^z e^{t^2} dt$$

1. The Faddeeva function w(z) for complex and real arguments z:

$${\rm w}(z) = e^{-z^2}\ {\rm erfc}(-i z) = e^{-z^2} \ \left(1 + \frac{2i}{\sqrt{\pi}} \int_0^z e^{t^2} dt \right)$$

1. The scaled complementary error function erfcx(z) for complex and real arguments z:

$${\rm erfcx}(z) = e^{z^2} \ {\rm erfc}(z) = {\rm w}(i z)$$

1. The imaginary part of the Faddeeva function w_im(x) for real arguments x:

$${\rm w}\_{\rm im}(x) = {\rm Im}({\rm w}(x)) = e^{-x^2} {\rm erfi}(x)$$

The implementation of this crate is a port of Steven G. Johnson's Faddeeva C/C++ library in Rust. The functions are computed in an efficient way up to machine precision for Complex<f64> or f64 arguments. The functions handle NaN and infinite (positive and negative) arguments correctly.

## Examples

Computing the error functions for a complex argument can be done as in the following example:

use num::complex::Complex;
use errorfunctions::ComplexErrorFunctions;

fn main() {

let z = Complex::<f64>::new(1.21, -0.93);

println!("z = {}", z);
println!("erf(z)    = {}",    z.erf());
println!("erfc(z)   = {}",   z.erfc());
println!("erfcx(z)  = {}",  z.erfcx());
println!("erfi(z)   = {}",   z.erfi());
println!("w(z)      = {}",      z.w());
println!("dawson(z) = {}", z.dawson());
}


Computing the error functions for a real argument can be done as in the following example:

use errorfunctions::RealErrorFunctions;

fn main() {

let x: f64 = 0.934;

println!("x = {}", x);
println!("erf(x)    = {}",    x.erf());
println!("erfc(x)   = {}",   x.erfc());
println!("erfcx(x)  = {}",  x.erfcx());
println!("erfi(x)   = {}",   x.erfi());
println!("Im(w(x))  = {}",   x.w_im());
println!("dawson(x) = {}", x.dawson());
}


If, for some reason, you don't need machine precision, you can specify the desired relative error as follows:

use num::complex::Complex;
use errorfunctions::*;

fn main() {

let z = Complex::<f64>::new(1.21, -0.93);
let relerror = 1.0e-3;

println!("z = {}", z);
println!("erf(z)    = {}",    erf_with_relerror(z, relerror));
println!("erfc(z)   = {}",   erfc_with_relerror(z, relerror));
println!("erfcx(z)  = {}",  erfcx_with_relerror(z, relerror));
println!("erfi(z)   = {}",   erfi_with_relerror(z, relerror));
println!("w(z)      = {}",      w_with_relerror(z, relerror));
println!("dawson(z) = {}", dawson_with_relerror(z, relerror));
}


Setting relerror=0.0 returns machine precision.

## Toml file

Include the following lines in your Cargo.toml file:

[dependencies]
num = "0.4.0"
errorfunctions = "*"


where * is the latest version of this errorfunctions package.

## Tests

The extenstive set of unit tests in the original Faddeeva code was also ported to Rust and is included in this crate.

## Credits

Since this is a close to literal translation in Rust of Steven G. Johnson's C++ code, credit should go to him.

~465KB