Skip to content

Commit 0e7a88a

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 021fb9c commit 0e7a88a

File tree

5 files changed

+250
-0
lines changed

5 files changed

+250
-0
lines changed

library/std/src/f128.rs

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

library/std/src/f16.rs

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

library/std/src/f32.rs

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

library/std/src/f64.rs

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

library/std/src/sys/cmath.rs

+6
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ unsafe 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 @@ unsafe 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)