Skip to content

Commit 84e15e7

Browse files
committed
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 rust-lang#136324 (comment)
1 parent aa4cfd0 commit 84e15e7

File tree

5 files changed

+242
-0
lines changed

5 files changed

+242
-0
lines changed

library/std/src/f128.rs

+65
Original file line numberDiff line numberDiff line change
@@ -1229,6 +1229,7 @@ impl f128 {
12291229
#[inline]
12301230
#[rustc_allow_incoherent_impl]
12311231
#[unstable(feature = "f128", issue = "116909")]
1232+
// #[unstable(feature = "float_gamma", issue = "99842")]
12321233
#[must_use = "method returns a new number and does not mutate the original value"]
12331234
pub fn gamma(self) -> f128 {
12341235
unsafe { cmath::tgammaf128(self) }
@@ -1263,10 +1264,74 @@ impl f128 {
12631264
#[inline]
12641265
#[rustc_allow_incoherent_impl]
12651266
#[unstable(feature = "f128", issue = "116909")]
1267+
// #[unstable(feature = "float_gamma", issue = "99842")]
12661268
#[must_use = "method returns a new number and does not mutate the original value"]
12671269
pub fn ln_gamma(self) -> (f128, i32) {
12681270
let mut signgamp: i32 = 0;
12691271
let x = unsafe { cmath::lgammaf128_r(self, &mut signgamp) };
12701272
(x, signgamp)
12711273
}
1274+
1275+
/// Error function.
1276+
///
1277+
/// # Unspecified precision
1278+
///
1279+
/// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and
1280+
/// can even differ within the same execution from one invocation to the next.
1281+
/// This function currently corresponds to the `erff128` from libc on Unix
1282+
/// and Windows. Note that this might change in the future.
1283+
///
1284+
/// # Examples
1285+
///
1286+
/// ```
1287+
/// #![feature(f128)]
1288+
/// #![feature(float_erf)]
1289+
/// # #[cfg(reliable_f128_math)] {
1290+
/// let x: f128 = 1.0;
1291+
///
1292+
/// let abs_difference = (x.erf() - 0.8427007929497148693412206350826093).abs();
1293+
///
1294+
/// assert!(abs_difference <= f128::EPSILON);
1295+
/// # }
1296+
/// ```
1297+
#[rustc_allow_incoherent_impl]
1298+
#[must_use = "method returns a new number and does not mutate the original value"]
1299+
#[unstable(feature = "f128", issue = "116909")]
1300+
// #[unstable(feature = "float_erf", issue = "136321")]
1301+
#[inline]
1302+
pub fn erf(self) -> f128 {
1303+
unsafe { cmath::erff128(self) }
1304+
}
1305+
1306+
/// Complementary error function.
1307+
///
1308+
/// # Unspecified precision
1309+
///
1310+
/// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and
1311+
/// can even differ within the same execution from one invocation to the next.
1312+
/// This function currently corresponds to the `erfcf128` from libc on Unix
1313+
/// and Windows. Note that this might change in the future.
1314+
///
1315+
/// # Examples
1316+
///
1317+
/// ```
1318+
/// #![feature(f128)]
1319+
/// #![feature(float_erf)]
1320+
/// # #[cfg(reliable_f128_math)] {
1321+
/// let x: f128 = 0.123;
1322+
///
1323+
/// let one = x.erf() + x.erfc();
1324+
/// let abs_difference = (one - 1.0).abs();
1325+
///
1326+
/// assert!(abs_difference <= f128::EPSILON);
1327+
/// # }
1328+
/// ```
1329+
#[rustc_allow_incoherent_impl]
1330+
#[must_use = "method returns a new number and does not mutate the original value"]
1331+
#[unstable(feature = "f128", issue = "116909")]
1332+
// #[unstable(feature = "float_erf", issue = "136321")]
1333+
#[inline]
1334+
pub fn erfc(self) -> f128 {
1335+
unsafe { cmath::erfcf128(self) }
1336+
}
12721337
}

library/std/src/f16.rs

+61
Original file line numberDiff line numberDiff line change
@@ -1227,6 +1227,7 @@ impl f16 {
12271227
#[inline]
12281228
#[rustc_allow_incoherent_impl]
12291229
#[unstable(feature = "f16", issue = "116909")]
1230+
// #[unstable(feature = "float_gamma", issue = "99842")]
12301231
#[must_use = "method returns a new number and does not mutate the original value"]
12311232
pub fn gamma(self) -> f16 {
12321233
(unsafe { cmath::tgammaf(self as f32) }) as f16
@@ -1261,10 +1262,70 @@ impl f16 {
12611262
#[inline]
12621263
#[rustc_allow_incoherent_impl]
12631264
#[unstable(feature = "f16", issue = "116909")]
1265+
// #[unstable(feature = "float_gamma", issue = "99842")]
12641266
#[must_use = "method returns a new number and does not mutate the original value"]
12651267
pub fn ln_gamma(self) -> (f16, i32) {
12661268
let mut signgamp: i32 = 0;
12671269
let x = (unsafe { cmath::lgammaf_r(self as f32, &mut signgamp) }) as f16;
12681270
(x, signgamp)
12691271
}
1272+
1273+
/// Error function.
1274+
///
1275+
/// # Unspecified precision
1276+
///
1277+
/// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and
1278+
/// can even differ within the same execution from one invocation to the next.
1279+
/// This function currently corresponds to the `erff` from libc on Unix
1280+
/// and Windows. Note that this might change in the future.
1281+
///
1282+
/// # Examples
1283+
///
1284+
/// ```
1285+
/// #![feature(f16)]
1286+
/// #![feature(float_erf)]
1287+
/// let x: f16 = 1.0;
1288+
///
1289+
/// let abs_difference = (x.erf() - 0.8427).abs();
1290+
///
1291+
/// assert!(abs_difference <= f16::EPSILON);
1292+
/// ```
1293+
#[rustc_allow_incoherent_impl]
1294+
#[must_use = "method returns a new number and does not mutate the original value"]
1295+
#[unstable(feature = "f16", issue = "116909")]
1296+
// #[unstable(feature = "float_erf", issue = "136321")]
1297+
#[inline]
1298+
pub fn erf(self) -> f16 {
1299+
(unsafe { cmath::erff(self as f32) }) as f16
1300+
}
1301+
1302+
/// Complementary error function.
1303+
///
1304+
/// # Unspecified precision
1305+
///
1306+
/// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and
1307+
/// can even differ within the same execution from one invocation to the next.
1308+
/// This function currently corresponds to the `erfcf` from libc on Unix
1309+
/// and Windows. Note that this might change in the future.
1310+
///
1311+
/// # Examples
1312+
///
1313+
/// ```
1314+
/// #![feature(f16)]
1315+
/// #![feature(float_erf)]
1316+
/// let x: f16 = 0.123;
1317+
///
1318+
/// let one = x.erf() + x.erfc();
1319+
/// let abs_difference = (one - 1.0).abs();
1320+
///
1321+
/// assert!(abs_difference <= f16::EPSILON);
1322+
/// ```
1323+
#[rustc_allow_incoherent_impl]
1324+
#[must_use = "method returns a new number and does not mutate the original value"]
1325+
#[unstable(feature = "f16", issue = "116909")]
1326+
// #[unstable(feature = "float_erf", issue = "136321")]
1327+
#[inline]
1328+
pub fn erfc(self) -> f16 {
1329+
(unsafe { cmath::erfcf(self as f32) }) as f16
1330+
}
12701331
}

library/std/src/f32.rs

+55
Original file line numberDiff line numberDiff line change
@@ -1154,4 +1154,59 @@ impl f32 {
11541154
let x = unsafe { cmath::lgammaf_r(self, &mut signgamp) };
11551155
(x, signgamp)
11561156
}
1157+
1158+
/// Error function.
1159+
///
1160+
/// # Unspecified precision
1161+
///
1162+
/// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and
1163+
/// can even differ within the same execution from one invocation to the next.
1164+
/// This function currently corresponds to the `erff` from libc on Unix
1165+
/// and Windows. Note that this might change in the future.
1166+
///
1167+
/// # Examples
1168+
///
1169+
/// ```
1170+
/// #![feature(float_erf)]
1171+
/// let x: f32 = 1.0;
1172+
///
1173+
/// let abs_difference = (x.erf() - 0.842700793).abs();
1174+
///
1175+
/// assert!(abs_difference <= f32::EPSILON);
1176+
/// ```
1177+
#[rustc_allow_incoherent_impl]
1178+
#[must_use = "method returns a new number and does not mutate the original value"]
1179+
#[unstable(feature = "float_erf", issue = "136321")]
1180+
#[inline]
1181+
pub fn erf(self) -> f32 {
1182+
unsafe { cmath::erff(self) }
1183+
}
1184+
1185+
/// Complementary error function.
1186+
///
1187+
/// # Unspecified precision
1188+
///
1189+
/// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and
1190+
/// can even differ within the same execution from one invocation to the next.
1191+
/// This function currently corresponds to the `erfcf` from libc on Unix
1192+
/// and Windows. Note that this might change in the future.
1193+
///
1194+
/// # Examples
1195+
///
1196+
/// ```
1197+
/// #![feature(float_erf)]
1198+
/// let x: f32 = 0.123;
1199+
///
1200+
/// let one = x.erf() + x.erfc();
1201+
/// let abs_difference = (one - 1.0).abs();
1202+
///
1203+
/// assert!(abs_difference <= f32::EPSILON);
1204+
/// ```
1205+
#[rustc_allow_incoherent_impl]
1206+
#[must_use = "method returns a new number and does not mutate the original value"]
1207+
#[unstable(feature = "float_erf", issue = "136321")]
1208+
#[inline]
1209+
pub fn erfc(self) -> f32 {
1210+
unsafe { cmath::erfcf(self) }
1211+
}
11571212
}

library/std/src/f64.rs

+55
Original file line numberDiff line numberDiff line change
@@ -1154,4 +1154,59 @@ impl f64 {
11541154
let x = unsafe { cmath::lgamma_r(self, &mut signgamp) };
11551155
(x, signgamp)
11561156
}
1157+
1158+
/// Error function.
1159+
///
1160+
/// # Unspecified precision
1161+
///
1162+
/// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and
1163+
/// can even differ within the same execution from one invocation to the next.
1164+
/// This function currently corresponds to the `erf` from libc on Unix
1165+
/// and Windows. Note that this might change in the future.
1166+
///
1167+
/// # Examples
1168+
///
1169+
/// ```
1170+
/// #![feature(float_erf)]
1171+
/// let x: f64 = 1.0;
1172+
///
1173+
/// let abs_difference = (x.erf() - 0.8427007929497149).abs();
1174+
///
1175+
/// assert!(abs_difference <= f64::EPSILON);
1176+
/// ```
1177+
#[rustc_allow_incoherent_impl]
1178+
#[must_use = "method returns a new number and does not mutate the original value"]
1179+
#[unstable(feature = "float_erf", issue = "136321")]
1180+
#[inline]
1181+
pub fn erf(self) -> f64 {
1182+
unsafe { cmath::erf(self) }
1183+
}
1184+
1185+
/// Complementary error function.
1186+
///
1187+
/// # Unspecified precision
1188+
///
1189+
/// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and
1190+
/// can even differ within the same execution from one invocation to the next.
1191+
/// This function currently corresponds to the `erfc` from libc on Unix
1192+
/// and Windows. Note that this might change in the future.
1193+
///
1194+
/// # Examples
1195+
///
1196+
/// ```
1197+
/// #![feature(float_erf)]
1198+
/// let x: f64 = 0.123;
1199+
///
1200+
/// let one = x.erf() + x.erfc();
1201+
/// let abs_difference = (one - 1.0).abs();
1202+
///
1203+
/// assert!(abs_difference <= f64::EPSILON);
1204+
/// ```
1205+
#[rustc_allow_incoherent_impl]
1206+
#[must_use = "method returns a new number and does not mutate the original value"]
1207+
#[unstable(feature = "float_erf", issue = "136321")]
1208+
#[inline]
1209+
pub fn erfc(self) -> f64 {
1210+
unsafe { cmath::erfc(self) }
1211+
}
11571212
}

library/std/src/sys/cmath.rs

+6
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ extern "C" {
2828
pub fn lgamma_r(n: f64, s: &mut i32) -> f64;
2929
#[cfg(not(target_os = "aix"))]
3030
pub fn lgammaf_r(n: f32, s: &mut i32) -> f32;
31+
pub fn erf(n: f64) -> f64;
32+
pub fn erff(n: f32) -> f32;
33+
pub fn erfc(n: f64) -> f64;
34+
pub fn erfcf(n: f32) -> f32;
3135

3236
pub fn acosf128(n: f128) -> f128;
3337
pub fn asinf128(n: f128) -> f128;
@@ -43,6 +47,8 @@ extern "C" {
4347
pub fn tanhf128(n: f128) -> f128;
4448
pub fn tgammaf128(n: f128) -> f128;
4549
pub fn lgammaf128_r(n: f128, s: &mut i32) -> f128;
50+
pub fn erff128(n: f128) -> f128;
51+
pub fn erfcf128(n: f128) -> f128;
4652

4753
cfg_if::cfg_if! {
4854
if #[cfg(not(all(target_os = "windows", target_env = "msvc", target_arch = "x86")))] {

0 commit comments

Comments
 (0)