From e3efddc2c25b36408fa5184b6bc8c7700d32b2a4 Mon Sep 17 00:00:00 2001 From: Jules Bertholet Date: Mon, 7 Nov 2022 12:34:47 -0500 Subject: [PATCH 1/4] Add `roundeven` and `roundevenf` --- library/compiler-builtins/libm/build.rs | 3 ++ .../compiler-builtins/libm/src/math/mod.rs | 4 ++ .../libm/src/math/roundeven.rs | 50 +++++++++++++++++++ .../libm/src/math/roundevenf.rs | 50 +++++++++++++++++++ 4 files changed, 107 insertions(+) create mode 100644 library/compiler-builtins/libm/src/math/roundeven.rs create mode 100644 library/compiler-builtins/libm/src/math/roundevenf.rs diff --git a/library/compiler-builtins/libm/build.rs b/library/compiler-builtins/libm/build.rs index 80145a9ccac9..403304a1383b 100644 --- a/library/compiler-builtins/libm/build.rs +++ b/library/compiler-builtins/libm/build.rs @@ -39,6 +39,9 @@ mod musl_reference_tests { "jnf.rs", "j1.rs", "j1f.rs", + // musl doens't have these + "roundeven.rs", + "roundevenf.rs", ]; struct Function { diff --git a/library/compiler-builtins/libm/src/math/mod.rs b/library/compiler-builtins/libm/src/math/mod.rs index 81bfc53ed854..e710bd381bc1 100644 --- a/library/compiler-builtins/libm/src/math/mod.rs +++ b/library/compiler-builtins/libm/src/math/mod.rs @@ -171,6 +171,8 @@ mod remainderf; mod remquo; mod remquof; mod round; +mod roundeven; +mod roundevenf; mod roundf; mod scalbn; mod scalbnf; @@ -285,6 +287,8 @@ pub use self::remainderf::remainderf; pub use self::remquo::remquo; pub use self::remquof::remquof; pub use self::round::round; +pub use self::roundeven::roundeven; +pub use self::roundevenf::roundevenf; pub use self::roundf::roundf; pub use self::scalbn::scalbn; pub use self::scalbnf::scalbnf; diff --git a/library/compiler-builtins/libm/src/math/roundeven.rs b/library/compiler-builtins/libm/src/math/roundeven.rs new file mode 100644 index 000000000000..5cc30c8af828 --- /dev/null +++ b/library/compiler-builtins/libm/src/math/roundeven.rs @@ -0,0 +1,50 @@ +// Source: musl libm rint +// (equivalent to roundeven when rounding mode is default, +// which Rust assumes) + +#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] +pub fn roundeven(x: f64) -> f64 { + let one_over_e = 1.0 / f64::EPSILON; + let as_u64: u64 = x.to_bits(); + let exponent: u64 = as_u64 >> 52 & 0x7ff; + let is_positive = (as_u64 >> 63) == 0; + if exponent >= 0x3ff + 52 { + x + } else { + let ans = if is_positive { + x + one_over_e - one_over_e + } else { + x - one_over_e + one_over_e + }; + + if ans == 0.0 { + if is_positive { + 0.0 + } else { + -0.0 + } + } else { + ans + } + } +} + +#[cfg(test)] +mod tests { + use super::roundeven; + + #[test] + fn negative_zero() { + assert_eq!(roundeven(-0.0_f64).to_bits(), (-0.0_f64).to_bits()); + } + + #[test] + fn sanity_check() { + assert_eq!(roundeven(-1.0), -1.0); + assert_eq!(roundeven(2.8), 3.0); + assert_eq!(roundeven(-0.5), -0.0); + assert_eq!(roundeven(0.5), 0.0); + assert_eq!(roundeven(-1.5), -2.0); + assert_eq!(roundeven(1.5), 2.0); + } +} diff --git a/library/compiler-builtins/libm/src/math/roundevenf.rs b/library/compiler-builtins/libm/src/math/roundevenf.rs new file mode 100644 index 000000000000..e720dcd94780 --- /dev/null +++ b/library/compiler-builtins/libm/src/math/roundevenf.rs @@ -0,0 +1,50 @@ +// Source: musl libm rintf +// (equivalent to roundevenf when rounding mode is default, +// which Rust assumes) + +#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] +pub fn roundevenf(x: f32) -> f32 { + let one_over_e = 1.0 / f32::EPSILON; + let as_u32: u32 = x.to_bits(); + let exponent: u32 = as_u32 >> 23 & 0xff; + let is_positive = (as_u32 >> 31) == 0; + if exponent >= 0x7f + 23 { + x + } else { + let ans = if is_positive { + x + one_over_e - one_over_e + } else { + x - one_over_e + one_over_e + }; + + if ans == 0.0 { + if is_positive { + 0.0 + } else { + -0.0 + } + } else { + ans + } + } +} + +#[cfg(test)] +mod tests { + use super::roundevenf; + + #[test] + fn negative_zero() { + assert_eq!(roundevenf(-0.0_f32).to_bits(), (-0.0_f32).to_bits()); + } + + #[test] + fn sanity_check() { + assert_eq!(roundevenf(-1.0), -1.0); + assert_eq!(roundevenf(2.8), 3.0); + assert_eq!(roundevenf(-0.5), -0.0); + assert_eq!(roundevenf(0.5), 0.0); + assert_eq!(roundevenf(-1.5), -2.0); + assert_eq!(roundevenf(1.5), 2.0); + } +} From 292221cf4c1055850c219f141525c7cfade0cab6 Mon Sep 17 00:00:00 2001 From: Jules Bertholet Date: Mon, 7 Nov 2022 12:53:26 -0500 Subject: [PATCH 2/4] `rint`/`rintf` instead of `roundeven`/`roundevenf` --- library/compiler-builtins/libm/build.rs | 3 --- .../compiler-builtins/libm/src/math/mod.rs | 8 +++---- .../libm/src/math/{roundeven.rs => rint.rs} | 22 ++++++++----------- .../libm/src/math/{roundevenf.rs => rintf.rs} | 22 ++++++++----------- 4 files changed, 22 insertions(+), 33 deletions(-) rename library/compiler-builtins/libm/src/math/{roundeven.rs => rint.rs} (59%) rename library/compiler-builtins/libm/src/math/{roundevenf.rs => rintf.rs} (58%) diff --git a/library/compiler-builtins/libm/build.rs b/library/compiler-builtins/libm/build.rs index 403304a1383b..80145a9ccac9 100644 --- a/library/compiler-builtins/libm/build.rs +++ b/library/compiler-builtins/libm/build.rs @@ -39,9 +39,6 @@ mod musl_reference_tests { "jnf.rs", "j1.rs", "j1f.rs", - // musl doens't have these - "roundeven.rs", - "roundevenf.rs", ]; struct Function { diff --git a/library/compiler-builtins/libm/src/math/mod.rs b/library/compiler-builtins/libm/src/math/mod.rs index e710bd381bc1..05ebb708c9c5 100644 --- a/library/compiler-builtins/libm/src/math/mod.rs +++ b/library/compiler-builtins/libm/src/math/mod.rs @@ -170,9 +170,9 @@ mod remainder; mod remainderf; mod remquo; mod remquof; +mod rint; +mod rintf; mod round; -mod roundeven; -mod roundevenf; mod roundf; mod scalbn; mod scalbnf; @@ -286,9 +286,9 @@ pub use self::remainder::remainder; pub use self::remainderf::remainderf; pub use self::remquo::remquo; pub use self::remquof::remquof; +pub use self::rint::rint; +pub use self::rintf::rintf; pub use self::round::round; -pub use self::roundeven::roundeven; -pub use self::roundevenf::roundevenf; pub use self::roundf::roundf; pub use self::scalbn::scalbn; pub use self::scalbnf::scalbnf; diff --git a/library/compiler-builtins/libm/src/math/roundeven.rs b/library/compiler-builtins/libm/src/math/rint.rs similarity index 59% rename from library/compiler-builtins/libm/src/math/roundeven.rs rename to library/compiler-builtins/libm/src/math/rint.rs index 5cc30c8af828..97d167ab8358 100644 --- a/library/compiler-builtins/libm/src/math/roundeven.rs +++ b/library/compiler-builtins/libm/src/math/rint.rs @@ -1,9 +1,5 @@ -// Source: musl libm rint -// (equivalent to roundeven when rounding mode is default, -// which Rust assumes) - #[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] -pub fn roundeven(x: f64) -> f64 { +pub fn rint(x: f64) -> f64 { let one_over_e = 1.0 / f64::EPSILON; let as_u64: u64 = x.to_bits(); let exponent: u64 = as_u64 >> 52 & 0x7ff; @@ -31,20 +27,20 @@ pub fn roundeven(x: f64) -> f64 { #[cfg(test)] mod tests { - use super::roundeven; + use super::rint; #[test] fn negative_zero() { - assert_eq!(roundeven(-0.0_f64).to_bits(), (-0.0_f64).to_bits()); + assert_eq!(rint(-0.0_f64).to_bits(), (-0.0_f64).to_bits()); } #[test] fn sanity_check() { - assert_eq!(roundeven(-1.0), -1.0); - assert_eq!(roundeven(2.8), 3.0); - assert_eq!(roundeven(-0.5), -0.0); - assert_eq!(roundeven(0.5), 0.0); - assert_eq!(roundeven(-1.5), -2.0); - assert_eq!(roundeven(1.5), 2.0); + assert_eq!(rint(-1.0), -1.0); + assert_eq!(rint(2.8), 3.0); + assert_eq!(rint(-0.5), -0.0); + assert_eq!(rint(0.5), 0.0); + assert_eq!(rint(-1.5), -2.0); + assert_eq!(rint(1.5), 2.0); } } diff --git a/library/compiler-builtins/libm/src/math/roundevenf.rs b/library/compiler-builtins/libm/src/math/rintf.rs similarity index 58% rename from library/compiler-builtins/libm/src/math/roundevenf.rs rename to library/compiler-builtins/libm/src/math/rintf.rs index e720dcd94780..7b87fafb3c58 100644 --- a/library/compiler-builtins/libm/src/math/roundevenf.rs +++ b/library/compiler-builtins/libm/src/math/rintf.rs @@ -1,9 +1,5 @@ -// Source: musl libm rintf -// (equivalent to roundevenf when rounding mode is default, -// which Rust assumes) - #[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] -pub fn roundevenf(x: f32) -> f32 { +pub fn rintf(x: f32) -> f32 { let one_over_e = 1.0 / f32::EPSILON; let as_u32: u32 = x.to_bits(); let exponent: u32 = as_u32 >> 23 & 0xff; @@ -31,20 +27,20 @@ pub fn roundevenf(x: f32) -> f32 { #[cfg(test)] mod tests { - use super::roundevenf; + use super::rintf; #[test] fn negative_zero() { - assert_eq!(roundevenf(-0.0_f32).to_bits(), (-0.0_f32).to_bits()); + assert_eq!(rintf(-0.0_f32).to_bits(), (-0.0_f32).to_bits()); } #[test] fn sanity_check() { - assert_eq!(roundevenf(-1.0), -1.0); - assert_eq!(roundevenf(2.8), 3.0); - assert_eq!(roundevenf(-0.5), -0.0); - assert_eq!(roundevenf(0.5), 0.0); - assert_eq!(roundevenf(-1.5), -2.0); - assert_eq!(roundevenf(1.5), 2.0); + assert_eq!(rintf(-1.0), -1.0); + assert_eq!(rintf(2.8), 3.0); + assert_eq!(rintf(-0.5), -0.0); + assert_eq!(rintf(0.5), 0.0); + assert_eq!(rintf(-1.5), -2.0); + assert_eq!(rintf(1.5), 2.0); } } From 83524d4aa286c80207b4742cb49b96e3c452d521 Mon Sep 17 00:00:00 2001 From: Jules Bertholet Date: Mon, 7 Nov 2022 13:19:05 -0500 Subject: [PATCH 3/4] Disable tests on PowerPC --- library/compiler-builtins/libm/src/math/rint.rs | 2 ++ library/compiler-builtins/libm/src/math/rintf.rs | 2 ++ 2 files changed, 4 insertions(+) diff --git a/library/compiler-builtins/libm/src/math/rint.rs b/library/compiler-builtins/libm/src/math/rint.rs index 97d167ab8358..0c6025c1f73d 100644 --- a/library/compiler-builtins/libm/src/math/rint.rs +++ b/library/compiler-builtins/libm/src/math/rint.rs @@ -25,6 +25,8 @@ pub fn rint(x: f64) -> f64 { } } +// 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::rint; diff --git a/library/compiler-builtins/libm/src/math/rintf.rs b/library/compiler-builtins/libm/src/math/rintf.rs index 7b87fafb3c58..d427793f7fc6 100644 --- a/library/compiler-builtins/libm/src/math/rintf.rs +++ b/library/compiler-builtins/libm/src/math/rintf.rs @@ -25,6 +25,8 @@ pub fn rintf(x: f32) -> f32 { } } +// 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::rintf; From 90128a1abb9b1a30c3b4dcc322ba408d6d5e24e6 Mon Sep 17 00:00:00 2001 From: Jules Bertholet Date: Mon, 7 Nov 2022 23:43:14 -0500 Subject: [PATCH 4/4] Add benchmarks --- .../compiler-builtins/libm/crates/libm-bench/benches/bench.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/library/compiler-builtins/libm/crates/libm-bench/benches/bench.rs b/library/compiler-builtins/libm/crates/libm-bench/benches/bench.rs index b6d8741531f3..ca999b90f27c 100644 --- a/library/compiler-builtins/libm/crates/libm-bench/benches/bench.rs +++ b/library/compiler-builtins/libm/crates/libm-bench/benches/bench.rs @@ -107,7 +107,8 @@ macro_rules! bessel { unary!( acos, acosh, asin, atan, cbrt, ceil, cos, cosh, erf, exp, exp2, exp10, expm1, fabs, floor, j0, - j1, lgamma, log, log1p, log2, log10, round, sin, sinh, sqrt, tan, tanh, tgamma, trunc, y0, y1 + j1, lgamma, log, log1p, log2, log10, rint, round, sin, sinh, sqrt, tan, tanh, tgamma, trunc, + y0, y1 ); binary!(atan2, copysign, fdim, fmax, fmin, fmod, hypot, pow); trinary!(fma);