Skip to content

Commit

Permalink
Implement f{16,32,64,128}::{erf,erfc}
Browse files Browse the repository at this point in the history
Also add
```rust
// #[unstable(feature = "float_gamma", issue = "99842")]
```
to `gamma`-function-related methods on `f16` & `f128`,
as per rust-lang#136324 (comment)
  • Loading branch information
GrigorenkoPV committed Feb 12, 2025
1 parent 021fb9c commit 0e7a88a
Show file tree
Hide file tree
Showing 5 changed files with 250 additions and 0 deletions.
67 changes: 67 additions & 0 deletions library/std/src/f128.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) }
Expand Down Expand Up @@ -1260,10 +1261,76 @@ 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)] {
/// let x: f128 = 1.0;
///
/// let abs_difference = (x.erf() - 0.8427007929497148693412206350826093).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 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) }
}
}
63 changes: 63 additions & 0 deletions library/std/src/f16.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -1258,10 +1259,72 @@ 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)]
/// let x: f16 = 1.0;
///
/// let abs_difference = (x.erf() - 0.8427).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 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
}
}
57 changes: 57 additions & 0 deletions library/std/src/f32.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1151,4 +1151,61 @@ 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)]
/// let x: f32 = 1.0;
///
/// let abs_difference = (x.erf() - 0.842700793).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 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) }
}
}
57 changes: 57 additions & 0 deletions library/std/src/f64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1151,4 +1151,61 @@ 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)]
/// let x: f64 = 1.0;
///
/// let abs_difference = (x.erf() - 0.8427007929497149).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 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) }
}
}
6 changes: 6 additions & 0 deletions library/std/src/sys/cmath.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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")))] {
Expand Down

0 comments on commit 0e7a88a

Please sign in to comment.