about summary refs log tree commit diff
path: root/library/std/src
diff options
context:
space:
mode:
authorPavel Grigorenko <GrigorenkoPV@ya.ru>2025-01-31 02:52:29 +0300
committerPavel Grigorenko <GrigorenkoPV@ya.ru>2025-02-14 01:23:16 +0300
commitb8f0ed37bd96ab6731a62a7a4f5dc1cd493138b3 (patch)
tree7a8a0889a4c8a6dfb9c160e12146fd3da591ebd2 /library/std/src
parent021fb9c09a19d206a37226fe6168f1cc7c984925 (diff)
downloadrust-b8f0ed37bd96ab6731a62a7a4f5dc1cd493138b3.tar.gz
rust-b8f0ed37bd96ab6731a62a7a4f5dc1cd493138b3.zip
Implement `f{16,32,64,128}::{erf,erfc}`
Also add
```rust
// #[unstable(feature = "float_gamma", issue = "99842")]
```
to `gamma`-function-related methods on `f16` & `f128`,
as per https://github.com/rust-lang/rust/pull/136324#issuecomment-2626270247
Diffstat (limited to 'library/std/src')
-rw-r--r--library/std/src/f128.rs74
-rw-r--r--library/std/src/f16.rs72
-rw-r--r--library/std/src/f32.rs64
-rw-r--r--library/std/src/f64.rs64
-rw-r--r--library/std/src/sys/cmath.rs6
5 files changed, 280 insertions, 0 deletions
diff --git a/library/std/src/f128.rs b/library/std/src/f128.rs
index 89612fa7475..133e91eaf32 100644
--- a/library/std/src/f128.rs
+++ b/library/std/src/f128.rs
@@ -1226,6 +1226,7 @@ impl f128 {
     #[inline]
     #[rustc_allow_incoherent_impl]
     #[unstable(feature = "f128", issue = "116909")]
+    // #[unstable(feature = "float_gamma", issue = "99842")]
     #[must_use = "method returns a new number and does not mutate the original value"]
     pub fn gamma(self) -> f128 {
         unsafe { cmath::tgammaf128(self) }
@@ -1260,10 +1261,83 @@ impl f128 {
     #[inline]
     #[rustc_allow_incoherent_impl]
     #[unstable(feature = "f128", issue = "116909")]
+    // #[unstable(feature = "float_gamma", issue = "99842")]
     #[must_use = "method returns a new number and does not mutate the original value"]
     pub fn ln_gamma(self) -> (f128, i32) {
         let mut signgamp: i32 = 0;
         let x = unsafe { cmath::lgammaf128_r(self, &mut signgamp) };
         (x, signgamp)
     }
+
+    /// Error function.
+    ///
+    /// # Unspecified precision
+    ///
+    /// The precision of this function is non-deterministic. This means it varies by platform,
+    /// Rust version, and can even differ within the same execution from one invocation to the next.
+    ///
+    /// This function currently corresponds to the `erff128` from libc on Unix
+    /// and Windows. Note that this might change in the future.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(f128)]
+    /// #![feature(float_erf)]
+    /// # #[cfg(reliable_f128_math)] {
+    /// /// The error function relates what percent of a normal distribution lies
+    /// /// within `x` standard deviations (scaled by `1/sqrt(2)`).
+    /// fn within_standard_deviations(x: f128) -> f128 {
+    ///     (x * std::f128::consts::FRAC_1_SQRT_2).erf() * 100.0
+    /// }
+    ///
+    /// // 68% of a normal distribution is within one standard deviation
+    /// assert!((within_standard_deviations(1.0) - 68.269).abs() < 0.01);
+    /// // 95% of a normal distribution is within two standard deviations
+    /// assert!((within_standard_deviations(2.0) - 95.450).abs() < 0.01);
+    /// // 99.7% of a normal distribution is within three standard deviations
+    /// assert!((within_standard_deviations(3.0) - 99.730).abs() < 0.01);
+    /// # }
+    /// ```
+    #[rustc_allow_incoherent_impl]
+    #[must_use = "method returns a new number and does not mutate the original value"]
+    #[unstable(feature = "f128", issue = "116909")]
+    // #[unstable(feature = "float_erf", issue = "136321")]
+    #[inline]
+    pub fn erf(self) -> f128 {
+        unsafe { cmath::erff128(self) }
+    }
+
+    /// Complementary error function.
+    ///
+    /// # Unspecified precision
+    ///
+    /// The precision of this function is non-deterministic. This means it varies by platform,
+    /// Rust version, and can even differ within the same execution from one invocation to the next.
+    ///
+    /// This function currently corresponds to the `erfcf128` from libc on Unix
+    /// and Windows. Note that this might change in the future.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(f128)]
+    /// #![feature(float_erf)]
+    /// # #[cfg(reliable_f128_math)] {
+    /// let x: f128 = 0.123;
+    ///
+    /// let one = x.erf() + x.erfc();
+    /// let abs_difference = (one - 1.0).abs();
+    ///
+    /// assert!(abs_difference <= f128::EPSILON);
+    /// # }
+    /// ```
+    #[rustc_allow_incoherent_impl]
+    #[must_use = "method returns a new number and does not mutate the original value"]
+    #[unstable(feature = "f128", issue = "116909")]
+    // #[unstable(feature = "float_erf", issue = "136321")]
+    #[inline]
+    pub fn erfc(self) -> f128 {
+        unsafe { cmath::erfcf128(self) }
+    }
 }
diff --git a/library/std/src/f16.rs b/library/std/src/f16.rs
index cc523c93b4d..c342250ae4e 100644
--- a/library/std/src/f16.rs
+++ b/library/std/src/f16.rs
@@ -1224,6 +1224,7 @@ impl f16 {
     #[inline]
     #[rustc_allow_incoherent_impl]
     #[unstable(feature = "f16", issue = "116909")]
+    // #[unstable(feature = "float_gamma", issue = "99842")]
     #[must_use = "method returns a new number and does not mutate the original value"]
     pub fn gamma(self) -> f16 {
         (unsafe { cmath::tgammaf(self as f32) }) as f16
@@ -1258,10 +1259,81 @@ impl f16 {
     #[inline]
     #[rustc_allow_incoherent_impl]
     #[unstable(feature = "f16", issue = "116909")]
+    // #[unstable(feature = "float_gamma", issue = "99842")]
     #[must_use = "method returns a new number and does not mutate the original value"]
     pub fn ln_gamma(self) -> (f16, i32) {
         let mut signgamp: i32 = 0;
         let x = (unsafe { cmath::lgammaf_r(self as f32, &mut signgamp) }) as f16;
         (x, signgamp)
     }
+
+    /// Error function.
+    ///
+    /// # Unspecified precision
+    ///
+    /// The precision of this function is non-deterministic. This means it varies by platform,
+    /// Rust version, and can even differ within the same execution from one invocation to the next.
+    ///
+    /// This function currently corresponds to the `erff` from libc on Unix
+    /// and Windows. Note that this might change in the future.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(f16)]
+    /// #![feature(float_erf)]
+    /// # #[cfg(reliable_f16_math)] {
+    /// /// The error function relates what percent of a normal distribution lies
+    /// /// within `x` standard deviations (scaled by `1/sqrt(2)`).
+    /// fn within_standard_deviations(x: f16) -> f16 {
+    ///     (x * std::f16::consts::FRAC_1_SQRT_2).erf() * 100.0
+    /// }
+    ///
+    /// // 68% of a normal distribution is within one standard deviation
+    /// assert!((within_standard_deviations(1.0) - 68.269).abs() < 0.1);
+    /// // 95% of a normal distribution is within two standard deviations
+    /// assert!((within_standard_deviations(2.0) - 95.450).abs() < 0.1);
+    /// // 99.7% of a normal distribution is within three standard deviations
+    /// assert!((within_standard_deviations(3.0) - 99.730).abs() < 0.1);
+    /// # }
+    /// ```
+    #[rustc_allow_incoherent_impl]
+    #[must_use = "method returns a new number and does not mutate the original value"]
+    #[unstable(feature = "f16", issue = "116909")]
+    // #[unstable(feature = "float_erf", issue = "136321")]
+    #[inline]
+    pub fn erf(self) -> f16 {
+        (unsafe { cmath::erff(self as f32) }) as f16
+    }
+
+    /// Complementary error function.
+    ///
+    /// # Unspecified precision
+    ///
+    /// The precision of this function is non-deterministic. This means it varies by platform,
+    /// Rust version, and can even differ within the same execution from one invocation to the next.
+    ///
+    /// This function currently corresponds to the `erfcf` from libc on Unix
+    /// and Windows. Note that this might change in the future.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(f16)]
+    /// #![feature(float_erf)]
+    /// let x: f16 = 0.123;
+    ///
+    /// let one = x.erf() + x.erfc();
+    /// let abs_difference = (one - 1.0).abs();
+    ///
+    /// assert!(abs_difference <= f16::EPSILON);
+    /// ```
+    #[rustc_allow_incoherent_impl]
+    #[must_use = "method returns a new number and does not mutate the original value"]
+    #[unstable(feature = "f16", issue = "116909")]
+    // #[unstable(feature = "float_erf", issue = "136321")]
+    #[inline]
+    pub fn erfc(self) -> f16 {
+        (unsafe { cmath::erfcf(self as f32) }) as f16
+    }
 }
diff --git a/library/std/src/f32.rs b/library/std/src/f32.rs
index 260c499b7f4..295eee8700a 100644
--- a/library/std/src/f32.rs
+++ b/library/std/src/f32.rs
@@ -1151,4 +1151,68 @@ impl f32 {
         let x = unsafe { cmath::lgammaf_r(self, &mut signgamp) };
         (x, signgamp)
     }
+
+    /// Error function.
+    ///
+    /// # Unspecified precision
+    ///
+    /// The precision of this function is non-deterministic. This means it varies by platform,
+    /// Rust version, and can even differ within the same execution from one invocation to the next.
+    ///
+    /// This function currently corresponds to the `erff` from libc on Unix
+    /// and Windows. Note that this might change in the future.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(float_erf)]
+    /// /// The error function relates what percent of a normal distribution lies
+    /// /// within `x` standard deviations (scaled by `1/sqrt(2)`).
+    /// fn within_standard_deviations(x: f32) -> f32 {
+    ///     (x * std::f32::consts::FRAC_1_SQRT_2).erf() * 100.0
+    /// }
+    ///
+    /// // 68% of a normal distribution is within one standard deviation
+    /// assert!((within_standard_deviations(1.0) - 68.269).abs() < 0.01);
+    /// // 95% of a normal distribution is within two standard deviations
+    /// assert!((within_standard_deviations(2.0) - 95.450).abs() < 0.01);
+    /// // 99.7% of a normal distribution is within three standard deviations
+    /// assert!((within_standard_deviations(3.0) - 99.730).abs() < 0.01);
+    /// ```
+    #[rustc_allow_incoherent_impl]
+    #[must_use = "method returns a new number and does not mutate the original value"]
+    #[unstable(feature = "float_erf", issue = "136321")]
+    #[inline]
+    pub fn erf(self) -> f32 {
+        unsafe { cmath::erff(self) }
+    }
+
+    /// Complementary error function.
+    ///
+    /// # Unspecified precision
+    ///
+    /// The precision of this function is non-deterministic. This means it varies by platform,
+    /// Rust version, and can even differ within the same execution from one invocation to the next.
+    ///
+    /// This function currently corresponds to the `erfcf` from libc on Unix
+    /// and Windows. Note that this might change in the future.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(float_erf)]
+    /// let x: f32 = 0.123;
+    ///
+    /// let one = x.erf() + x.erfc();
+    /// let abs_difference = (one - 1.0).abs();
+    ///
+    /// assert!(abs_difference <= f32::EPSILON);
+    /// ```
+    #[rustc_allow_incoherent_impl]
+    #[must_use = "method returns a new number and does not mutate the original value"]
+    #[unstable(feature = "float_erf", issue = "136321")]
+    #[inline]
+    pub fn erfc(self) -> f32 {
+        unsafe { cmath::erfcf(self) }
+    }
 }
diff --git a/library/std/src/f64.rs b/library/std/src/f64.rs
index 7af646f8cfd..0d713ecbc73 100644
--- a/library/std/src/f64.rs
+++ b/library/std/src/f64.rs
@@ -1151,4 +1151,68 @@ impl f64 {
         let x = unsafe { cmath::lgamma_r(self, &mut signgamp) };
         (x, signgamp)
     }
+
+    /// Error function.
+    ///
+    /// # Unspecified precision
+    ///
+    /// The precision of this function is non-deterministic. This means it varies by platform,
+    /// Rust version, and can even differ within the same execution from one invocation to the next.
+    ///
+    /// This function currently corresponds to the `erf` from libc on Unix
+    /// and Windows. Note that this might change in the future.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(float_erf)]
+    /// /// The error function relates what percent of a normal distribution lies
+    /// /// within `x` standard deviations (scaled by `1/sqrt(2)`).
+    /// fn within_standard_deviations(x: f64) -> f64 {
+    ///     (x * std::f64::consts::FRAC_1_SQRT_2).erf() * 100.0
+    /// }
+    ///
+    /// // 68% of a normal distribution is within one standard deviation
+    /// assert!((within_standard_deviations(1.0) - 68.269).abs() < 0.01);
+    /// // 95% of a normal distribution is within two standard deviations
+    /// assert!((within_standard_deviations(2.0) - 95.450).abs() < 0.01);
+    /// // 99.7% of a normal distribution is within three standard deviations
+    /// assert!((within_standard_deviations(3.0) - 99.730).abs() < 0.01);
+    /// ```
+    #[rustc_allow_incoherent_impl]
+    #[must_use = "method returns a new number and does not mutate the original value"]
+    #[unstable(feature = "float_erf", issue = "136321")]
+    #[inline]
+    pub fn erf(self) -> f64 {
+        unsafe { cmath::erf(self) }
+    }
+
+    /// Complementary error function.
+    ///
+    /// # Unspecified precision
+    ///
+    /// The precision of this function is non-deterministic. This means it varies by platform,
+    /// Rust version, and can even differ within the same execution from one invocation to the next.
+    ///
+    /// This function currently corresponds to the `erfc` from libc on Unix
+    /// and Windows. Note that this might change in the future.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(float_erf)]
+    /// let x: f64 = 0.123;
+    ///
+    /// let one = x.erf() + x.erfc();
+    /// let abs_difference = (one - 1.0).abs();
+    ///
+    /// assert!(abs_difference <= f64::EPSILON);
+    /// ```
+    #[rustc_allow_incoherent_impl]
+    #[must_use = "method returns a new number and does not mutate the original value"]
+    #[unstable(feature = "float_erf", issue = "136321")]
+    #[inline]
+    pub fn erfc(self) -> f64 {
+        unsafe { cmath::erfc(self) }
+    }
 }
diff --git a/library/std/src/sys/cmath.rs b/library/std/src/sys/cmath.rs
index e3f41f4fdbb..c9969b4e376 100644
--- a/library/std/src/sys/cmath.rs
+++ b/library/std/src/sys/cmath.rs
@@ -28,6 +28,10 @@ unsafe extern "C" {
     pub fn lgamma_r(n: f64, s: &mut i32) -> f64;
     #[cfg(not(target_os = "aix"))]
     pub fn lgammaf_r(n: f32, s: &mut i32) -> f32;
+    pub fn erf(n: f64) -> f64;
+    pub fn erff(n: f32) -> f32;
+    pub fn erfc(n: f64) -> f64;
+    pub fn erfcf(n: f32) -> f32;
 
     pub fn acosf128(n: f128) -> f128;
     pub fn asinf128(n: f128) -> f128;
@@ -43,6 +47,8 @@ unsafe extern "C" {
     pub fn tanhf128(n: f128) -> f128;
     pub fn tgammaf128(n: f128) -> f128;
     pub fn lgammaf128_r(n: f128, s: &mut i32) -> f128;
+    pub fn erff128(n: f128) -> f128;
+    pub fn erfcf128(n: f128) -> f128;
 
     cfg_if::cfg_if! {
     if #[cfg(not(all(target_os = "windows", target_env = "msvc", target_arch = "x86")))] {