Skip to content

Commit c7b1278

Browse files
committed
Implement f{16,32,64,128}::{erf,erfc}
1 parent 6ac8878 commit c7b1278

File tree

5 files changed

+230
-0
lines changed

5 files changed

+230
-0
lines changed

library/std/src/f128.rs

+57
Original file line numberDiff line numberDiff line change
@@ -1269,4 +1269,61 @@ impl f128 {
12691269
let x = unsafe { cmath::lgammaf128_r(self, &mut signgamp) };
12701270
(x, signgamp)
12711271
}
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 `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+
/// let x: f128 = 1.0;
1288+
///
1289+
/// let abs_difference = (x.erf() - 0.8427007929497148693412206350826093).abs();
1290+
///
1291+
/// assert!(abs_difference <= f128::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 = "float_erf", issue = "136321")]
1296+
#[inline]
1297+
pub fn erf(self) -> f128 {
1298+
unsafe { cmath::erff128(self) }
1299+
}
1300+
1301+
/// Complementary error function.
1302+
///
1303+
/// # Unspecified precision
1304+
///
1305+
/// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and
1306+
/// can even differ within the same execution from one invocation to the next.
1307+
/// This function currently corresponds to the `erfcf128` from libc on Unix
1308+
/// and Windows. Note that this might change in the future.
1309+
///
1310+
/// # Examples
1311+
///
1312+
/// ```
1313+
/// #![feature(f128)]
1314+
/// #![feature(float_erf)]
1315+
/// let x: f128 = 0.123;
1316+
///
1317+
/// let one = x.erf() + x.erfc();
1318+
/// let abs_difference = (one - 1.0).abs();
1319+
///
1320+
/// assert!(abs_difference <= f128::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 = "float_erf", issue = "136321")]
1325+
#[inline]
1326+
pub fn erfc(self) -> f128 {
1327+
unsafe { cmath::erfcf128(self) }
1328+
}
12721329
}

library/std/src/f16.rs

+57
Original file line numberDiff line numberDiff line change
@@ -1267,4 +1267,61 @@ impl f16 {
12671267
let x = (unsafe { cmath::lgammaf_r(self as f32, &mut signgamp) }) as f16;
12681268
(x, signgamp)
12691269
}
1270+
1271+
/// Error function.
1272+
///
1273+
/// # Unspecified precision
1274+
///
1275+
/// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and
1276+
/// can even differ within the same execution from one invocation to the next.
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 = "float_erf", issue = "136321")]
1294+
#[inline]
1295+
pub fn erf(self) -> f16 {
1296+
(unsafe { cmath::erff(self as f32) }) as f16
1297+
}
1298+
1299+
/// Complementary error function.
1300+
///
1301+
/// # Unspecified precision
1302+
///
1303+
/// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and
1304+
/// can even differ within the same execution from one invocation to the next.
1305+
/// This function currently corresponds to the `erfcf` from libc on Unix
1306+
/// and Windows. Note that this might change in the future.
1307+
///
1308+
/// # Examples
1309+
///
1310+
/// ```
1311+
/// #![feature(f16)]
1312+
/// #![feature(float_erf)]
1313+
/// let x: f16 = 0.123;
1314+
///
1315+
/// let one = x.erf() + x.erfc();
1316+
/// let abs_difference = (one - 1.0).abs();
1317+
///
1318+
/// assert!(abs_difference <= f16::EPSILON);
1319+
/// ```
1320+
#[rustc_allow_incoherent_impl]
1321+
#[must_use = "method returns a new number and does not mutate the original value"]
1322+
#[unstable(feature = "float_erf", issue = "136321")]
1323+
#[inline]
1324+
pub fn erfc(self) -> f16 {
1325+
(unsafe { cmath::erfcf(self as f32) }) as f16
1326+
}
12701327
}

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)