]> git.proxmox.com Git - debcargo-conf.git/commitdiff
libm - update x87 patches to more closely match accepted upstream PR.
authorPeter Michael Green <plugwash@debian.org>
Tue, 4 Jan 2022 23:04:30 +0000 (23:04 +0000)
committerPeter Michael Green <plugwash@debian.org>
Sat, 8 Jan 2022 11:04:56 +0000 (11:04 +0000)
14 files changed:
src/libm/debian/changelog
src/libm/debian/copyright.debcargo.hint
src/libm/debian/patches/fix-rem-pio2.patch [deleted file]
src/libm/debian/patches/fix-tests.patch [deleted file]
src/libm/debian/patches/fix-unused-result-error.patch [new file with mode: 0644]
src/libm/debian/patches/series
src/libm/debian/patches/x87-01-force-test-eval-runtime.patch [new file with mode: 0644]
src/libm/debian/patches/x87-02-fix-testcases.patch [new file with mode: 0644]
src/libm/debian/patches/x87-03-use-force-eval.patch [new file with mode: 0644]
src/libm/debian/patches/x87-04-fix-rem-pio2.patch [new file with mode: 0644]
src/libm/debian/patches/x87-05-round-to-storage-format-in.tests.patch [new file with mode: 0644]
src/libm/debian/patches/x87-06-only-allow-x87-result-on-x87.patch [new file with mode: 0644]
src/libm/debian/patches/x87-07-allow-force-eval-to-produce-result.patch [new file with mode: 0644]
src/libm/debian/patches/x87-08-fix-round-and-roundf.patch [new file with mode: 0644]

index 4f286d192fe185dc33a3c92e23a13e0ff94714e6..265083707bad2e52d6f585decc550ee3a06210b4 100644 (file)
@@ -1,3 +1,15 @@
+rust-libm (0.2.1-5) UNRELEASED-FIXME-AUTOGENERATED-DEBCARGO; urgency=medium
+
+  * Team upload.
+  * Package libm 0.2.1 from crates.io using debcargo 2.5.0
+  * Apply an upstream fix that fixes a build error when manually running
+    cargo test (this doesn't seem to apply when running under cargo_auto_test,
+    it appears cargo_auto_test overrides the maximum lint level somehow).
+  * Update x87 patches to more closely match what was accepted upstream
+    and to fix most errors in release mode as well as debug mode.
+
+ -- Peter Michael Green <plugwash@debian.org>  Tue, 04 Jan 2022 22:59:50 +0000
+
 rust-libm (0.2.1-4) unstable; urgency=medium
 
   * Team upload.
index 7c42bacfb498f02bb6a154361fdb3a81a8b035f8..33a80585bcfbfbd227d1c449326469aa8e067184 100644 (file)
@@ -413,8 +413,8 @@ Comment:
 
 Files: debian/*
 Copyright:
- 2020-2021 Debian Rust Maintainers <pkg-rust-maintainers@alioth-lists.debian.net>
- 2020-2021 Andrej Shadura <andrewsh@debian.org>
+ 2020-2022 Debian Rust Maintainers <pkg-rust-maintainers@alioth-lists.debian.net>
+ 2020-2022 Andrej Shadura <andrewsh@debian.org>
 License: MIT or Apache-2.0
 
 License: Apache-2.0
diff --git a/src/libm/debian/patches/fix-rem-pio2.patch b/src/libm/debian/patches/fix-rem-pio2.patch
deleted file mode 100644 (file)
index dce8069..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-Index: rust-libm-0.2.1/src/math/rem_pio2.rs
-===================================================================
---- rust-libm-0.2.1.orig/src/math/rem_pio2.rs
-+++ rust-libm-0.2.1/src/math/rem_pio2.rs
-@@ -50,7 +50,9 @@ pub(crate) fn rem_pio2(x: f64) -> (i32,
-     fn medium(x: f64, ix: u32) -> (i32, f64, f64) {
-         /* rint(x/(pi/2)), Assume round-to-nearest. */
--        let f_n = x as f64 * INV_PIO2 + TO_INT - TO_INT;
-+        //use to_bits and from_bits to force rounding to the storage format,
-+        //otherwise this doesn't work on x87
-+        let f_n = f64::from_bits((x as f64 * INV_PIO2 + TO_INT).to_bits()) - TO_INT;
-         let n = f_n as i32;
-         let mut r = x - f_n * PIO2_1;
-         let mut w = f_n * PIO2_1T; /* 1st round, good to 85 bits */
diff --git a/src/libm/debian/patches/fix-tests.patch b/src/libm/debian/patches/fix-tests.patch
deleted file mode 100644 (file)
index 848dd15..0000000
+++ /dev/null
@@ -1,148 +0,0 @@
-From 1b41fb03b51740a4323e5dbb09390b30a8f926f8 Mon Sep 17 00:00:00 2001
-From: Peter Michael Green <plugwash@debian.org>
-Date: Sat, 2 Jan 2021 04:11:40 +0000
-Subject: [PATCH] Fix testcases on x87
-
----
- src/lib.rs            |  1 +
- src/math/ceil.rs      | 17 +++++++++++++++++
- src/math/floor.rs     | 17 +++++++++++++++++
- src/math/j1f.rs       |  6 +++++-
- src/math/rem_pio2f.rs |  2 +-
- src/math/round.rs     |  2 +-
- src/math/roundf.rs    |  2 +-
- src/math/sincosf.rs   |  5 ++++-
- 8 files changed, 47 insertions(+), 5 deletions(-)
-
---- a/src/lib.rs
-+++ b/src/lib.rs
-@@ -1,5 +1,6 @@
- //! libm in pure Rust
- #![deny(warnings)]
-+#![allow(unreachable_code)]
- #![no_std]
- #![cfg_attr(
-     all(target_arch = "wasm32", feature = "unstable"),
---- a/src/math/ceil.rs
-+++ b/src/math/ceil.rs
-@@ -1,4 +1,5 @@
- use core::f64;
-+use super::fabs;
- const TOINT: f64 = 1. / f64::EPSILON;
-@@ -15,6 +16,22 @@ pub fn ceil(x: f64) -> f64 {
-             return unsafe { ::core::intrinsics::ceilf64(x) }
-         }
-     }
-+    #[cfg(target_arch = "x86")] {
-+        //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
-+        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;
---- a/src/math/floor.rs
-+++ b/src/math/floor.rs
-@@ -1,4 +1,5 @@
- use core::f64;
-+use super::fabs;
- const TOINT: f64 = 1. / f64::EPSILON;
-@@ -15,6 +16,22 @@ pub fn floor(x: f64) -> f64 {
-             return unsafe { ::core::intrinsics::floorf64(x) }
-         }
-     }
-+    #[cfg(target_arch = "x86")] {
-+        //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
-+        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;
---- a/src/math/j1f.rs
-+++ b/src/math/j1f.rs
-@@ -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);
-+        }
-     }
- }
---- a/src/math/rem_pio2f.rs
-+++ b/src/math/rem_pio2f.rs
-@@ -43,7 +43,7 @@ pub(crate) fn rem_pio2f(x: f32) -> (i32,
-     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;
-+        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 {
---- a/src/math/round.rs
-+++ b/src/math/round.rs
-@@ -19,7 +19,7 @@ pub fn round(mut x: f64) -> f64 {
-     if i >> 63 != 0 {
-         x = -x;
-     }
--    y = x + TOINT - TOINT - x;
-+    y = f64::from_bits((x + TOINT).to_bits()) - TOINT - x;
-     if y > 0.5 {
-         y = y + x - 1.0;
-     } else if y <= -0.5 {
---- a/src/math/roundf.rs
-+++ b/src/math/roundf.rs
-@@ -18,7 +18,7 @@ pub fn roundf(mut x: f32) -> f32 {
-     if i >> 31 != 0 {
-         x = -x;
-     }
--    y = x + TOINT - TOINT - x;
-+    y = f32::from_bits((x + TOINT).to_bits()) - TOINT - x;
-     if y > 0.5f32 {
-         y = y + x - 1.0;
-     } else if y <= -0.5f32 {
---- a/src/math/sincosf.rs
-+++ b/src/math/sincosf.rs
-@@ -145,7 +145,10 @@ mod tests {
-             let (s_minus, c_minus) = sincosf(theta - 2. * PI);
-             const TOLERANCE: f32 = 1e-6;
--            assert!((s - s_plus).abs() < TOLERANCE);
-+            //hack so it's possible to see how far out of tolerance the results are
-+            if (s - s_plus).abs() >= TOLERANCE {
-+                assert_eq!((s - s_plus).abs(),TOLERANCE);
-+            }
-             assert!((s - s_minus).abs() < TOLERANCE);
-             assert!((c - c_plus).abs() < TOLERANCE);
-             assert!((c - c_minus).abs() < TOLERANCE);
diff --git a/src/libm/debian/patches/fix-unused-result-error.patch b/src/libm/debian/patches/fix-unused-result-error.patch
new file mode 100644 (file)
index 0000000..e9290ce
--- /dev/null
@@ -0,0 +1,28 @@
+commit c18c704856ffa8b3349401300e66796d4cc8d4f5
+Author: Jethro Beekman <jethro@fortanix.com>
+Date:   Thu Jun 24 15:58:36 2021 +0200
+
+    Fix build failure with latest nightly
+
+diff --git a/src/math/pow.rs b/src/math/pow.rs
+index c7fd0df..f79680a 100644
+--- a/src/math/pow.rs
++++ b/src/math/pow.rs
+@@ -604,7 +604,7 @@ mod tests {
+         // Factoring -1 out:
+         // (negative anything ^ integer should be (-1 ^ integer) * (positive anything ^ integer))
+-        &[POS_ZERO, NEG_ZERO, POS_ONE, NEG_ONE, POS_EVENS, NEG_EVENS]
++        (&[POS_ZERO, NEG_ZERO, POS_ONE, NEG_ONE, POS_EVENS, NEG_EVENS])
+             .iter()
+             .for_each(|int_set| {
+                 int_set.iter().for_each(|int| {
+@@ -616,7 +616,7 @@ mod tests {
+         // Negative base (imaginary results):
+         // (-anything except 0 and Infinity ^ non-integer should be NAN)
+-        &NEG[1..(NEG.len() - 1)].iter().for_each(|set| {
++        (&NEG[1..(NEG.len() - 1)]).iter().for_each(|set| {
+             set.iter().for_each(|val| {
+                 test_sets(&ALL[3..7], &|v: f64| pow(*val, v), &|_| NAN);
+             })
index ba04ace7db63cb390af20b8b0340ef7d988fd3fc..80554cf6264b5d5f377575a98345feac8b004b89 100644 (file)
@@ -1,3 +1,10 @@
 features.patch
-fix-tests.patch
-fix-rem-pio2.patch
+fix-unused-result-error.patch
+x87-01-force-test-eval-runtime.patch
+x87-02-fix-testcases.patch
+x87-03-use-force-eval.patch
+x87-04-fix-rem-pio2.patch
+x87-05-round-to-storage-format-in.tests.patch
+x87-06-only-allow-x87-result-on-x87.patch
+x87-07-allow-force-eval-to-produce-result.patch
+x87-08-fix-round-and-roundf.patch
diff --git a/src/libm/debian/patches/x87-01-force-test-eval-runtime.patch b/src/libm/debian/patches/x87-01-force-test-eval-runtime.patch
new file mode 100644 (file)
index 0000000..7456c35
--- /dev/null
@@ -0,0 +1,43 @@
+commit 5672d6722919a6bdd9fbb386eec667fb091f4cbc
+Author: Peter Michael Green <plugwash@debian.org>
+Date:   Wed Dec 22 00:56:18 2021 +0000
+
+    force test_near_pi in rem_pio2.rs to be evaluated at runtime not compiletime.
+
+diff --git a/src/math/rem_pio2.rs b/src/math/rem_pio2.rs
+index 46f7c38..f58fa35 100644
+--- a/src/math/rem_pio2.rs
++++ b/src/math/rem_pio2.rs
+@@ -190,20 +190,28 @@ mod tests {
+     #[test]
+     fn test_near_pi() {
++        let arg = 3.141592025756836;
++        force_eval!(arg);
+         assert_eq!(
+-            rem_pio2(3.141592025756836),
++            rem_pio2(arg),
+             (2, -6.278329573009626e-7, -2.1125998133974653e-23)
+         );
++        let arg = 3.141592033207416;
++        force_eval!(arg);
+         assert_eq!(
+-            rem_pio2(3.141592033207416),
++            rem_pio2(arg),
+             (2, -6.20382377148128e-7, -2.1125998133974653e-23)
+         );
++        let arg = 3.141592144966125;
++        force_eval!(arg);
+         assert_eq!(
+-            rem_pio2(3.141592144966125),
++            rem_pio2(arg),
+             (2, -5.086236681942706e-7, -2.1125998133974653e-23)
+         );
++        let arg = 3.141592979431152;
++        force_eval!(arg);
+         assert_eq!(
+-            rem_pio2(3.141592979431152),
++            rem_pio2(arg),
+             (2, 3.2584135866119817e-7, -2.1125998133974653e-23)
+         );
+     }
diff --git a/src/libm/debian/patches/x87-02-fix-testcases.patch b/src/libm/debian/patches/x87-02-fix-testcases.patch
new file mode 100644 (file)
index 0000000..d1fda48
--- /dev/null
@@ -0,0 +1,152 @@
+commit 8b0db9f5baacf87494547f23bb656c1903825baf
+Author: Peter Michael Green <plugwash@debian.org>
+Date:   Tue Jan 5 17:32:30 2021 +0000
+
+    Fix testcases on x87
+
+diff --git a/src/math/ceil.rs b/src/math/ceil.rs
+index eda28b9..22d8929 100644
+--- a/src/math/ceil.rs
++++ b/src/math/ceil.rs
+@@ -1,3 +1,4 @@
++#![allow(unreachable_code)]
+ use core::f64;
+ const TOINT: f64 = 1. / f64::EPSILON;
+@@ -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;
+diff --git a/src/math/floor.rs b/src/math/floor.rs
+index b2b7605..d09f9a1 100644
+--- a/src/math/floor.rs
++++ b/src/math/floor.rs
+@@ -1,3 +1,4 @@
++#![allow(unreachable_code)]
+ use core::f64;
+ const TOINT: f64 = 1. / f64::EPSILON;
+@@ -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;
+diff --git a/src/math/j1f.rs b/src/math/j1f.rs
+index 3369490..225b719 100644
+--- a/src/math/j1f.rs
++++ b/src/math/j1f.rs
+@@ -369,6 +369,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);
++        }
+     }
+ }
+diff --git a/src/math/rem_pio2f.rs b/src/math/rem_pio2f.rs
+index 5d392ba..4d4499b 100644
+--- a/src/math/rem_pio2f.rs
++++ b/src/math/rem_pio2f.rs
+@@ -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 {
+diff --git a/src/math/sincosf.rs b/src/math/sincosf.rs
+index 83c9f40..5304e8c 100644
+--- a/src/math/sincosf.rs
++++ b/src/math/sincosf.rs
+@@ -147,10 +147,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
++            );
+         }
+     }
+ }
diff --git a/src/libm/debian/patches/x87-03-use-force-eval.patch b/src/libm/debian/patches/x87-03-use-force-eval.patch
new file mode 100644 (file)
index 0000000..4587f27
--- /dev/null
@@ -0,0 +1,29 @@
+commit 16ce35bb191ed075dae3668257025feed2cf169f
+Author: Peter Michael Green <plugwash@debian.org>
+Date:   Tue Dec 21 22:41:29 2021 +0000
+
+    Use force_eval instead of to_bits/from_bits combination,
+    
+    Using to_bits/from_bits to force conversion to storage format
+    apparently doesn't work in release mode. Also add an architecture
+    conditional to avoid pessimising other architectures.
+
+diff --git a/src/math/rem_pio2f.rs b/src/math/rem_pio2f.rs
+index 4d4499b..3ce8f9a 100644
+--- a/src/math/rem_pio2f.rs
++++ b/src/math/rem_pio2f.rs
+@@ -43,9 +43,11 @@ 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. */
+-        // 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;
++        let tmp = x64 * INV_PIO2 + TOINT;
++        // force rounding of tmp to it's storage format on x87 to avoid
++        // excess precision issues.
++        #[cfg(all(target_arch = "x86", not(target_feature = "sse2")))]force_eval!(tmp);
++        let f_n = tmp - TOINT;
+         return (f_n as i32, x64 - f_n * PIO2_1 - f_n * PIO2_1T);
+     }
+     if ix >= 0x7f800000 {
diff --git a/src/libm/debian/patches/x87-04-fix-rem-pio2.patch b/src/libm/debian/patches/x87-04-fix-rem-pio2.patch
new file mode 100644 (file)
index 0000000..35cc913
--- /dev/null
@@ -0,0 +1,105 @@
+commit fa70d9bda797b5a78b1fb9a6ed7b372935f14e6e
+Author: Peter Michael Green <plugwash@debian.org>
+Date:   Tue Dec 21 23:53:06 2021 +0000
+
+    Add forced rounding to storage format for x87 to rem_pio2.rs as well.
+
+diff --git a/src/math/rem_pio2.rs b/src/math/rem_pio2.rs
+index f58fa35..4ac9415 100644
+--- a/src/math/rem_pio2.rs
++++ b/src/math/rem_pio2.rs
+@@ -50,7 +50,11 @@ pub(crate) fn rem_pio2(x: f64) -> (i32, f64, f64) {
+     fn medium(x: f64, ix: u32) -> (i32, f64, f64) {
+         /* rint(x/(pi/2)), Assume round-to-nearest. */
+-        let f_n = x as f64 * INV_PIO2 + TO_INT - TO_INT;
++        let tmp = x as f64 * INV_PIO2 + TO_INT;
++        // force rounding of tmp to it's storage format on x87 to avoid
++        // excess precision issues.
++        #[cfg(all(target_arch = "x86", not(target_feature = "sse2")))]force_eval!(tmp);
++        let f_n = tmp - TO_INT;
+         let n = f_n as i32;
+         let mut r = x - f_n * PIO2_1;
+         let mut w = f_n * PIO2_1T; /* 1st round, good to 85 bits */
+diff --git a/src/math/sincos.rs b/src/math/sincos.rs
+index d49f65c..bfc4561 100644
+--- a/src/math/sincos.rs
++++ b/src/math/sincos.rs
+@@ -57,3 +57,77 @@ pub fn sincos(x: f64) -> (f64, f64) {
+         _ => (0.0, 1.0),
+     }
+ }
++
++// These tests are based on those from sincosf.rs
++#[cfg(test)]
++mod tests {
++    use super::sincos;
++
++    const TOLERANCE: f64 = 1e-6;
++
++    #[test]
++    fn with_pi() {
++        let (s, c) = sincos(core::f64::consts::PI);
++        assert!(
++                (s - 0.0).abs() < TOLERANCE,
++                "|{} - {}| = {} >= {}",
++                s,
++                0.0,
++                (s - 0.0).abs(),
++                TOLERANCE
++            );
++        assert!(
++                (c + 1.0).abs() < TOLERANCE,
++                "|{} + {}| = {} >= {}",
++                c,
++                1.0,
++                (s + 1.0).abs(),
++                TOLERANCE
++            );
++    }
++
++    #[test]
++    fn rotational_symmetry() {
++        use core::f64::consts::PI;
++        const N: usize = 24;
++        for n in 0..N {
++            let theta = 2. * PI * (n as f64) / (N as f64);
++            let (s, c) = sincos(theta);
++            let (s_plus, c_plus) = sincos(theta + 2. * PI);
++            let (s_minus, c_minus) = sincos(theta - 2. * PI);
++
++            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
++            );
++        }
++    }
++}
diff --git a/src/libm/debian/patches/x87-05-round-to-storage-format-in.tests.patch b/src/libm/debian/patches/x87-05-round-to-storage-format-in.tests.patch
new file mode 100644 (file)
index 0000000..960ce14
--- /dev/null
@@ -0,0 +1,51 @@
+This patch is based on the commit below which has been submitted
+as part of https://github.com/rust-lang/libm/pull/249 
+adapted for use in the Debian package.
+
+commit db80cfb90663284dd351f85284cb2a1b295d4043
+Author: Peter Michael Green <plugwash@debian.org>
+Date:   Wed Dec 22 00:21:25 2021 +0000
+
+    round to storage format in some tests before comparison to prevent spurious errors on x87.
+
+Index: rust-libm-0.2.1/src/math/fma.rs
+===================================================================
+--- rust-libm-0.2.1.orig/src/math/fma.rs
++++ rust-libm-0.2.1/src/math/fma.rs
+@@ -218,6 +218,9 @@ mod tests {
+             -0.00000000000000022204460492503126,
+         );
+-        assert_eq!(fma(-0.992, -0.992, -0.992), -0.00793599999988632,);
++        let result = fma(-0.992, -0.992, -0.992);
++        //force rounding to storage format on x87 to prevent superious errors.
++        #[cfg(all(target_arch = "x86", not(target_feature = "sse2")))]force_eval!(result);
++        assert_eq!(result, -0.00793599999988632,);
+     }
+ }
+Index: rust-libm-0.2.1/src/math/pow.rs
+===================================================================
+--- rust-libm-0.2.1.orig/src/math/pow.rs
++++ rust-libm-0.2.1/src/math/pow.rs
+@@ -484,6 +484,8 @@ mod tests {
+                 let exp = expected(*val);
+                 let res = computed(*val);
++                #[cfg(all(target_arch = "x86", not(target_feature = "sse2")))]force_eval!(exp);
++                #[cfg(all(target_arch = "x86", not(target_feature = "sse2")))]force_eval!(res);
+                 assert!(
+                     if exp.is_nan() {
+                         res.is_nan()
+Index: rust-libm-0.2.1/src/math/sin.rs
+===================================================================
+--- rust-libm-0.2.1.orig/src/math/sin.rs
++++ rust-libm-0.2.1/src/math/sin.rs
+@@ -81,5 +81,7 @@ pub fn sin(x: f64) -> f64 {
+ fn test_near_pi() {
+     let x = f64::from_bits(0x400921fb000FD5DD); // 3.141592026217707
+     let sx = f64::from_bits(0x3ea50d15ced1a4a2); // 6.273720864039205e-7
+-    assert_eq!(sin(x), sx);
++    let result = sin(x);
++    #[cfg(all(target_arch = "x86", not(target_feature = "sse2")))]force_eval!(result);
++    assert_eq!(result, sx);
+ }
diff --git a/src/libm/debian/patches/x87-06-only-allow-x87-result-on-x87.patch b/src/libm/debian/patches/x87-06-only-allow-x87-result-on-x87.patch
new file mode 100644 (file)
index 0000000..69aca9d
--- /dev/null
@@ -0,0 +1,21 @@
+commit 1606eeae5c1a916adb926d2972ab63a781b1b670
+Author: Peter Michael Green <plugwash@debian.org>
+Date:   Tue Jan 4 20:38:09 2022 +0000
+
+    only allow x87-specific result in j1f.rs test on x87
+
+diff --git a/src/math/j1f.rs b/src/math/j1f.rs
+index 225b719..775ff2b 100644
+--- a/src/math/j1f.rs
++++ b/src/math/j1f.rs
+@@ -371,8 +371,7 @@ mod tests {
+     fn test_y1f_2002() {
+         //allow slightly different result on x87
+         let res = y1f(2.0000002_f32);
+-        if res != -0.10703231_f32 {
+-            assert_eq!(res, -0.10703229_f32);
+-        }
++        if cfg!(all(target_arch = "x86", not(target_feature = "sse2"))) && (res == -0.10703231_f32) { return };
++        assert_eq!(res, -0.10703229_f32);
+     }
+ }
diff --git a/src/libm/debian/patches/x87-07-allow-force-eval-to-produce-result.patch b/src/libm/debian/patches/x87-07-allow-force-eval-to-produce-result.patch
new file mode 100644 (file)
index 0000000..0292f2a
--- /dev/null
@@ -0,0 +1,125 @@
+This patch is based on the commit described below, which has
+been submitted as part of https://github.com/rust-lang/libm/pull/249
+adapted for use in the Debian package.
+
+commit 9b6f469d5b3e35f793800da1c58070da2478f76e
+Author: Peter Michael Green <plugwash@debian.org>
+Date:   Tue Jan 4 20:51:40 2022 +0000
+
+    allow force_eval! to produce a result and use that result to more explicitly force rounding on x87.
+
+Index: rust-libm-0.2.1/src/math/fma.rs
+===================================================================
+--- rust-libm-0.2.1.orig/src/math/fma.rs
++++ rust-libm-0.2.1/src/math/fma.rs
+@@ -220,7 +220,8 @@ mod tests {
+         let result = fma(-0.992, -0.992, -0.992);
+         //force rounding to storage format on x87 to prevent superious errors.
+-        #[cfg(all(target_arch = "x86", not(target_feature = "sse2")))]force_eval!(result);
++        #[cfg(all(target_arch = "x86", not(target_feature = "sse2")))]
++        let result = force_eval!(result);
+         assert_eq!(result, -0.00793599999988632,);
+     }
+ }
+Index: rust-libm-0.2.1/src/math/mod.rs
+===================================================================
+--- rust-libm-0.2.1.orig/src/math/mod.rs
++++ rust-libm-0.2.1/src/math/mod.rs
+@@ -1,7 +1,7 @@
+ macro_rules! force_eval {
+     ($e:expr) => {
+         unsafe {
+-            ::core::ptr::read_volatile(&$e);
++            ::core::ptr::read_volatile(&$e)
+         }
+     };
+ }
+Index: rust-libm-0.2.1/src/math/pow.rs
+===================================================================
+--- rust-libm-0.2.1.orig/src/math/pow.rs
++++ rust-libm-0.2.1/src/math/pow.rs
+@@ -484,8 +484,10 @@ mod tests {
+                 let exp = expected(*val);
+                 let res = computed(*val);
+-                #[cfg(all(target_arch = "x86", not(target_feature = "sse2")))]force_eval!(exp);
+-                #[cfg(all(target_arch = "x86", not(target_feature = "sse2")))]force_eval!(res);
++                #[cfg(all(target_arch = "x86", not(target_feature = "sse2")))]
++                let exp = force_eval!(exp);
++                #[cfg(all(target_arch = "x86", not(target_feature = "sse2")))]
++                let res = force_eval!(res);
+                 assert!(
+                     if exp.is_nan() {
+                         res.is_nan()
+Index: rust-libm-0.2.1/src/math/rem_pio2.rs
+===================================================================
+--- rust-libm-0.2.1.orig/src/math/rem_pio2.rs
++++ rust-libm-0.2.1/src/math/rem_pio2.rs
+@@ -53,7 +53,8 @@ pub(crate) fn rem_pio2(x: f64) -> (i32,
+         let tmp = x as f64 * INV_PIO2 + TO_INT;
+         // force rounding of tmp to it's storage format on x87 to avoid
+         // excess precision issues.
+-        #[cfg(all(target_arch = "x86", not(target_feature = "sse2")))]force_eval!(tmp);
++        #[cfg(all(target_arch = "x86", not(target_feature = "sse2")))]
++        let tmp = force_eval!(tmp);
+         let f_n = tmp - TO_INT;
+         let n = f_n as i32;
+         let mut r = x - f_n * PIO2_1;
+@@ -195,25 +196,25 @@ mod tests {
+     #[test]
+     fn test_near_pi() {
+         let arg = 3.141592025756836;
+-        force_eval!(arg);
++        let arg = force_eval!(arg);
+         assert_eq!(
+             rem_pio2(arg),
+             (2, -6.278329573009626e-7, -2.1125998133974653e-23)
+         );
+         let arg = 3.141592033207416;
+-        force_eval!(arg);
++        let arg = force_eval!(arg);
+         assert_eq!(
+             rem_pio2(arg),
+             (2, -6.20382377148128e-7, -2.1125998133974653e-23)
+         );
+         let arg = 3.141592144966125;
+-        force_eval!(arg);
++        let arg = force_eval!(arg);
+         assert_eq!(
+             rem_pio2(arg),
+             (2, -5.086236681942706e-7, -2.1125998133974653e-23)
+         );
+         let arg = 3.141592979431152;
+-        force_eval!(arg);
++        let arg = force_eval!(arg);
+         assert_eq!(
+             rem_pio2(arg),
+             (2, 3.2584135866119817e-7, -2.1125998133974653e-23)
+Index: rust-libm-0.2.1/src/math/rem_pio2f.rs
+===================================================================
+--- rust-libm-0.2.1.orig/src/math/rem_pio2f.rs
++++ rust-libm-0.2.1/src/math/rem_pio2f.rs
+@@ -46,7 +46,8 @@ pub(crate) fn rem_pio2f(x: f32) -> (i32,
+         let tmp = x64 * INV_PIO2 + TOINT;
+         // force rounding of tmp to it's storage format on x87 to avoid
+         // excess precision issues.
+-        #[cfg(all(target_arch = "x86", not(target_feature = "sse2")))]force_eval!(tmp);
++        #[cfg(all(target_arch = "x86", not(target_feature = "sse2")))]
++        let tmp = force_eval!(tmp);
+         let f_n = tmp - TOINT;
+         return (f_n as i32, x64 - f_n * PIO2_1 - f_n * PIO2_1T);
+     }
+Index: rust-libm-0.2.1/src/math/sin.rs
+===================================================================
+--- rust-libm-0.2.1.orig/src/math/sin.rs
++++ rust-libm-0.2.1/src/math/sin.rs
+@@ -82,6 +82,7 @@ fn test_near_pi() {
+     let x = f64::from_bits(0x400921fb000FD5DD); // 3.141592026217707
+     let sx = f64::from_bits(0x3ea50d15ced1a4a2); // 6.273720864039205e-7
+     let result = sin(x);
+-    #[cfg(all(target_arch = "x86", not(target_feature = "sse2")))]force_eval!(result);
++    #[cfg(all(target_arch = "x86", not(target_feature = "sse2")))]
++    let result = force_eval!(result);
+     assert_eq!(result, sx);
+ }
diff --git a/src/libm/debian/patches/x87-08-fix-round-and-roundf.patch b/src/libm/debian/patches/x87-08-fix-round-and-roundf.patch
new file mode 100644 (file)
index 0000000..ff139a0
--- /dev/null
@@ -0,0 +1,39 @@
+This patch contains fixes for round and roundf that are similar
+to those made to other functions in https://github.com/rust-lang/libm/pull/249
+they are not included in the PR because since the latest release
+upstream reimplemented found and roundf in terms of trunc and truncf.
+
+Index: rust-libm-0.2.1.newpatches/src/math/round.rs
+===================================================================
+--- rust-libm-0.2.1.newpatches.orig/src/math/round.rs
++++ rust-libm-0.2.1.newpatches/src/math/round.rs
+@@ -19,7 +19,11 @@ pub fn round(mut x: f64) -> f64 {
+     if i >> 63 != 0 {
+         x = -x;
+     }
+-    y = x + TOINT - TOINT - x;
++    // use force_eval to force rounding to storage format on x87.
++    let tmp = x + TOINT;
++    #[cfg(all(target_arch = "x86", not(target_feature = "sse2")))]
++    let tmp = force_eval!(tmp);
++    y = tmp - TOINT - x;
+     if y > 0.5 {
+         y = y + x - 1.0;
+     } else if y <= -0.5 {
+Index: rust-libm-0.2.1.newpatches/src/math/roundf.rs
+===================================================================
+--- rust-libm-0.2.1.newpatches.orig/src/math/roundf.rs
++++ rust-libm-0.2.1.newpatches/src/math/roundf.rs
+@@ -18,7 +18,11 @@ pub fn roundf(mut x: f32) -> f32 {
+     if i >> 31 != 0 {
+         x = -x;
+     }
+-    y = x + TOINT - TOINT - x;
++    // use force_eval to force rounding to storage format on x87.
++    let tmp = x + TOINT;
++    #[cfg(all(target_arch = "x86", not(target_feature = "sse2")))]
++    let tmp = force_eval!(tmp);
++    y = tmp - TOINT - x;
+     if y > 0.5f32 {
+         y = y + x - 1.0;
+     } else if y <= -0.5f32 {