Skip to content

Commit

Permalink
Fix testcases on x87
Browse files Browse the repository at this point in the history
  • Loading branch information
Peter Michael Green committed Jan 5, 2021
1 parent 98c21c7 commit 2011c92
Show file tree
Hide file tree
Showing 7 changed files with 84 additions and 8 deletions.
19 changes: 19 additions & 0 deletions src/math/ceil.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#![allow(unreachable_code)]
use core::f64;

const TOINT: f64 = 1. / f64::EPSILON;
Expand All @@ -15,6 +16,24 @@ pub fn ceil(x: f64) -> f64 {
return unsafe { ::core::intrinsics::ceilf64(x) }
}
}
#[cfg(all(target_arch = "x86", not(target_feature = "sse2")))]
{
//use an alternative implementation on x86, because the
//main implementation fails with the x87 FPU used by
//debian i386, probablly due to excess precision issues.
//basic implementation taken from https://github.com/rust-lang/libm/issues/219
use super::fabs;
if fabs(x).to_bits() < 4503599627370496.0_f64.to_bits() {
let truncated = x as i64 as f64;
if truncated < x {
return truncated + 1.0;
} else {
return truncated;
}
} else {
return x;
}
}
let u: u64 = x.to_bits();
let e: i64 = (u >> 52 & 0x7ff) as i64;
let y: f64;
Expand Down
19 changes: 19 additions & 0 deletions src/math/floor.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#![allow(unreachable_code)]
use core::f64;

const TOINT: f64 = 1. / f64::EPSILON;
Expand All @@ -15,6 +16,24 @@ pub fn floor(x: f64) -> f64 {
return unsafe { ::core::intrinsics::floorf64(x) }
}
}
#[cfg(all(target_arch = "x86", not(target_feature = "sse2")))]
{
//use an alternative implementation on x86, because the
//main implementation fails with the x87 FPU used by
//debian i386, probablly due to excess precision issues.
//basic implementation taken from https://github.com/rust-lang/libm/issues/219
use super::fabs;
if fabs(x).to_bits() < 4503599627370496.0_f64.to_bits() {
let truncated = x as i64 as f64;
if truncated > x {
return truncated - 1.0;
} else {
return truncated;
}
} else {
return x;
}
}
let ui = x.to_bits();
let e = ((ui >> 52) & 0x7ff) as i32;

Expand Down
6 changes: 5 additions & 1 deletion src/math/j1f.rs
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,10 @@ mod tests {
}
#[test]
fn test_y1f_2002() {
assert_eq!(y1f(2.0000002_f32), -0.10703229_f32);
//allow slightly different result on x87
let res = y1f(2.0000002_f32);
if res != -0.10703231_f32 {
assert_eq!(res, -0.10703229_f32);
}
}
}
4 changes: 3 additions & 1 deletion src/math/rem_pio2f.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,9 @@ pub(crate) fn rem_pio2f(x: f32) -> (i32, f64) {
if ix < 0x4dc90fdb {
/* |x| ~< 2^28*(pi/2), medium size */
/* Use a specialized rint() to get fn. Assume round-to-nearest. */
let f_n = x64 * INV_PIO2 + TOINT - TOINT;
// use to_bits and from_bits to force rounding to storage format on
// x87.
let f_n = f64::from_bits((x64 * INV_PIO2 + TOINT).to_bits()) - TOINT;
return (f_n as i32, x64 - f_n * PIO2_1 - f_n * PIO2_1T);
}
if ix >= 0x7f800000 {
Expand Down
4 changes: 3 additions & 1 deletion src/math/round.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ pub fn round(mut x: f64) -> f64 {
if i >> 63 != 0 {
x = -x;
}
y = x + TOINT - TOINT - x;
// use to_bits and from_bits to force rounding to storage format on
// x87.
y = f64::from_bits((x + TOINT).to_bits()) - TOINT - x;
if y > 0.5 {
y = y + x - 1.0;
} else if y <= -0.5 {
Expand Down
4 changes: 3 additions & 1 deletion src/math/roundf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ pub fn roundf(mut x: f32) -> f32 {
if i >> 31 != 0 {
x = -x;
}
y = x + TOINT - TOINT - x;
// use to_bits and from_bits to force rounding to storage format on
// x87.
y = f32::from_bits((x + TOINT).to_bits()) - TOINT - x;
if y > 0.5f32 {
y = y + x - 1.0;
} else if y <= -0.5f32 {
Expand Down
36 changes: 32 additions & 4 deletions src/math/sincosf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,10 +145,38 @@ mod tests {
let (s_minus, c_minus) = sincosf(theta - 2. * PI);

const TOLERANCE: f32 = 1e-6;
assert!((s - s_plus).abs() < TOLERANCE);
assert!((s - s_minus).abs() < TOLERANCE);
assert!((c - c_plus).abs() < TOLERANCE);
assert!((c - c_minus).abs() < TOLERANCE);
assert!(
(s - s_plus).abs() < TOLERANCE,
"|{} - {}| = {} >= {}",
s,
s_plus,
(s - s_plus).abs(),
TOLERANCE
);
assert!(
(s - s_minus).abs() < TOLERANCE,
"|{} - {}| = {} >= {}",
s,
s_minus,
(s - s_minus).abs(),
TOLERANCE
);
assert!(
(c - c_plus).abs() < TOLERANCE,
"|{} - {}| = {} >= {}",
c,
c_plus,
(c - c_plus).abs(),
TOLERANCE
);
assert!(
(c - c_minus).abs() < TOLERANCE,
"|{} - {}| = {} >= {}",
c,
c_minus,
(c - c_minus).abs(),
TOLERANCE
);
}
}
}

0 comments on commit 2011c92

Please sign in to comment.