diff --git a/library/compiler-builtins/libm/crates/libm-macros/src/shared.rs b/library/compiler-builtins/libm/crates/libm-macros/src/shared.rs index 80bd3e90753b..b233e34f1822 100644 --- a/library/compiler-builtins/libm/crates/libm-macros/src/shared.rs +++ b/library/compiler-builtins/libm/crates/libm-macros/src/shared.rs @@ -9,7 +9,7 @@ const ALL_OPERATIONS_NESTED: &[(FloatTy, Signature, Option, &[&str])] FloatTy::F16, Signature { args: &[Ty::F16], returns: &[Ty::F16] }, None, - &["ceilf16", "fabsf16", "floorf16", "rintf16", "sqrtf16", "truncf16"], + &["ceilf16", "fabsf16", "floorf16", "rintf16", "roundf16", "sqrtf16", "truncf16"], ), ( // `fn(f32) -> f32` @@ -40,7 +40,7 @@ const ALL_OPERATIONS_NESTED: &[(FloatTy, Signature, Option, &[&str])] FloatTy::F128, Signature { args: &[Ty::F128], returns: &[Ty::F128] }, None, - &["ceilf128", "fabsf128", "floorf128", "rintf128", "sqrtf128", "truncf128"], + &["ceilf128", "fabsf128", "floorf128", "rintf128", "roundf128", "sqrtf128", "truncf128"], ), ( // `(f16, f16) -> f16` diff --git a/library/compiler-builtins/libm/crates/libm-test/benches/random.rs b/library/compiler-builtins/libm/crates/libm-test/benches/random.rs index 4d050e817e23..d0ecd851e346 100644 --- a/library/compiler-builtins/libm/crates/libm-test/benches/random.rs +++ b/library/compiler-builtins/libm/crates/libm-test/benches/random.rs @@ -129,6 +129,8 @@ libm_macros::for_each_function! { | floorf16 | rintf128 | rintf16 + | roundf128 + | roundf16 | sqrtf128 | sqrtf16 | truncf128 diff --git a/library/compiler-builtins/libm/crates/libm-test/src/mpfloat.rs b/library/compiler-builtins/libm/crates/libm-test/src/mpfloat.rs index 4ac70c2eb5e7..4422ab88d0d1 100644 --- a/library/compiler-builtins/libm/crates/libm-test/src/mpfloat.rs +++ b/library/compiler-builtins/libm/crates/libm-test/src/mpfloat.rs @@ -175,6 +175,8 @@ libm_macros::for_each_function! { rintf16, round, roundf, + roundf128, + roundf16, scalbn, scalbnf, sincos,sincosf, @@ -247,6 +249,7 @@ impl_no_round! { fabsf16 => abs_mut; floorf16 => floor_mut; rintf16 => round_even_mut; // FIXME: respect rounding mode + roundf16 => round_mut; truncf16 => trunc_mut; } @@ -256,6 +259,7 @@ impl_no_round! { fabsf128 => abs_mut; floorf128 => floor_mut; rintf128 => round_even_mut; // FIXME: respect rounding mode + roundf128 => round_mut; truncf128 => trunc_mut; } diff --git a/library/compiler-builtins/libm/crates/libm-test/src/precision.rs b/library/compiler-builtins/libm/crates/libm-test/src/precision.rs index 800425f12adf..bed6158825a5 100644 --- a/library/compiler-builtins/libm/crates/libm-test/src/precision.rs +++ b/library/compiler-builtins/libm/crates/libm-test/src/precision.rs @@ -13,9 +13,6 @@ use crate::{BaseName, CheckBasis, CheckCtx, Float, Identifier, Int, TestResult}; pub struct SpecialCase; /// ULP allowed to differ from the results returned by a test basis. -/// -/// Note that these results were obtained using 400M rounds of random inputs, which -/// is not a value used by default. pub fn default_ulp(ctx: &CheckCtx) -> u32 { // ULP compared to the infinite (MPFR) result. let mut ulp = match ctx.base_name { diff --git a/library/compiler-builtins/libm/crates/libm-test/tests/compare_built_musl.rs b/library/compiler-builtins/libm/crates/libm-test/tests/compare_built_musl.rs index f009816c97f1..0fc1b0df13da 100644 --- a/library/compiler-builtins/libm/crates/libm-test/tests/compare_built_musl.rs +++ b/library/compiler-builtins/libm/crates/libm-test/tests/compare_built_musl.rs @@ -91,6 +91,8 @@ libm_macros::for_each_function! { floorf16, rintf128, rintf16, + roundf128, + roundf16, sqrtf128, sqrtf16, truncf128, diff --git a/library/compiler-builtins/libm/crates/util/src/main.rs b/library/compiler-builtins/libm/crates/util/src/main.rs index 889823d2e4ab..aaedda6d152b 100644 --- a/library/compiler-builtins/libm/crates/util/src/main.rs +++ b/library/compiler-builtins/libm/crates/util/src/main.rs @@ -98,6 +98,8 @@ fn do_eval(basis: &str, op: &str, inputs: &[&str]) { | floorf16 | rintf128 | rintf16 + | roundf128 + | roundf16 | sqrtf128 | sqrtf16 | truncf128 diff --git a/library/compiler-builtins/libm/etc/function-definitions.json b/library/compiler-builtins/libm/etc/function-definitions.json index bbb2b40f14d4..8c5903e93b92 100644 --- a/library/compiler-builtins/libm/etc/function-definitions.json +++ b/library/compiler-builtins/libm/etc/function-definitions.json @@ -685,16 +685,32 @@ "round": { "sources": [ "src/libm_helper.rs", + "src/math/generic/round.rs", "src/math/round.rs" ], "type": "f64" }, "roundf": { "sources": [ + "src/math/generic/round.rs", "src/math/roundf.rs" ], "type": "f32" }, + "roundf128": { + "sources": [ + "src/math/generic/round.rs", + "src/math/roundf128.rs" + ], + "type": "f128" + }, + "roundf16": { + "sources": [ + "src/math/generic/round.rs", + "src/math/roundf16.rs" + ], + "type": "f16" + }, "scalbn": { "sources": [ "src/libm_helper.rs", diff --git a/library/compiler-builtins/libm/etc/function-list.txt b/library/compiler-builtins/libm/etc/function-list.txt index 41bb4e06be8d..0b6eed828b52 100644 --- a/library/compiler-builtins/libm/etc/function-list.txt +++ b/library/compiler-builtins/libm/etc/function-list.txt @@ -101,6 +101,8 @@ rintf128 rintf16 round roundf +roundf128 +roundf16 scalbn scalbnf sin diff --git a/library/compiler-builtins/libm/src/math/generic/mod.rs b/library/compiler-builtins/libm/src/math/generic/mod.rs index c7741cb46007..1f557719f42c 100644 --- a/library/compiler-builtins/libm/src/math/generic/mod.rs +++ b/library/compiler-builtins/libm/src/math/generic/mod.rs @@ -4,6 +4,7 @@ mod fabs; mod fdim; mod floor; mod rint; +mod round; mod scalbn; mod sqrt; mod trunc; @@ -14,6 +15,7 @@ pub use fabs::fabs; pub use fdim::fdim; pub use floor::floor; pub use rint::rint; +pub use round::round; pub use scalbn::scalbn; pub use sqrt::sqrt; pub use trunc::trunc; diff --git a/library/compiler-builtins/libm/src/math/generic/round.rs b/library/compiler-builtins/libm/src/math/generic/round.rs new file mode 100644 index 000000000000..8b51381880cc --- /dev/null +++ b/library/compiler-builtins/libm/src/math/generic/round.rs @@ -0,0 +1,82 @@ +use super::super::{Float, MinInt}; +use super::{copysign, trunc}; + +pub fn round(x: F) -> F { + let f0p5 = F::from_parts(false, F::EXP_BIAS - 1, F::Int::ZERO); // 0.5 + let f0p25 = F::from_parts(false, F::EXP_BIAS - 2, F::Int::ZERO); // 0.25 + + trunc(x + copysign(f0p5 - f0p25 * F::EPSILON, x)) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + #[cfg(f16_enabled)] + fn zeroes_f16() { + assert_biteq!(round(0.0_f16), 0.0_f16); + assert_biteq!(round(-0.0_f16), -0.0_f16); + } + + #[test] + #[cfg(f16_enabled)] + fn sanity_check_f16() { + assert_eq!(round(-1.0_f16), -1.0); + assert_eq!(round(2.8_f16), 3.0); + assert_eq!(round(-0.5_f16), -1.0); + assert_eq!(round(0.5_f16), 1.0); + assert_eq!(round(-1.5_f16), -2.0); + assert_eq!(round(1.5_f16), 2.0); + } + + #[test] + fn zeroes_f32() { + assert_biteq!(round(0.0_f32), 0.0_f32); + assert_biteq!(round(-0.0_f32), -0.0_f32); + } + + #[test] + fn sanity_check_f32() { + assert_eq!(round(-1.0_f32), -1.0); + assert_eq!(round(2.8_f32), 3.0); + assert_eq!(round(-0.5_f32), -1.0); + assert_eq!(round(0.5_f32), 1.0); + assert_eq!(round(-1.5_f32), -2.0); + assert_eq!(round(1.5_f32), 2.0); + } + + #[test] + fn zeroes_f64() { + assert_biteq!(round(0.0_f64), 0.0_f64); + assert_biteq!(round(-0.0_f64), -0.0_f64); + } + + #[test] + fn sanity_check_f64() { + assert_eq!(round(-1.0_f64), -1.0); + assert_eq!(round(2.8_f64), 3.0); + assert_eq!(round(-0.5_f64), -1.0); + assert_eq!(round(0.5_f64), 1.0); + assert_eq!(round(-1.5_f64), -2.0); + assert_eq!(round(1.5_f64), 2.0); + } + + #[test] + #[cfg(f128_enabled)] + fn zeroes_f128() { + assert_biteq!(round(0.0_f128), 0.0_f128); + assert_biteq!(round(-0.0_f128), -0.0_f128); + } + + #[test] + #[cfg(f128_enabled)] + fn sanity_check_f128() { + assert_eq!(round(-1.0_f128), -1.0); + assert_eq!(round(2.8_f128), 3.0); + assert_eq!(round(-0.5_f128), -1.0); + assert_eq!(round(0.5_f128), 1.0); + assert_eq!(round(-1.5_f128), -2.0); + assert_eq!(round(1.5_f128), 2.0); + } +} diff --git a/library/compiler-builtins/libm/src/math/mod.rs b/library/compiler-builtins/libm/src/math/mod.rs index 53d06974ceec..8db17a02dfce 100644 --- a/library/compiler-builtins/libm/src/math/mod.rs +++ b/library/compiler-builtins/libm/src/math/mod.rs @@ -347,6 +347,7 @@ cfg_if! { mod fdimf16; mod floorf16; mod rintf16; + mod roundf16; mod sqrtf16; mod truncf16; @@ -356,6 +357,7 @@ cfg_if! { pub use self::fdimf16::fdimf16; pub use self::floorf16::floorf16; pub use self::rintf16::rintf16; + pub use self::roundf16::roundf16; pub use self::sqrtf16::sqrtf16; pub use self::truncf16::truncf16; } @@ -369,6 +371,7 @@ cfg_if! { mod fdimf128; mod floorf128; mod rintf128; + mod roundf128; mod sqrtf128; mod truncf128; @@ -378,6 +381,7 @@ cfg_if! { pub use self::fdimf128::fdimf128; pub use self::floorf128::floorf128; pub use self::rintf128::rintf128; + pub use self::roundf128::roundf128; pub use self::sqrtf128::sqrtf128; pub use self::truncf128::truncf128; } diff --git a/library/compiler-builtins/libm/src/math/round.rs b/library/compiler-builtins/libm/src/math/round.rs index b81ebaa1dbec..36e0eb1f2ed4 100644 --- a/library/compiler-builtins/libm/src/math/round.rs +++ b/library/compiler-builtins/libm/src/math/round.rs @@ -1,28 +1,5 @@ -use core::f64; - -use super::{copysign, trunc}; - +/// Round `x` to the nearest integer, breaking ties away from zero. #[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] pub fn round(x: f64) -> f64 { - trunc(x + copysign(0.5 - 0.25 * f64::EPSILON, x)) -} - -#[cfg(test)] -mod tests { - use super::round; - - #[test] - fn negative_zero() { - assert_eq!(round(-0.0_f64).to_bits(), (-0.0_f64).to_bits()); - } - - #[test] - fn sanity_check() { - assert_eq!(round(-1.0), -1.0); - assert_eq!(round(2.8), 3.0); - assert_eq!(round(-0.5), -1.0); - assert_eq!(round(0.5), 1.0); - assert_eq!(round(-1.5), -2.0); - assert_eq!(round(1.5), 2.0); - } + super::generic::round(x) } diff --git a/library/compiler-builtins/libm/src/math/roundf.rs b/library/compiler-builtins/libm/src/math/roundf.rs index fb974bbfe73f..b5d7c9d693e7 100644 --- a/library/compiler-builtins/libm/src/math/roundf.rs +++ b/library/compiler-builtins/libm/src/math/roundf.rs @@ -1,30 +1,5 @@ -use core::f32; - -use super::{copysignf, truncf}; - +/// Round `x` to the nearest integer, breaking ties away from zero. #[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] pub fn roundf(x: f32) -> f32 { - truncf(x + copysignf(0.5 - 0.25 * f32::EPSILON, x)) -} - -// PowerPC tests are failing on LLVM 13: https://github.com/rust-lang/rust/issues/88520 -#[cfg(not(target_arch = "powerpc64"))] -#[cfg(test)] -mod tests { - use super::roundf; - - #[test] - fn negative_zero() { - assert_eq!(roundf(-0.0_f32).to_bits(), (-0.0_f32).to_bits()); - } - - #[test] - fn sanity_check() { - assert_eq!(roundf(-1.0), -1.0); - assert_eq!(roundf(2.8), 3.0); - assert_eq!(roundf(-0.5), -1.0); - assert_eq!(roundf(0.5), 1.0); - assert_eq!(roundf(-1.5), -2.0); - assert_eq!(roundf(1.5), 2.0); - } + super::generic::round(x) } diff --git a/library/compiler-builtins/libm/src/math/roundf128.rs b/library/compiler-builtins/libm/src/math/roundf128.rs new file mode 100644 index 000000000000..fc3164929fe4 --- /dev/null +++ b/library/compiler-builtins/libm/src/math/roundf128.rs @@ -0,0 +1,5 @@ +/// Round `x` to the nearest integer, breaking ties away from zero. +#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] +pub fn roundf128(x: f128) -> f128 { + super::generic::round(x) +} diff --git a/library/compiler-builtins/libm/src/math/roundf16.rs b/library/compiler-builtins/libm/src/math/roundf16.rs new file mode 100644 index 000000000000..8b356eaabeec --- /dev/null +++ b/library/compiler-builtins/libm/src/math/roundf16.rs @@ -0,0 +1,5 @@ +/// Round `x` to the nearest integer, breaking ties away from zero. +#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] +pub fn roundf16(x: f16) -> f16 { + super::generic::round(x) +}