libs-team
libs-team copied to clipboard
Add error functions (`erf`, `erfc`) to the `f32`/`f64` API.
Proposal
Problem statement
The f32/f64 APIs are missing some useful functions, namely erf and erfc, such as in libm (where the current gamma function is from I believe) or the C++ Faddeeva library.
Motivating examples or use cases
The error function is used in numerous areas of scientific computing, such as statistics where the CDF of the Normal Distribution can be written in terms of it:
$$ \mathbb{P}(X \leq x) = F_X(x) = \Phi\left(\frac{x-\mu}{\sigma}\right) = \frac{1}{2} \left[ 1 + \text{erf}\left( \frac{x-\mu}{\sigma\sqrt{2}} \right) \right] $$
Solution sketch
As far as I can tell, the float functions are already from the libm crate, and erf, erfc have just been skipped for some reason.
Alternatives
There are obviously multiple ways to implement integrals numerically, but if the gamma function from libm was good enough, I don't see why the error function wouldn't be.
Another alternative is to port the Faddeeva library from C++ (released under an MIT licence).
Links and related work
IMO the only reason to add erf and erfc is matching the content of math.h in C99 / C++11. The implementation should just defer to the build environment's libm.a or compiler-builtins i.e.
extern "C" {
fn erf(x: f64) -> f64;
}
...
impl f64 {
pub fn erf(self) -> Self {
unsafe { cmath::erf(self) }
}
}
POSIX also defined the Bessel functions (j0, j1, jn, y0, y1, yn), but these are not part of any C standard. That being said lgamma_r referred in cmath.rs is also not part of C99 either, not even POSIX.
The gamma functions (rust-lang/rust#99842) are still not stable yet. But rust-lang/rust#26350 explicitly mentioned tgamma as something that should not be part of standard library. Certainly the same argument applies to erf.
@kennytm all valid points. Is there anyone else worth checking with? I can close the issue if not.
Cc @workingjubilee, since you usually have useful opinions on floating point stuff. :)
Can someone offer a clarifying explanation of why f32::erf, f64::erf, f32::erfc, and f64::erfc should not be added to std? It appears that on Rust 1.77, std provides methods for logarithms, cube root, trig functions, and Gamma functions on floating point primatives. Is there a reason why these functions should be provided by std but erf and erfc should not? What is different about erf and erfc relative to these functions that justifies their exclusion from std?
I admit that I agree that std should probably not provide methods for every single named function of the Reals, as doing so could cause users to face low SNR in the documentation and could pose unwanted maintenance burden for the maintainers, but the line drawn as it currently is seems pretty arbitrary to me.
@pezcore
Elementary functions like log and sin/cos can be lowered to LLVM intrinsics so the core library can stay not explicitly relying on libm thus avoiding rust-lang/rust#26350.
gamma is not yet stable, and could be removed because of the libm dependency (see my comment above https://github.com/rust-lang/libs-team/issues/352#issuecomment-1992094858).
IMO if we accept (stabilize) gamma we should also accept erf, and if we remove gamma there is no reason for erf in std either.