This crate allows to compute:
erf(z)
for complex and real arguments z
:$$ {\rm erf}(z) = \frac{2}{\sqrt{\pi}} \int_0^z e^{-t^2} dt $$
erfc(z)
for complex and real arguments z
:$$ {\rm erfc}(z) = 1 - {\rm erf}(z) $$
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 $$
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 $$
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) $$
erfcx(z)
for complex and real arguments z
:$$ {\rm erfcx}(z) = e^{z^2} \ {\rm erfc}(z) = {\rm w}(i z) $$
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.
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::
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::
println!("z = {}", z);
println!("erf(z) = {}", erfwithrelerror(z, relerror));
println!("erfc(z) = {}", erfcwithrelerror(z, relerror));
println!("erfcx(z) = {}", erfcxwithrelerror(z, relerror));
println!("erfi(z) = {}", erfiwithrelerror(z, relerror));
println!("w(z) = {}", wwithrelerror(z, relerror));
println!("dawson(z) = {}", dawsonwithrelerror(z, relerror));
}
``
Setting
relerror=0.0` returns machine precision.
The extenstive set of unit tests in the original Faddeeva code was also ported to Rust and is included in this crate.
Since this is a close to literal translation in Rust of Steven G. Johnson's C++ code, credit should go to him.