about summary refs log tree commit diff
diff options
context:
space:
mode:
authorLokathor <zefria@gmail.com>2021-07-02 06:47:03 -0600
committerGitHub <noreply@github.com>2021-07-02 06:47:03 -0600
commit0dc91d40e69552b4ec9be86c3cb2c659b218e7a4 (patch)
tree96b1bdf76c508bf1a001620b8c3fe1d9bb8d1c99
parent777b8fa251e71173804b8169cc6aa7702801ec14 (diff)
parent5f23bf3c9bc4cf1681586003c3dca877ad0760a6 (diff)
downloadrust-0dc91d40e69552b4ec9be86c3cb2c659b218e7a4.tar.gz
rust-0dc91d40e69552b4ec9be86c3cb2c659b218e7a4.zip
Merge pull request rust-lang/libm#253 from bvinc/round_slow
Optimize round and roundf
-rw-r--r--library/compiler-builtins/libm/src/math/round.rs46
-rw-r--r--library/compiler-builtins/libm/src/math/roundf.rs44
2 files changed, 28 insertions, 62 deletions
diff --git a/library/compiler-builtins/libm/src/math/round.rs b/library/compiler-builtins/libm/src/math/round.rs
index bf72f5b941d..46fabc90ff5 100644
--- a/library/compiler-builtins/libm/src/math/round.rs
+++ b/library/compiler-builtins/libm/src/math/round.rs
@@ -1,38 +1,10 @@
+use super::copysign;
+use super::trunc;
 use core::f64;
 
-const TOINT: f64 = 1.0 / f64::EPSILON;
-
 #[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
-pub fn round(mut x: f64) -> f64 {
-    let i = x.to_bits();
-    let e: u64 = i >> 52 & 0x7ff;
-    let mut y: f64;
-
-    if e >= 0x3ff + 52 {
-        return x;
-    }
-    if e < 0x3ff - 1 {
-        // raise inexact if x!=0
-        force_eval!(x + TOINT);
-        return 0.0 * x;
-    }
-    if i >> 63 != 0 {
-        x = -x;
-    }
-    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
-    }
+pub fn round(x: f64) -> f64 {
+    trunc(x + copysign(0.5 - 0.25 * f64::EPSILON, x))
 }
 
 #[cfg(test)]
@@ -43,4 +15,14 @@ mod tests {
     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);
+    }
 }
diff --git a/library/compiler-builtins/libm/src/math/roundf.rs b/library/compiler-builtins/libm/src/math/roundf.rs
index 497e88d6254..c0872a7829d 100644
--- a/library/compiler-builtins/libm/src/math/roundf.rs
+++ b/library/compiler-builtins/libm/src/math/roundf.rs
@@ -1,36 +1,10 @@
+use super::copysignf;
+use super::truncf;
 use core::f32;
 
-const TOINT: f32 = 1.0 / f32::EPSILON;
-
 #[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
-pub fn roundf(mut x: f32) -> f32 {
-    let i = x.to_bits();
-    let e: u32 = i >> 23 & 0xff;
-    let mut y: f32;
-
-    if e >= 0x7f + 23 {
-        return x;
-    }
-    if e < 0x7f - 1 {
-        force_eval!(x + TOINT);
-        return 0.0 * x;
-    }
-    if i >> 31 != 0 {
-        x = -x;
-    }
-    y = x + TOINT - TOINT - x;
-    if y > 0.5f32 {
-        y = y + x - 1.0;
-    } else if y <= -0.5f32 {
-        y = y + x + 1.0;
-    } else {
-        y = y + x;
-    }
-    if i >> 31 != 0 {
-        -y
-    } else {
-        y
-    }
+pub fn roundf(x: f32) -> f32 {
+    truncf(x + copysignf(0.5 - 0.25 * f32::EPSILON, x))
 }
 
 #[cfg(test)]
@@ -41,4 +15,14 @@ mod tests {
     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);
+    }
 }