diff --git a/library/compiler-builtins/libm/src/lib.rs b/library/compiler-builtins/libm/src/lib.rs index fc9628d919f3..f54366b95ae2 100644 --- a/library/compiler-builtins/libm/src/lib.rs +++ b/library/compiler-builtins/libm/src/lib.rs @@ -12,6 +12,12 @@ #![deny(warnings)] #![no_std] +macro_rules! force_eval { + ($e:expr) => { + unsafe { ::core::ptr::read_volatile(&$e); } + } +} + mod math; #[cfg(todo)] diff --git a/library/compiler-builtins/libm/src/math/mod.rs b/library/compiler-builtins/libm/src/math/mod.rs index 09d81944c27b..c150a629516c 100644 --- a/library/compiler-builtins/libm/src/math/mod.rs +++ b/library/compiler-builtins/libm/src/math/mod.rs @@ -2,6 +2,7 @@ mod fabs; mod fabsf; mod fmodf; mod powf; +mod round; mod scalbnf; mod sqrtf; @@ -9,6 +10,7 @@ pub use self::fabs::fabs; pub use self::fabsf::fabsf; pub use self::fmodf::fmodf; pub use self::powf::powf; +pub use self::round::round; pub use self::scalbnf::scalbnf; pub use self::sqrtf::sqrtf; diff --git a/library/compiler-builtins/libm/src/math/round.rs b/library/compiler-builtins/libm/src/math/round.rs new file mode 100644 index 000000000000..2a9f67c1d0fa --- /dev/null +++ b/library/compiler-builtins/libm/src/math/round.rs @@ -0,0 +1,35 @@ +use core::f64; + +const TOINT: f64 = 1.0 / f64::EPSILON; + +pub fn round(mut x: f64) -> f64 { + let (f, i) = (x, x.to_bits()); + let e: u64 = i >> 52 & 0x7ff; + let mut y: f64; + + if e >= 0x3ff + 52 { + return x; + } + if i >> 63 != 0 { + x = -x; + } + if e < 0x3ff - 1 { + // raise inexact if x!=0 + force_eval!(x + TOINT); + return 0.0 * f; + } + y = x + TOINT - TOINT - x; + if y > 0.5 { + y = y + x - 1.0; + } else if y <= -0.5 { + y = y + x + 1.0; + } else { + y = y + x; + } + + if i >> 63 != 0 { + -y + } else { + y + } +} diff --git a/library/compiler-builtins/libm/test-generator/src/main.rs b/library/compiler-builtins/libm/test-generator/src/main.rs index a13aa4ef705a..5ff78ffc8b37 100644 --- a/library/compiler-builtins/libm/test-generator/src/main.rs +++ b/library/compiler-builtins/libm/test-generator/src/main.rs @@ -618,7 +618,7 @@ f64_f64! { // log10, // log1p, // log2, - // round, + round, // sin, // sinh, // sqrt,