about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--library/coretests/tests/floats/f128.rs392
-rw-r--r--library/coretests/tests/floats/f16.rs346
-rw-r--r--library/coretests/tests/floats/f32.rs312
-rw-r--r--library/coretests/tests/floats/f64.rs310
-rw-r--r--library/coretests/tests/floats/mod.rs37
5 files changed, 680 insertions, 717 deletions
diff --git a/library/coretests/tests/floats/f128.rs b/library/coretests/tests/floats/f128.rs
index 12cf651f03f..01770f119df 100644
--- a/library/coretests/tests/floats/f128.rs
+++ b/library/coretests/tests/floats/f128.rs
@@ -1,12 +1,9 @@
 // FIXME(f16_f128): only tested on platforms that have symbols and aren't buggy
 #![cfg(target_has_reliable_f128)]
 
+use core::ops::{Add, Div, Mul, Sub};
 use std::f128::consts;
 use std::num::FpCategory as Fp;
-#[cfg(not(miri))]
-#[cfg(target_has_reliable_f128_math)]
-use std::ops::Rem;
-use std::ops::{Add, Div, Mul, Sub};
 
 // Note these tolerances make sense around zero, but not for more extreme exponents.
 
@@ -39,68 +36,46 @@ const NAN_MASK1: u128 = 0x0000aaaaaaaaaaaaaaaaaaaaaaaaaaaa;
 /// Second pattern over the mantissa
 const NAN_MASK2: u128 = 0x00005555555555555555555555555555;
 
-/// Compare by representation
-#[allow(unused_macros)]
-macro_rules! assert_f128_biteq {
-    ($a:expr, $b:expr) => {
-        let (l, r): (&f128, &f128) = (&$a, &$b);
-        let lb = l.to_bits();
-        let rb = r.to_bits();
-        assert_eq!(lb, rb, "float {l:?} is not bitequal to {r:?}.\na: {lb:#034x}\nb: {rb:#034x}");
-    };
-}
-
 #[test]
 fn test_num_f128() {
     // FIXME(f16_f128): replace with a `test_num` call once the required `fmodl`/`fmodf128`
     // function is available on all platforms.
     let ten = 10f128;
     let two = 2f128;
-    assert_eq!(ten.add(two), ten + two);
-    assert_eq!(ten.sub(two), ten - two);
-    assert_eq!(ten.mul(two), ten * two);
-    assert_eq!(ten.div(two), ten / two);
+    assert_biteq!(ten.add(two), ten + two);
+    assert_biteq!(ten.sub(two), ten - two);
+    assert_biteq!(ten.mul(two), ten * two);
+    assert_biteq!(ten.div(two), ten / two);
+    #[cfg(any(miri, target_has_reliable_f128_math))]
+    assert_biteq!(core::ops::Rem::rem(ten, two), ten % two);
 }
 
 // FIXME(f16_f128,miri): many of these have to be disabled since miri does not yet support
 // the intrinsics.
 
 #[test]
-#[cfg(not(miri))]
-#[cfg(target_has_reliable_f128_math)]
-fn test_num_f128_rem() {
-    let ten = 10f128;
-    let two = 2f128;
-    assert_eq!(ten.rem(two), ten % two);
-}
-
-#[test]
-#[cfg(not(miri))]
-#[cfg(target_has_reliable_f128_math)]
+#[cfg(any(miri, target_has_reliable_f128_math))]
 fn test_min_nan() {
-    assert_eq!(f128::NAN.min(2.0), 2.0);
-    assert_eq!(2.0f128.min(f128::NAN), 2.0);
+    assert_biteq!(f128::NAN.min(2.0), 2.0);
+    assert_biteq!(2.0f128.min(f128::NAN), 2.0);
 }
 
 #[test]
-#[cfg(not(miri))]
-#[cfg(target_has_reliable_f128_math)]
+#[cfg(any(miri, target_has_reliable_f128_math))]
 fn test_max_nan() {
-    assert_eq!(f128::NAN.max(2.0), 2.0);
-    assert_eq!(2.0f128.max(f128::NAN), 2.0);
+    assert_biteq!(f128::NAN.max(2.0), 2.0);
+    assert_biteq!(2.0f128.max(f128::NAN), 2.0);
 }
 
 #[test]
-#[cfg(not(miri))]
-#[cfg(target_has_reliable_f128_math)]
+#[cfg(any(miri, target_has_reliable_f128_math))]
 fn test_minimum() {
     assert!(f128::NAN.minimum(2.0).is_nan());
     assert!(2.0f128.minimum(f128::NAN).is_nan());
 }
 
 #[test]
-#[cfg(not(miri))]
-#[cfg(target_has_reliable_f128_math)]
+#[cfg(any(miri, target_has_reliable_f128_math))]
 fn test_maximum() {
     assert!(f128::NAN.maximum(2.0).is_nan());
     assert!(2.0f128.maximum(f128::NAN).is_nan());
@@ -147,7 +122,7 @@ fn test_neg_infinity() {
 #[test]
 fn test_zero() {
     let zero: f128 = 0.0f128;
-    assert_eq!(0.0, zero);
+    assert_biteq!(0.0, zero);
     assert!(!zero.is_infinite());
     assert!(zero.is_finite());
     assert!(zero.is_sign_positive());
@@ -161,6 +136,7 @@ fn test_zero() {
 fn test_neg_zero() {
     let neg_zero: f128 = -0.0;
     assert_eq!(0.0, neg_zero);
+    assert_biteq!(-0.0, neg_zero);
     assert!(!neg_zero.is_infinite());
     assert!(neg_zero.is_finite());
     assert!(!neg_zero.is_sign_positive());
@@ -173,7 +149,7 @@ fn test_neg_zero() {
 #[test]
 fn test_one() {
     let one: f128 = 1.0f128;
-    assert_eq!(1.0, one);
+    assert_biteq!(1.0, one);
     assert!(!one.is_infinite());
     assert!(one.is_finite());
     assert!(one.is_sign_positive());
@@ -257,114 +233,107 @@ fn test_classify() {
 }
 
 #[test]
-#[cfg(not(miri))]
 #[cfg(target_has_reliable_f128_math)]
 fn test_floor() {
-    assert_approx_eq!(1.0f128.floor(), 1.0f128, TOL_PRECISE);
-    assert_approx_eq!(1.3f128.floor(), 1.0f128, TOL_PRECISE);
-    assert_approx_eq!(1.5f128.floor(), 1.0f128, TOL_PRECISE);
-    assert_approx_eq!(1.7f128.floor(), 1.0f128, TOL_PRECISE);
-    assert_approx_eq!(0.0f128.floor(), 0.0f128, TOL_PRECISE);
-    assert_approx_eq!((-0.0f128).floor(), -0.0f128, TOL_PRECISE);
-    assert_approx_eq!((-1.0f128).floor(), -1.0f128, TOL_PRECISE);
-    assert_approx_eq!((-1.3f128).floor(), -2.0f128, TOL_PRECISE);
-    assert_approx_eq!((-1.5f128).floor(), -2.0f128, TOL_PRECISE);
-    assert_approx_eq!((-1.7f128).floor(), -2.0f128, TOL_PRECISE);
+    assert_biteq!(1.0f128.floor(), 1.0f128);
+    assert_biteq!(1.3f128.floor(), 1.0f128);
+    assert_biteq!(1.5f128.floor(), 1.0f128);
+    assert_biteq!(1.7f128.floor(), 1.0f128);
+    assert_biteq!(0.0f128.floor(), 0.0f128);
+    assert_biteq!((-0.0f128).floor(), -0.0f128);
+    assert_biteq!((-1.0f128).floor(), -1.0f128);
+    assert_biteq!((-1.3f128).floor(), -2.0f128);
+    assert_biteq!((-1.5f128).floor(), -2.0f128);
+    assert_biteq!((-1.7f128).floor(), -2.0f128);
 }
 
 #[test]
-#[cfg(not(miri))]
-#[cfg(target_has_reliable_f128_math)]
+#[cfg(any(miri, target_has_reliable_f128_math))]
 fn test_ceil() {
-    assert_approx_eq!(1.0f128.ceil(), 1.0f128, TOL_PRECISE);
-    assert_approx_eq!(1.3f128.ceil(), 2.0f128, TOL_PRECISE);
-    assert_approx_eq!(1.5f128.ceil(), 2.0f128, TOL_PRECISE);
-    assert_approx_eq!(1.7f128.ceil(), 2.0f128, TOL_PRECISE);
-    assert_approx_eq!(0.0f128.ceil(), 0.0f128, TOL_PRECISE);
-    assert_approx_eq!((-0.0f128).ceil(), -0.0f128, TOL_PRECISE);
-    assert_approx_eq!((-1.0f128).ceil(), -1.0f128, TOL_PRECISE);
-    assert_approx_eq!((-1.3f128).ceil(), -1.0f128, TOL_PRECISE);
-    assert_approx_eq!((-1.5f128).ceil(), -1.0f128, TOL_PRECISE);
-    assert_approx_eq!((-1.7f128).ceil(), -1.0f128, TOL_PRECISE);
+    assert_biteq!(1.0f128.ceil(), 1.0f128);
+    assert_biteq!(1.3f128.ceil(), 2.0f128);
+    assert_biteq!(1.5f128.ceil(), 2.0f128);
+    assert_biteq!(1.7f128.ceil(), 2.0f128);
+    assert_biteq!(0.0f128.ceil(), 0.0f128);
+    assert_biteq!((-0.0f128).ceil(), -0.0f128);
+    assert_biteq!((-1.0f128).ceil(), -1.0f128);
+    assert_biteq!((-1.3f128).ceil(), -1.0f128);
+    assert_biteq!((-1.5f128).ceil(), -1.0f128);
+    assert_biteq!((-1.7f128).ceil(), -1.0f128);
 }
 
 #[test]
-#[cfg(not(miri))]
-#[cfg(target_has_reliable_f128_math)]
+#[cfg(any(miri, target_has_reliable_f128_math))]
 fn test_round() {
-    assert_approx_eq!(2.5f128.round(), 3.0f128, TOL_PRECISE);
-    assert_approx_eq!(1.0f128.round(), 1.0f128, TOL_PRECISE);
-    assert_approx_eq!(1.3f128.round(), 1.0f128, TOL_PRECISE);
-    assert_approx_eq!(1.5f128.round(), 2.0f128, TOL_PRECISE);
-    assert_approx_eq!(1.7f128.round(), 2.0f128, TOL_PRECISE);
-    assert_approx_eq!(0.0f128.round(), 0.0f128, TOL_PRECISE);
-    assert_approx_eq!((-0.0f128).round(), -0.0f128, TOL_PRECISE);
-    assert_approx_eq!((-1.0f128).round(), -1.0f128, TOL_PRECISE);
-    assert_approx_eq!((-1.3f128).round(), -1.0f128, TOL_PRECISE);
-    assert_approx_eq!((-1.5f128).round(), -2.0f128, TOL_PRECISE);
-    assert_approx_eq!((-1.7f128).round(), -2.0f128, TOL_PRECISE);
+    assert_biteq!(2.5f128.round(), 3.0f128);
+    assert_biteq!(1.0f128.round(), 1.0f128);
+    assert_biteq!(1.3f128.round(), 1.0f128);
+    assert_biteq!(1.5f128.round(), 2.0f128);
+    assert_biteq!(1.7f128.round(), 2.0f128);
+    assert_biteq!(0.0f128.round(), 0.0f128);
+    assert_biteq!((-0.0f128).round(), -0.0f128);
+    assert_biteq!((-1.0f128).round(), -1.0f128);
+    assert_biteq!((-1.3f128).round(), -1.0f128);
+    assert_biteq!((-1.5f128).round(), -2.0f128);
+    assert_biteq!((-1.7f128).round(), -2.0f128);
 }
 
 #[test]
-#[cfg(not(miri))]
-#[cfg(target_has_reliable_f128_math)]
+#[cfg(any(miri, target_has_reliable_f128_math))]
 fn test_round_ties_even() {
-    assert_approx_eq!(2.5f128.round_ties_even(), 2.0f128, TOL_PRECISE);
-    assert_approx_eq!(1.0f128.round_ties_even(), 1.0f128, TOL_PRECISE);
-    assert_approx_eq!(1.3f128.round_ties_even(), 1.0f128, TOL_PRECISE);
-    assert_approx_eq!(1.5f128.round_ties_even(), 2.0f128, TOL_PRECISE);
-    assert_approx_eq!(1.7f128.round_ties_even(), 2.0f128, TOL_PRECISE);
-    assert_approx_eq!(0.0f128.round_ties_even(), 0.0f128, TOL_PRECISE);
-    assert_approx_eq!((-0.0f128).round_ties_even(), -0.0f128, TOL_PRECISE);
-    assert_approx_eq!((-1.0f128).round_ties_even(), -1.0f128, TOL_PRECISE);
-    assert_approx_eq!((-1.3f128).round_ties_even(), -1.0f128, TOL_PRECISE);
-    assert_approx_eq!((-1.5f128).round_ties_even(), -2.0f128, TOL_PRECISE);
-    assert_approx_eq!((-1.7f128).round_ties_even(), -2.0f128, TOL_PRECISE);
+    assert_biteq!(2.5f128.round_ties_even(), 2.0f128);
+    assert_biteq!(1.0f128.round_ties_even(), 1.0f128);
+    assert_biteq!(1.3f128.round_ties_even(), 1.0f128);
+    assert_biteq!(1.5f128.round_ties_even(), 2.0f128);
+    assert_biteq!(1.7f128.round_ties_even(), 2.0f128);
+    assert_biteq!(0.0f128.round_ties_even(), 0.0f128);
+    assert_biteq!((-0.0f128).round_ties_even(), -0.0f128);
+    assert_biteq!((-1.0f128).round_ties_even(), -1.0f128);
+    assert_biteq!((-1.3f128).round_ties_even(), -1.0f128);
+    assert_biteq!((-1.5f128).round_ties_even(), -2.0f128);
+    assert_biteq!((-1.7f128).round_ties_even(), -2.0f128);
 }
 
 #[test]
-#[cfg(not(miri))]
-#[cfg(target_has_reliable_f128_math)]
+#[cfg(any(miri, target_has_reliable_f128_math))]
 fn test_trunc() {
-    assert_approx_eq!(1.0f128.trunc(), 1.0f128, TOL_PRECISE);
-    assert_approx_eq!(1.3f128.trunc(), 1.0f128, TOL_PRECISE);
-    assert_approx_eq!(1.5f128.trunc(), 1.0f128, TOL_PRECISE);
-    assert_approx_eq!(1.7f128.trunc(), 1.0f128, TOL_PRECISE);
-    assert_approx_eq!(0.0f128.trunc(), 0.0f128, TOL_PRECISE);
-    assert_approx_eq!((-0.0f128).trunc(), -0.0f128, TOL_PRECISE);
-    assert_approx_eq!((-1.0f128).trunc(), -1.0f128, TOL_PRECISE);
-    assert_approx_eq!((-1.3f128).trunc(), -1.0f128, TOL_PRECISE);
-    assert_approx_eq!((-1.5f128).trunc(), -1.0f128, TOL_PRECISE);
-    assert_approx_eq!((-1.7f128).trunc(), -1.0f128, TOL_PRECISE);
+    assert_biteq!(1.0f128.trunc(), 1.0f128);
+    assert_biteq!(1.3f128.trunc(), 1.0f128);
+    assert_biteq!(1.5f128.trunc(), 1.0f128);
+    assert_biteq!(1.7f128.trunc(), 1.0f128);
+    assert_biteq!(0.0f128.trunc(), 0.0f128);
+    assert_biteq!((-0.0f128).trunc(), -0.0f128);
+    assert_biteq!((-1.0f128).trunc(), -1.0f128);
+    assert_biteq!((-1.3f128).trunc(), -1.0f128);
+    assert_biteq!((-1.5f128).trunc(), -1.0f128);
+    assert_biteq!((-1.7f128).trunc(), -1.0f128);
 }
 
 #[test]
-#[cfg(not(miri))]
-#[cfg(target_has_reliable_f128_math)]
+#[cfg(any(miri, target_has_reliable_f128_math))]
 fn test_fract() {
-    assert_approx_eq!(1.0f128.fract(), 0.0f128, TOL_PRECISE);
-    assert_approx_eq!(1.3f128.fract(), 0.3f128, TOL_PRECISE);
-    assert_approx_eq!(1.5f128.fract(), 0.5f128, TOL_PRECISE);
-    assert_approx_eq!(1.7f128.fract(), 0.7f128, TOL_PRECISE);
-    assert_approx_eq!(0.0f128.fract(), 0.0f128, TOL_PRECISE);
-    assert_approx_eq!((-0.0f128).fract(), -0.0f128, TOL_PRECISE);
-    assert_approx_eq!((-1.0f128).fract(), -0.0f128, TOL_PRECISE);
-    assert_approx_eq!((-1.3f128).fract(), -0.3f128, TOL_PRECISE);
-    assert_approx_eq!((-1.5f128).fract(), -0.5f128, TOL_PRECISE);
-    assert_approx_eq!((-1.7f128).fract(), -0.7f128, TOL_PRECISE);
+    assert_biteq!(1.0f128.fract(), 0.0f128);
+    assert_biteq!(1.3f128.fract(), 0.300000000000000000000000000000000039f128);
+    assert_biteq!(1.5f128.fract(), 0.5f128);
+    assert_biteq!(1.7f128.fract(), 0.7f128);
+    assert_biteq!(0.0f128.fract(), 0.0f128);
+    assert_biteq!((-0.0f128).fract(), 0.0f128);
+    assert_biteq!((-1.0f128).fract(), 0.0f128);
+    assert_biteq!((-1.3f128).fract(), -0.300000000000000000000000000000000039f128);
+    assert_biteq!((-1.5f128).fract(), -0.5f128);
+    assert_biteq!((-1.7f128).fract(), -0.699999999999999999999999999999999961f128);
 }
 
 #[test]
-#[cfg(not(miri))]
-#[cfg(target_has_reliable_f128_math)]
+#[cfg(any(miri, target_has_reliable_f128_math))]
 fn test_abs() {
-    assert_eq!(f128::INFINITY.abs(), f128::INFINITY);
-    assert_eq!(1f128.abs(), 1f128);
-    assert_eq!(0f128.abs(), 0f128);
-    assert_eq!((-0f128).abs(), 0f128);
-    assert_eq!((-1f128).abs(), 1f128);
-    assert_eq!(f128::NEG_INFINITY.abs(), f128::INFINITY);
-    assert_eq!((1f128 / f128::NEG_INFINITY).abs(), 0f128);
+    assert_biteq!(f128::INFINITY.abs(), f128::INFINITY);
+    assert_biteq!(1f128.abs(), 1f128);
+    assert_biteq!(0f128.abs(), 0f128);
+    assert_biteq!((-0f128).abs(), 0f128);
+    assert_biteq!((-1f128).abs(), 1f128);
+    assert_biteq!(f128::NEG_INFINITY.abs(), f128::INFINITY);
+    assert_biteq!((1f128 / f128::NEG_INFINITY).abs(), 0f128);
     assert!(f128::NAN.abs().is_nan());
 }
 
@@ -401,27 +370,27 @@ fn test_next_up() {
     let max_down = f128::from_bits(MAX_DOWN_BITS);
     let largest_subnormal = f128::from_bits(LARGEST_SUBNORMAL_BITS);
     let smallest_normal = f128::from_bits(SMALLEST_NORMAL_BITS);
-    assert_f128_biteq!(f128::NEG_INFINITY.next_up(), f128::MIN);
-    assert_f128_biteq!(f128::MIN.next_up(), -max_down);
-    assert_f128_biteq!((-1.0 - f128::EPSILON).next_up(), -1.0);
-    assert_f128_biteq!((-smallest_normal).next_up(), -largest_subnormal);
-    assert_f128_biteq!((-tiny_up).next_up(), -tiny);
-    assert_f128_biteq!((-tiny).next_up(), -0.0f128);
-    assert_f128_biteq!((-0.0f128).next_up(), tiny);
-    assert_f128_biteq!(0.0f128.next_up(), tiny);
-    assert_f128_biteq!(tiny.next_up(), tiny_up);
-    assert_f128_biteq!(largest_subnormal.next_up(), smallest_normal);
-    assert_f128_biteq!(1.0f128.next_up(), 1.0 + f128::EPSILON);
-    assert_f128_biteq!(f128::MAX.next_up(), f128::INFINITY);
-    assert_f128_biteq!(f128::INFINITY.next_up(), f128::INFINITY);
+    assert_biteq!(f128::NEG_INFINITY.next_up(), f128::MIN);
+    assert_biteq!(f128::MIN.next_up(), -max_down);
+    assert_biteq!((-1.0 - f128::EPSILON).next_up(), -1.0f128);
+    assert_biteq!((-smallest_normal).next_up(), -largest_subnormal);
+    assert_biteq!((-tiny_up).next_up(), -tiny);
+    assert_biteq!((-tiny).next_up(), -0.0f128);
+    assert_biteq!((-0.0f128).next_up(), tiny);
+    assert_biteq!(0.0f128.next_up(), tiny);
+    assert_biteq!(tiny.next_up(), tiny_up);
+    assert_biteq!(largest_subnormal.next_up(), smallest_normal);
+    assert_biteq!(1.0f128.next_up(), 1.0 + f128::EPSILON);
+    assert_biteq!(f128::MAX.next_up(), f128::INFINITY);
+    assert_biteq!(f128::INFINITY.next_up(), f128::INFINITY);
 
     // Check that NaNs roundtrip.
     let nan0 = f128::NAN;
     let nan1 = f128::from_bits(f128::NAN.to_bits() ^ 0x002a_aaaa);
     let nan2 = f128::from_bits(f128::NAN.to_bits() ^ 0x0055_5555);
-    assert_f128_biteq!(nan0.next_up(), nan0);
-    assert_f128_biteq!(nan1.next_up(), nan1);
-    assert_f128_biteq!(nan2.next_up(), nan2);
+    assert_biteq!(nan0.next_up(), nan0);
+    assert_biteq!(nan1.next_up(), nan1);
+    assert_biteq!(nan2.next_up(), nan2);
 }
 
 #[test]
@@ -431,28 +400,28 @@ fn test_next_down() {
     let max_down = f128::from_bits(MAX_DOWN_BITS);
     let largest_subnormal = f128::from_bits(LARGEST_SUBNORMAL_BITS);
     let smallest_normal = f128::from_bits(SMALLEST_NORMAL_BITS);
-    assert_f128_biteq!(f128::NEG_INFINITY.next_down(), f128::NEG_INFINITY);
-    assert_f128_biteq!(f128::MIN.next_down(), f128::NEG_INFINITY);
-    assert_f128_biteq!((-max_down).next_down(), f128::MIN);
-    assert_f128_biteq!((-1.0f128).next_down(), -1.0 - f128::EPSILON);
-    assert_f128_biteq!((-largest_subnormal).next_down(), -smallest_normal);
-    assert_f128_biteq!((-tiny).next_down(), -tiny_up);
-    assert_f128_biteq!((-0.0f128).next_down(), -tiny);
-    assert_f128_biteq!((0.0f128).next_down(), -tiny);
-    assert_f128_biteq!(tiny.next_down(), 0.0f128);
-    assert_f128_biteq!(tiny_up.next_down(), tiny);
-    assert_f128_biteq!(smallest_normal.next_down(), largest_subnormal);
-    assert_f128_biteq!((1.0 + f128::EPSILON).next_down(), 1.0f128);
-    assert_f128_biteq!(f128::MAX.next_down(), max_down);
-    assert_f128_biteq!(f128::INFINITY.next_down(), f128::MAX);
+    assert_biteq!(f128::NEG_INFINITY.next_down(), f128::NEG_INFINITY);
+    assert_biteq!(f128::MIN.next_down(), f128::NEG_INFINITY);
+    assert_biteq!((-max_down).next_down(), f128::MIN);
+    assert_biteq!((-1.0f128).next_down(), -1.0 - f128::EPSILON);
+    assert_biteq!((-largest_subnormal).next_down(), -smallest_normal);
+    assert_biteq!((-tiny).next_down(), -tiny_up);
+    assert_biteq!((-0.0f128).next_down(), -tiny);
+    assert_biteq!((0.0f128).next_down(), -tiny);
+    assert_biteq!(tiny.next_down(), 0.0f128);
+    assert_biteq!(tiny_up.next_down(), tiny);
+    assert_biteq!(smallest_normal.next_down(), largest_subnormal);
+    assert_biteq!((1.0 + f128::EPSILON).next_down(), 1.0f128);
+    assert_biteq!(f128::MAX.next_down(), max_down);
+    assert_biteq!(f128::INFINITY.next_down(), f128::MAX);
 
     // Check that NaNs roundtrip.
     let nan0 = f128::NAN;
     let nan1 = f128::from_bits(f128::NAN.to_bits() ^ 0x002a_aaaa);
     let nan2 = f128::from_bits(f128::NAN.to_bits() ^ 0x0055_5555);
-    assert_f128_biteq!(nan0.next_down(), nan0);
-    assert_f128_biteq!(nan1.next_down(), nan1);
-    assert_f128_biteq!(nan2.next_down(), nan2);
+    assert_biteq!(nan0.next_down(), nan0);
+    assert_biteq!(nan1.next_down(), nan1);
+    assert_biteq!(nan2.next_down(), nan2);
 }
 
 #[test]
@@ -462,36 +431,35 @@ fn test_mul_add() {
     let nan: f128 = f128::NAN;
     let inf: f128 = f128::INFINITY;
     let neg_inf: f128 = f128::NEG_INFINITY;
-    assert_approx_eq!(12.3f128.mul_add(4.5, 6.7), 62.05, TOL_PRECISE);
-    assert_approx_eq!((-12.3f128).mul_add(-4.5, -6.7), 48.65, TOL_PRECISE);
-    assert_approx_eq!(0.0f128.mul_add(8.9, 1.2), 1.2, TOL_PRECISE);
-    assert_approx_eq!(3.4f128.mul_add(-0.0, 5.6), 5.6, TOL_PRECISE);
+    assert_biteq!(12.3f128.mul_add(4.5, 6.7), 62.0500000000000000000000000000000037);
+    assert_biteq!((-12.3f128).mul_add(-4.5, -6.7), 48.6500000000000000000000000000000049);
+    assert_biteq!(0.0f128.mul_add(8.9, 1.2), 1.2);
+    assert_biteq!(3.4f128.mul_add(-0.0, 5.6), 5.6);
     assert!(nan.mul_add(7.8, 9.0).is_nan());
-    assert_eq!(inf.mul_add(7.8, 9.0), inf);
-    assert_eq!(neg_inf.mul_add(7.8, 9.0), neg_inf);
-    assert_eq!(8.9f128.mul_add(inf, 3.2), inf);
-    assert_eq!((-3.2f128).mul_add(2.4, neg_inf), neg_inf);
+    assert_biteq!(inf.mul_add(7.8, 9.0), inf);
+    assert_biteq!(neg_inf.mul_add(7.8, 9.0), neg_inf);
+    assert_biteq!(8.9f128.mul_add(inf, 3.2), inf);
+    assert_biteq!((-3.2f128).mul_add(2.4, neg_inf), neg_inf);
 }
 
 #[test]
-#[cfg(not(miri))]
-#[cfg(target_has_reliable_f128_math)]
+#[cfg(any(miri, target_has_reliable_f128_math))]
 fn test_recip() {
     let nan: f128 = f128::NAN;
     let inf: f128 = f128::INFINITY;
     let neg_inf: f128 = f128::NEG_INFINITY;
-    assert_eq!(1.0f128.recip(), 1.0);
-    assert_eq!(2.0f128.recip(), 0.5);
-    assert_eq!((-0.4f128).recip(), -2.5);
-    assert_eq!(0.0f128.recip(), inf);
+    assert_biteq!(1.0f128.recip(), 1.0);
+    assert_biteq!(2.0f128.recip(), 0.5);
+    assert_biteq!((-0.4f128).recip(), -2.5);
+    assert_biteq!(0.0f128.recip(), inf);
     assert_approx_eq!(
         f128::MAX.recip(),
         8.40525785778023376565669454330438228902076605e-4933,
         1e-4900
     );
     assert!(nan.recip().is_nan());
-    assert_eq!(inf.recip(), 0.0);
-    assert_eq!(neg_inf.recip(), 0.0);
+    assert_biteq!(inf.recip(), 0.0);
+    assert_biteq!(neg_inf.recip(), -0.0);
 }
 
 #[test]
@@ -501,13 +469,13 @@ fn test_powi() {
     let nan: f128 = f128::NAN;
     let inf: f128 = f128::INFINITY;
     let neg_inf: f128 = f128::NEG_INFINITY;
-    assert_eq!(1.0f128.powi(1), 1.0);
+    assert_biteq!(1.0f128.powi(1), 1.0);
     assert_approx_eq!((-3.1f128).powi(2), 9.6100000000000005506706202140776519387, TOL);
     assert_approx_eq!(5.9f128.powi(-2), 0.028727377190462507313100483690639638451, TOL);
-    assert_eq!(8.3f128.powi(0), 1.0);
+    assert_biteq!(8.3f128.powi(0), 1.0);
     assert!(nan.powi(2).is_nan());
-    assert_eq!(inf.powi(3), inf);
-    assert_eq!(neg_inf.powi(2), inf);
+    assert_biteq!(inf.powi(3), inf);
+    assert_biteq!(neg_inf.powi(2), inf);
 }
 
 #[test]
@@ -517,10 +485,10 @@ fn test_sqrt_domain() {
     assert!(f128::NAN.sqrt().is_nan());
     assert!(f128::NEG_INFINITY.sqrt().is_nan());
     assert!((-1.0f128).sqrt().is_nan());
-    assert_eq!((-0.0f128).sqrt(), -0.0);
-    assert_eq!(0.0f128.sqrt(), 0.0);
-    assert_eq!(1.0f128.sqrt(), 1.0);
-    assert_eq!(f128::INFINITY.sqrt(), f128::INFINITY);
+    assert_biteq!((-0.0f128).sqrt(), -0.0);
+    assert_biteq!(0.0f128.sqrt(), 0.0);
+    assert_biteq!(1.0f128.sqrt(), 1.0);
+    assert_biteq!(f128::INFINITY.sqrt(), f128::INFINITY);
 }
 
 #[test]
@@ -529,13 +497,13 @@ fn test_to_degrees() {
     let nan: f128 = f128::NAN;
     let inf: f128 = f128::INFINITY;
     let neg_inf: f128 = f128::NEG_INFINITY;
-    assert_eq!(0.0f128.to_degrees(), 0.0);
+    assert_biteq!(0.0f128.to_degrees(), 0.0);
     assert_approx_eq!((-5.8f128).to_degrees(), -332.31552117587745090765431723855668471, TOL);
     assert_approx_eq!(pi.to_degrees(), 180.0, TOL);
     assert!(nan.to_degrees().is_nan());
-    assert_eq!(inf.to_degrees(), inf);
-    assert_eq!(neg_inf.to_degrees(), neg_inf);
-    assert_eq!(1_f128.to_degrees(), 57.2957795130823208767981548141051703);
+    assert_biteq!(inf.to_degrees(), inf);
+    assert_biteq!(neg_inf.to_degrees(), neg_inf);
+    assert_biteq!(1_f128.to_degrees(), 57.2957795130823208767981548141051703);
 }
 
 #[test]
@@ -544,15 +512,15 @@ fn test_to_radians() {
     let nan: f128 = f128::NAN;
     let inf: f128 = f128::INFINITY;
     let neg_inf: f128 = f128::NEG_INFINITY;
-    assert_eq!(0.0f128.to_radians(), 0.0);
+    assert_biteq!(0.0f128.to_radians(), 0.0);
     assert_approx_eq!(154.6f128.to_radians(), 2.6982790235832334267135442069489767804, TOL);
     assert_approx_eq!((-332.31f128).to_radians(), -5.7999036373023566567593094812182763013, TOL);
     // check approx rather than exact because round trip for pi doesn't fall on an exactly
     // representable value (unlike `f32` and `f64`).
     assert_approx_eq!(180.0f128.to_radians(), pi, TOL_PRECISE);
     assert!(nan.to_radians().is_nan());
-    assert_eq!(inf.to_radians(), inf);
-    assert_eq!(neg_inf.to_radians(), neg_inf);
+    assert_biteq!(inf.to_radians(), inf);
+    assert_biteq!(neg_inf.to_radians(), neg_inf);
 }
 
 #[test]
@@ -561,10 +529,10 @@ fn test_float_bits_conv() {
     assert_eq!((12.5f128).to_bits(), 0x40029000000000000000000000000000);
     assert_eq!((1337f128).to_bits(), 0x40094e40000000000000000000000000);
     assert_eq!((-14.25f128).to_bits(), 0xc002c800000000000000000000000000);
-    assert_approx_eq!(f128::from_bits(0x3fff0000000000000000000000000000), 1.0, TOL_PRECISE);
-    assert_approx_eq!(f128::from_bits(0x40029000000000000000000000000000), 12.5, TOL_PRECISE);
-    assert_approx_eq!(f128::from_bits(0x40094e40000000000000000000000000), 1337.0, TOL_PRECISE);
-    assert_approx_eq!(f128::from_bits(0xc002c800000000000000000000000000), -14.25, TOL_PRECISE);
+    assert_biteq!(f128::from_bits(0x3fff0000000000000000000000000000), 1.0);
+    assert_biteq!(f128::from_bits(0x40029000000000000000000000000000), 12.5);
+    assert_biteq!(f128::from_bits(0x40094e40000000000000000000000000), 1337.0);
+    assert_biteq!(f128::from_bits(0xc002c800000000000000000000000000), -14.25);
 
     // Check that NaNs roundtrip their bits regardless of signaling-ness
     // 0xA is 0b1010; 0x5 is 0b0101 -- so these two together clobbers all the mantissa bits
@@ -760,26 +728,26 @@ fn test_algebraic() {
 
 #[test]
 fn test_from() {
-    assert_eq!(f128::from(false), 0.0);
-    assert_eq!(f128::from(true), 1.0);
-    assert_eq!(f128::from(u8::MIN), 0.0);
-    assert_eq!(f128::from(42_u8), 42.0);
-    assert_eq!(f128::from(u8::MAX), 255.0);
-    assert_eq!(f128::from(i8::MIN), -128.0);
-    assert_eq!(f128::from(42_i8), 42.0);
-    assert_eq!(f128::from(i8::MAX), 127.0);
-    assert_eq!(f128::from(u16::MIN), 0.0);
-    assert_eq!(f128::from(42_u16), 42.0);
-    assert_eq!(f128::from(u16::MAX), 65535.0);
-    assert_eq!(f128::from(i16::MIN), -32768.0);
-    assert_eq!(f128::from(42_i16), 42.0);
-    assert_eq!(f128::from(i16::MAX), 32767.0);
-    assert_eq!(f128::from(u32::MIN), 0.0);
-    assert_eq!(f128::from(42_u32), 42.0);
-    assert_eq!(f128::from(u32::MAX), 4294967295.0);
-    assert_eq!(f128::from(i32::MIN), -2147483648.0);
-    assert_eq!(f128::from(42_i32), 42.0);
-    assert_eq!(f128::from(i32::MAX), 2147483647.0);
+    assert_biteq!(f128::from(false), 0.0);
+    assert_biteq!(f128::from(true), 1.0);
+    assert_biteq!(f128::from(u8::MIN), 0.0);
+    assert_biteq!(f128::from(42_u8), 42.0);
+    assert_biteq!(f128::from(u8::MAX), 255.0);
+    assert_biteq!(f128::from(i8::MIN), -128.0);
+    assert_biteq!(f128::from(42_i8), 42.0);
+    assert_biteq!(f128::from(i8::MAX), 127.0);
+    assert_biteq!(f128::from(u16::MIN), 0.0);
+    assert_biteq!(f128::from(42_u16), 42.0);
+    assert_biteq!(f128::from(u16::MAX), 65535.0);
+    assert_biteq!(f128::from(i16::MIN), -32768.0);
+    assert_biteq!(f128::from(42_i16), 42.0);
+    assert_biteq!(f128::from(i16::MAX), 32767.0);
+    assert_biteq!(f128::from(u32::MIN), 0.0);
+    assert_biteq!(f128::from(42_u32), 42.0);
+    assert_biteq!(f128::from(u32::MAX), 4294967295.0);
+    assert_biteq!(f128::from(i32::MIN), -2147483648.0);
+    assert_biteq!(f128::from(42_i32), 42.0);
+    assert_biteq!(f128::from(i32::MAX), 2147483647.0);
     // FIXME(f16_f128): Uncomment these tests once the From<{u64,i64}> impls are added.
     // assert_eq!(f128::from(u64::MIN), 0.0);
     // assert_eq!(f128::from(42_u64), 42.0);
diff --git a/library/coretests/tests/floats/f16.rs b/library/coretests/tests/floats/f16.rs
index 9246805a728..4797573f7d0 100644
--- a/library/coretests/tests/floats/f16.rs
+++ b/library/coretests/tests/floats/f16.rs
@@ -41,17 +41,6 @@ const NAN_MASK1: u16 = 0x02aa;
 /// Second pattern over the mantissa
 const NAN_MASK2: u16 = 0x0155;
 
-/// Compare by representation
-#[allow(unused_macros)]
-macro_rules! assert_f16_biteq {
-    ($a:expr, $b:expr) => {
-        let (l, r): (&f16, &f16) = (&$a, &$b);
-        let lb = l.to_bits();
-        let rb = r.to_bits();
-        assert_eq!(lb, rb, "float {l:?} ({lb:#04x}) is not bitequal to {r:?} ({rb:#04x})");
-    };
-}
-
 #[test]
 fn test_num_f16() {
     super::test_num(10f16, 2f16);
@@ -61,32 +50,28 @@ fn test_num_f16() {
 // the intrinsics.
 
 #[test]
-#[cfg(not(miri))]
-#[cfg(target_has_reliable_f16_math)]
+#[cfg(any(miri, target_has_reliable_f16_math))]
 fn test_min_nan() {
-    assert_eq!(f16::NAN.min(2.0), 2.0);
-    assert_eq!(2.0f16.min(f16::NAN), 2.0);
+    assert_biteq!(f16::NAN.min(2.0), 2.0);
+    assert_biteq!(2.0f16.min(f16::NAN), 2.0);
 }
 
 #[test]
-#[cfg(not(miri))]
-#[cfg(target_has_reliable_f16_math)]
+#[cfg(any(miri, target_has_reliable_f16_math))]
 fn test_max_nan() {
-    assert_eq!(f16::NAN.max(2.0), 2.0);
-    assert_eq!(2.0f16.max(f16::NAN), 2.0);
+    assert_biteq!(f16::NAN.max(2.0), 2.0);
+    assert_biteq!(2.0f16.max(f16::NAN), 2.0);
 }
 
 #[test]
-#[cfg(not(miri))]
-#[cfg(target_has_reliable_f16_math)]
+#[cfg(any(miri, target_has_reliable_f16_math))]
 fn test_minimum() {
     assert!(f16::NAN.minimum(2.0).is_nan());
     assert!(2.0f16.minimum(f16::NAN).is_nan());
 }
 
 #[test]
-#[cfg(not(miri))]
-#[cfg(target_has_reliable_f16_math)]
+#[cfg(any(miri, target_has_reliable_f16_math))]
 fn test_maximum() {
     assert!(f16::NAN.maximum(2.0).is_nan());
     assert!(2.0f16.maximum(f16::NAN).is_nan());
@@ -133,7 +118,7 @@ fn test_neg_infinity() {
 #[test]
 fn test_zero() {
     let zero: f16 = 0.0f16;
-    assert_eq!(0.0, zero);
+    assert_biteq!(0.0, zero);
     assert!(!zero.is_infinite());
     assert!(zero.is_finite());
     assert!(zero.is_sign_positive());
@@ -147,6 +132,7 @@ fn test_zero() {
 fn test_neg_zero() {
     let neg_zero: f16 = -0.0;
     assert_eq!(0.0, neg_zero);
+    assert_biteq!(-0.0, neg_zero);
     assert!(!neg_zero.is_infinite());
     assert!(neg_zero.is_finite());
     assert!(!neg_zero.is_sign_positive());
@@ -159,7 +145,7 @@ fn test_neg_zero() {
 #[test]
 fn test_one() {
     let one: f16 = 1.0f16;
-    assert_eq!(1.0, one);
+    assert_biteq!(1.0, one);
     assert!(!one.is_infinite());
     assert!(one.is_finite());
     assert!(one.is_sign_positive());
@@ -243,114 +229,107 @@ fn test_classify() {
 }
 
 #[test]
-#[cfg(not(miri))]
-#[cfg(target_has_reliable_f16_math)]
+#[cfg(any(miri, target_has_reliable_f16_math))]
 fn test_floor() {
-    assert_approx_eq!(1.0f16.floor(), 1.0f16, TOL_0);
-    assert_approx_eq!(1.3f16.floor(), 1.0f16, TOL_0);
-    assert_approx_eq!(1.5f16.floor(), 1.0f16, TOL_0);
-    assert_approx_eq!(1.7f16.floor(), 1.0f16, TOL_0);
-    assert_approx_eq!(0.0f16.floor(), 0.0f16, TOL_0);
-    assert_approx_eq!((-0.0f16).floor(), -0.0f16, TOL_0);
-    assert_approx_eq!((-1.0f16).floor(), -1.0f16, TOL_0);
-    assert_approx_eq!((-1.3f16).floor(), -2.0f16, TOL_0);
-    assert_approx_eq!((-1.5f16).floor(), -2.0f16, TOL_0);
-    assert_approx_eq!((-1.7f16).floor(), -2.0f16, TOL_0);
+    assert_biteq!(1.0f16.floor(), 1.0f16);
+    assert_biteq!(1.3f16.floor(), 1.0f16);
+    assert_biteq!(1.5f16.floor(), 1.0f16);
+    assert_biteq!(1.7f16.floor(), 1.0f16);
+    assert_biteq!(0.0f16.floor(), 0.0f16);
+    assert_biteq!((-0.0f16).floor(), -0.0f16);
+    assert_biteq!((-1.0f16).floor(), -1.0f16);
+    assert_biteq!((-1.3f16).floor(), -2.0f16);
+    assert_biteq!((-1.5f16).floor(), -2.0f16);
+    assert_biteq!((-1.7f16).floor(), -2.0f16);
 }
 
 #[test]
-#[cfg(not(miri))]
-#[cfg(target_has_reliable_f16_math)]
+#[cfg(any(miri, target_has_reliable_f16_math))]
 fn test_ceil() {
-    assert_approx_eq!(1.0f16.ceil(), 1.0f16, TOL_0);
-    assert_approx_eq!(1.3f16.ceil(), 2.0f16, TOL_0);
-    assert_approx_eq!(1.5f16.ceil(), 2.0f16, TOL_0);
-    assert_approx_eq!(1.7f16.ceil(), 2.0f16, TOL_0);
-    assert_approx_eq!(0.0f16.ceil(), 0.0f16, TOL_0);
-    assert_approx_eq!((-0.0f16).ceil(), -0.0f16, TOL_0);
-    assert_approx_eq!((-1.0f16).ceil(), -1.0f16, TOL_0);
-    assert_approx_eq!((-1.3f16).ceil(), -1.0f16, TOL_0);
-    assert_approx_eq!((-1.5f16).ceil(), -1.0f16, TOL_0);
-    assert_approx_eq!((-1.7f16).ceil(), -1.0f16, TOL_0);
+    assert_biteq!(1.0f16.ceil(), 1.0f16);
+    assert_biteq!(1.3f16.ceil(), 2.0f16);
+    assert_biteq!(1.5f16.ceil(), 2.0f16);
+    assert_biteq!(1.7f16.ceil(), 2.0f16);
+    assert_biteq!(0.0f16.ceil(), 0.0f16);
+    assert_biteq!((-0.0f16).ceil(), -0.0f16);
+    assert_biteq!((-1.0f16).ceil(), -1.0f16);
+    assert_biteq!((-1.3f16).ceil(), -1.0f16);
+    assert_biteq!((-1.5f16).ceil(), -1.0f16);
+    assert_biteq!((-1.7f16).ceil(), -1.0f16);
 }
 
 #[test]
-#[cfg(not(miri))]
-#[cfg(target_has_reliable_f16_math)]
+#[cfg(any(miri, target_has_reliable_f16_math))]
 fn test_round() {
-    assert_approx_eq!(2.5f16.round(), 3.0f16, TOL_0);
-    assert_approx_eq!(1.0f16.round(), 1.0f16, TOL_0);
-    assert_approx_eq!(1.3f16.round(), 1.0f16, TOL_0);
-    assert_approx_eq!(1.5f16.round(), 2.0f16, TOL_0);
-    assert_approx_eq!(1.7f16.round(), 2.0f16, TOL_0);
-    assert_approx_eq!(0.0f16.round(), 0.0f16, TOL_0);
-    assert_approx_eq!((-0.0f16).round(), -0.0f16, TOL_0);
-    assert_approx_eq!((-1.0f16).round(), -1.0f16, TOL_0);
-    assert_approx_eq!((-1.3f16).round(), -1.0f16, TOL_0);
-    assert_approx_eq!((-1.5f16).round(), -2.0f16, TOL_0);
-    assert_approx_eq!((-1.7f16).round(), -2.0f16, TOL_0);
+    assert_biteq!(2.5f16.round(), 3.0f16);
+    assert_biteq!(1.0f16.round(), 1.0f16);
+    assert_biteq!(1.3f16.round(), 1.0f16);
+    assert_biteq!(1.5f16.round(), 2.0f16);
+    assert_biteq!(1.7f16.round(), 2.0f16);
+    assert_biteq!(0.0f16.round(), 0.0f16);
+    assert_biteq!((-0.0f16).round(), -0.0f16);
+    assert_biteq!((-1.0f16).round(), -1.0f16);
+    assert_biteq!((-1.3f16).round(), -1.0f16);
+    assert_biteq!((-1.5f16).round(), -2.0f16);
+    assert_biteq!((-1.7f16).round(), -2.0f16);
 }
 
 #[test]
-#[cfg(not(miri))]
-#[cfg(target_has_reliable_f16_math)]
+#[cfg(any(miri, target_has_reliable_f16_math))]
 fn test_round_ties_even() {
-    assert_approx_eq!(2.5f16.round_ties_even(), 2.0f16, TOL_0);
-    assert_approx_eq!(1.0f16.round_ties_even(), 1.0f16, TOL_0);
-    assert_approx_eq!(1.3f16.round_ties_even(), 1.0f16, TOL_0);
-    assert_approx_eq!(1.5f16.round_ties_even(), 2.0f16, TOL_0);
-    assert_approx_eq!(1.7f16.round_ties_even(), 2.0f16, TOL_0);
-    assert_approx_eq!(0.0f16.round_ties_even(), 0.0f16, TOL_0);
-    assert_approx_eq!((-0.0f16).round_ties_even(), -0.0f16, TOL_0);
-    assert_approx_eq!((-1.0f16).round_ties_even(), -1.0f16, TOL_0);
-    assert_approx_eq!((-1.3f16).round_ties_even(), -1.0f16, TOL_0);
-    assert_approx_eq!((-1.5f16).round_ties_even(), -2.0f16, TOL_0);
-    assert_approx_eq!((-1.7f16).round_ties_even(), -2.0f16, TOL_0);
+    assert_biteq!(2.5f16.round_ties_even(), 2.0f16);
+    assert_biteq!(1.0f16.round_ties_even(), 1.0f16);
+    assert_biteq!(1.3f16.round_ties_even(), 1.0f16);
+    assert_biteq!(1.5f16.round_ties_even(), 2.0f16);
+    assert_biteq!(1.7f16.round_ties_even(), 2.0f16);
+    assert_biteq!(0.0f16.round_ties_even(), 0.0f16);
+    assert_biteq!((-0.0f16).round_ties_even(), -0.0f16);
+    assert_biteq!((-1.0f16).round_ties_even(), -1.0f16);
+    assert_biteq!((-1.3f16).round_ties_even(), -1.0f16);
+    assert_biteq!((-1.5f16).round_ties_even(), -2.0f16);
+    assert_biteq!((-1.7f16).round_ties_even(), -2.0f16);
 }
 
 #[test]
-#[cfg(not(miri))]
-#[cfg(target_has_reliable_f16_math)]
+#[cfg(any(miri, target_has_reliable_f16_math))]
 fn test_trunc() {
-    assert_approx_eq!(1.0f16.trunc(), 1.0f16, TOL_0);
-    assert_approx_eq!(1.3f16.trunc(), 1.0f16, TOL_0);
-    assert_approx_eq!(1.5f16.trunc(), 1.0f16, TOL_0);
-    assert_approx_eq!(1.7f16.trunc(), 1.0f16, TOL_0);
-    assert_approx_eq!(0.0f16.trunc(), 0.0f16, TOL_0);
-    assert_approx_eq!((-0.0f16).trunc(), -0.0f16, TOL_0);
-    assert_approx_eq!((-1.0f16).trunc(), -1.0f16, TOL_0);
-    assert_approx_eq!((-1.3f16).trunc(), -1.0f16, TOL_0);
-    assert_approx_eq!((-1.5f16).trunc(), -1.0f16, TOL_0);
-    assert_approx_eq!((-1.7f16).trunc(), -1.0f16, TOL_0);
+    assert_biteq!(1.0f16.trunc(), 1.0f16);
+    assert_biteq!(1.3f16.trunc(), 1.0f16);
+    assert_biteq!(1.5f16.trunc(), 1.0f16);
+    assert_biteq!(1.7f16.trunc(), 1.0f16);
+    assert_biteq!(0.0f16.trunc(), 0.0f16);
+    assert_biteq!((-0.0f16).trunc(), -0.0f16);
+    assert_biteq!((-1.0f16).trunc(), -1.0f16);
+    assert_biteq!((-1.3f16).trunc(), -1.0f16);
+    assert_biteq!((-1.5f16).trunc(), -1.0f16);
+    assert_biteq!((-1.7f16).trunc(), -1.0f16);
 }
 
 #[test]
-#[cfg(not(miri))]
-#[cfg(target_has_reliable_f16_math)]
+#[cfg(any(miri, target_has_reliable_f16_math))]
 fn test_fract() {
-    assert_approx_eq!(1.0f16.fract(), 0.0f16, TOL_0);
-    assert_approx_eq!(1.3f16.fract(), 0.3f16, TOL_0);
-    assert_approx_eq!(1.5f16.fract(), 0.5f16, TOL_0);
-    assert_approx_eq!(1.7f16.fract(), 0.7f16, TOL_0);
-    assert_approx_eq!(0.0f16.fract(), 0.0f16, TOL_0);
-    assert_approx_eq!((-0.0f16).fract(), -0.0f16, TOL_0);
-    assert_approx_eq!((-1.0f16).fract(), -0.0f16, TOL_0);
-    assert_approx_eq!((-1.3f16).fract(), -0.3f16, TOL_0);
-    assert_approx_eq!((-1.5f16).fract(), -0.5f16, TOL_0);
-    assert_approx_eq!((-1.7f16).fract(), -0.7f16, TOL_0);
+    assert_biteq!(1.0f16.fract(), 0.0f16);
+    assert_biteq!(1.3f16.fract(), 0.2998f16);
+    assert_biteq!(1.5f16.fract(), 0.5f16);
+    assert_biteq!(1.7f16.fract(), 0.7f16);
+    assert_biteq!(0.0f16.fract(), 0.0f16);
+    assert_biteq!((-0.0f16).fract(), 0.0f16);
+    assert_biteq!((-1.0f16).fract(), 0.0f16);
+    assert_biteq!((-1.3f16).fract(), -0.2998f16);
+    assert_biteq!((-1.5f16).fract(), -0.5f16);
+    assert_biteq!((-1.7f16).fract(), -0.7f16);
 }
 
 #[test]
-#[cfg(not(miri))]
-#[cfg(target_has_reliable_f16_math)]
+#[cfg(any(miri, target_has_reliable_f16_math))]
 fn test_abs() {
-    assert_eq!(f16::INFINITY.abs(), f16::INFINITY);
-    assert_eq!(1f16.abs(), 1f16);
-    assert_eq!(0f16.abs(), 0f16);
-    assert_eq!((-0f16).abs(), 0f16);
-    assert_eq!((-1f16).abs(), 1f16);
-    assert_eq!(f16::NEG_INFINITY.abs(), f16::INFINITY);
-    assert_eq!((1f16 / f16::NEG_INFINITY).abs(), 0f16);
+    assert_biteq!(f16::INFINITY.abs(), f16::INFINITY);
+    assert_biteq!(1f16.abs(), 1f16);
+    assert_biteq!(0f16.abs(), 0f16);
+    assert_biteq!((-0f16).abs(), 0f16);
+    assert_biteq!((-1f16).abs(), 1f16);
+    assert_biteq!(f16::NEG_INFINITY.abs(), f16::INFINITY);
+    assert_biteq!((1f16 / f16::NEG_INFINITY).abs(), 0f16);
     assert!(f16::NAN.abs().is_nan());
 }
 
@@ -387,27 +366,27 @@ fn test_next_up() {
     let max_down = f16::from_bits(MAX_DOWN_BITS);
     let largest_subnormal = f16::from_bits(LARGEST_SUBNORMAL_BITS);
     let smallest_normal = f16::from_bits(SMALLEST_NORMAL_BITS);
-    assert_f16_biteq!(f16::NEG_INFINITY.next_up(), f16::MIN);
-    assert_f16_biteq!(f16::MIN.next_up(), -max_down);
-    assert_f16_biteq!((-1.0 - f16::EPSILON).next_up(), -1.0);
-    assert_f16_biteq!((-smallest_normal).next_up(), -largest_subnormal);
-    assert_f16_biteq!((-tiny_up).next_up(), -tiny);
-    assert_f16_biteq!((-tiny).next_up(), -0.0f16);
-    assert_f16_biteq!((-0.0f16).next_up(), tiny);
-    assert_f16_biteq!(0.0f16.next_up(), tiny);
-    assert_f16_biteq!(tiny.next_up(), tiny_up);
-    assert_f16_biteq!(largest_subnormal.next_up(), smallest_normal);
-    assert_f16_biteq!(1.0f16.next_up(), 1.0 + f16::EPSILON);
-    assert_f16_biteq!(f16::MAX.next_up(), f16::INFINITY);
-    assert_f16_biteq!(f16::INFINITY.next_up(), f16::INFINITY);
+    assert_biteq!(f16::NEG_INFINITY.next_up(), f16::MIN);
+    assert_biteq!(f16::MIN.next_up(), -max_down);
+    assert_biteq!((-1.0 - f16::EPSILON).next_up(), -1.0f16);
+    assert_biteq!((-smallest_normal).next_up(), -largest_subnormal);
+    assert_biteq!((-tiny_up).next_up(), -tiny);
+    assert_biteq!((-tiny).next_up(), -0.0f16);
+    assert_biteq!((-0.0f16).next_up(), tiny);
+    assert_biteq!(0.0f16.next_up(), tiny);
+    assert_biteq!(tiny.next_up(), tiny_up);
+    assert_biteq!(largest_subnormal.next_up(), smallest_normal);
+    assert_biteq!(1.0f16.next_up(), 1.0 + f16::EPSILON);
+    assert_biteq!(f16::MAX.next_up(), f16::INFINITY);
+    assert_biteq!(f16::INFINITY.next_up(), f16::INFINITY);
 
     // Check that NaNs roundtrip.
     let nan0 = f16::NAN;
     let nan1 = f16::from_bits(f16::NAN.to_bits() ^ NAN_MASK1);
     let nan2 = f16::from_bits(f16::NAN.to_bits() ^ NAN_MASK2);
-    assert_f16_biteq!(nan0.next_up(), nan0);
-    assert_f16_biteq!(nan1.next_up(), nan1);
-    assert_f16_biteq!(nan2.next_up(), nan2);
+    assert_biteq!(nan0.next_up(), nan0);
+    assert_biteq!(nan1.next_up(), nan1);
+    assert_biteq!(nan2.next_up(), nan2);
 }
 
 #[test]
@@ -417,28 +396,28 @@ fn test_next_down() {
     let max_down = f16::from_bits(MAX_DOWN_BITS);
     let largest_subnormal = f16::from_bits(LARGEST_SUBNORMAL_BITS);
     let smallest_normal = f16::from_bits(SMALLEST_NORMAL_BITS);
-    assert_f16_biteq!(f16::NEG_INFINITY.next_down(), f16::NEG_INFINITY);
-    assert_f16_biteq!(f16::MIN.next_down(), f16::NEG_INFINITY);
-    assert_f16_biteq!((-max_down).next_down(), f16::MIN);
-    assert_f16_biteq!((-1.0f16).next_down(), -1.0 - f16::EPSILON);
-    assert_f16_biteq!((-largest_subnormal).next_down(), -smallest_normal);
-    assert_f16_biteq!((-tiny).next_down(), -tiny_up);
-    assert_f16_biteq!((-0.0f16).next_down(), -tiny);
-    assert_f16_biteq!((0.0f16).next_down(), -tiny);
-    assert_f16_biteq!(tiny.next_down(), 0.0f16);
-    assert_f16_biteq!(tiny_up.next_down(), tiny);
-    assert_f16_biteq!(smallest_normal.next_down(), largest_subnormal);
-    assert_f16_biteq!((1.0 + f16::EPSILON).next_down(), 1.0f16);
-    assert_f16_biteq!(f16::MAX.next_down(), max_down);
-    assert_f16_biteq!(f16::INFINITY.next_down(), f16::MAX);
+    assert_biteq!(f16::NEG_INFINITY.next_down(), f16::NEG_INFINITY);
+    assert_biteq!(f16::MIN.next_down(), f16::NEG_INFINITY);
+    assert_biteq!((-max_down).next_down(), f16::MIN);
+    assert_biteq!((-1.0f16).next_down(), -1.0 - f16::EPSILON);
+    assert_biteq!((-largest_subnormal).next_down(), -smallest_normal);
+    assert_biteq!((-tiny).next_down(), -tiny_up);
+    assert_biteq!((-0.0f16).next_down(), -tiny);
+    assert_biteq!((0.0f16).next_down(), -tiny);
+    assert_biteq!(tiny.next_down(), 0.0f16);
+    assert_biteq!(tiny_up.next_down(), tiny);
+    assert_biteq!(smallest_normal.next_down(), largest_subnormal);
+    assert_biteq!((1.0 + f16::EPSILON).next_down(), 1.0f16);
+    assert_biteq!(f16::MAX.next_down(), max_down);
+    assert_biteq!(f16::INFINITY.next_down(), f16::MAX);
 
     // Check that NaNs roundtrip.
     let nan0 = f16::NAN;
     let nan1 = f16::from_bits(f16::NAN.to_bits() ^ NAN_MASK1);
     let nan2 = f16::from_bits(f16::NAN.to_bits() ^ NAN_MASK2);
-    assert_f16_biteq!(nan0.next_down(), nan0);
-    assert_f16_biteq!(nan1.next_down(), nan1);
-    assert_f16_biteq!(nan2.next_down(), nan2);
+    assert_biteq!(nan0.next_down(), nan0);
+    assert_biteq!(nan1.next_down(), nan1);
+    assert_biteq!(nan2.next_down(), nan2);
 }
 
 #[test]
@@ -448,32 +427,31 @@ fn test_mul_add() {
     let nan: f16 = f16::NAN;
     let inf: f16 = f16::INFINITY;
     let neg_inf: f16 = f16::NEG_INFINITY;
-    assert_approx_eq!(12.3f16.mul_add(4.5, 6.7), 62.05, TOL_P2);
-    assert_approx_eq!((-12.3f16).mul_add(-4.5, -6.7), 48.65, TOL_P2);
-    assert_approx_eq!(0.0f16.mul_add(8.9, 1.2), 1.2, TOL_0);
-    assert_approx_eq!(3.4f16.mul_add(-0.0, 5.6), 5.6, TOL_0);
+    assert_biteq!(12.3f16.mul_add(4.5, 6.7), 62.031);
+    assert_biteq!((-12.3f16).mul_add(-4.5, -6.7), 48.625);
+    assert_biteq!(0.0f16.mul_add(8.9, 1.2), 1.2);
+    assert_biteq!(3.4f16.mul_add(-0.0, 5.6), 5.6);
     assert!(nan.mul_add(7.8, 9.0).is_nan());
-    assert_eq!(inf.mul_add(7.8, 9.0), inf);
-    assert_eq!(neg_inf.mul_add(7.8, 9.0), neg_inf);
-    assert_eq!(8.9f16.mul_add(inf, 3.2), inf);
-    assert_eq!((-3.2f16).mul_add(2.4, neg_inf), neg_inf);
+    assert_biteq!(inf.mul_add(7.8, 9.0), inf);
+    assert_biteq!(neg_inf.mul_add(7.8, 9.0), neg_inf);
+    assert_biteq!(8.9f16.mul_add(inf, 3.2), inf);
+    assert_biteq!((-3.2f16).mul_add(2.4, neg_inf), neg_inf);
 }
 
 #[test]
-#[cfg(not(miri))]
-#[cfg(target_has_reliable_f16_math)]
+#[cfg(any(miri, target_has_reliable_f16_math))]
 fn test_recip() {
     let nan: f16 = f16::NAN;
     let inf: f16 = f16::INFINITY;
     let neg_inf: f16 = f16::NEG_INFINITY;
-    assert_eq!(1.0f16.recip(), 1.0);
-    assert_eq!(2.0f16.recip(), 0.5);
-    assert_eq!((-0.4f16).recip(), -2.5);
-    assert_eq!(0.0f16.recip(), inf);
+    assert_biteq!(1.0f16.recip(), 1.0);
+    assert_biteq!(2.0f16.recip(), 0.5);
+    assert_biteq!((-0.4f16).recip(), -2.5);
+    assert_biteq!(0.0f16.recip(), inf);
     assert_approx_eq!(f16::MAX.recip(), 1.526624e-5f16, 1e-4);
     assert!(nan.recip().is_nan());
-    assert_eq!(inf.recip(), 0.0);
-    assert_eq!(neg_inf.recip(), 0.0);
+    assert_biteq!(inf.recip(), 0.0);
+    assert_biteq!(neg_inf.recip(), -0.0);
 }
 
 #[test]
@@ -483,13 +461,13 @@ fn test_powi() {
     let nan: f16 = f16::NAN;
     let inf: f16 = f16::INFINITY;
     let neg_inf: f16 = f16::NEG_INFINITY;
-    assert_eq!(1.0f16.powi(1), 1.0);
+    assert_biteq!(1.0f16.powi(1), 1.0);
     assert_approx_eq!((-3.1f16).powi(2), 9.61, TOL_0);
     assert_approx_eq!(5.9f16.powi(-2), 0.028727, TOL_N2);
-    assert_eq!(8.3f16.powi(0), 1.0);
+    assert_biteq!(8.3f16.powi(0), 1.0);
     assert!(nan.powi(2).is_nan());
-    assert_eq!(inf.powi(3), inf);
-    assert_eq!(neg_inf.powi(2), inf);
+    assert_biteq!(inf.powi(3), inf);
+    assert_biteq!(neg_inf.powi(2), inf);
 }
 
 #[test]
@@ -499,10 +477,10 @@ fn test_sqrt_domain() {
     assert!(f16::NAN.sqrt().is_nan());
     assert!(f16::NEG_INFINITY.sqrt().is_nan());
     assert!((-1.0f16).sqrt().is_nan());
-    assert_eq!((-0.0f16).sqrt(), -0.0);
-    assert_eq!(0.0f16.sqrt(), 0.0);
-    assert_eq!(1.0f16.sqrt(), 1.0);
-    assert_eq!(f16::INFINITY.sqrt(), f16::INFINITY);
+    assert_biteq!((-0.0f16).sqrt(), -0.0);
+    assert_biteq!(0.0f16.sqrt(), 0.0);
+    assert_biteq!(1.0f16.sqrt(), 1.0);
+    assert_biteq!(f16::INFINITY.sqrt(), f16::INFINITY);
 }
 
 #[test]
@@ -511,13 +489,13 @@ fn test_to_degrees() {
     let nan: f16 = f16::NAN;
     let inf: f16 = f16::INFINITY;
     let neg_inf: f16 = f16::NEG_INFINITY;
-    assert_eq!(0.0f16.to_degrees(), 0.0);
+    assert_biteq!(0.0f16.to_degrees(), 0.0);
     assert_approx_eq!((-5.8f16).to_degrees(), -332.315521, TOL_P2);
     assert_approx_eq!(pi.to_degrees(), 180.0, TOL_P2);
     assert!(nan.to_degrees().is_nan());
-    assert_eq!(inf.to_degrees(), inf);
-    assert_eq!(neg_inf.to_degrees(), neg_inf);
-    assert_eq!(1_f16.to_degrees(), 57.2957795130823208767981548141051703);
+    assert_biteq!(inf.to_degrees(), inf);
+    assert_biteq!(neg_inf.to_degrees(), neg_inf);
+    assert_biteq!(1_f16.to_degrees(), 57.2957795130823208767981548141051703);
 }
 
 #[test]
@@ -526,13 +504,13 @@ fn test_to_radians() {
     let nan: f16 = f16::NAN;
     let inf: f16 = f16::INFINITY;
     let neg_inf: f16 = f16::NEG_INFINITY;
-    assert_eq!(0.0f16.to_radians(), 0.0);
+    assert_biteq!(0.0f16.to_radians(), 0.0);
     assert_approx_eq!(154.6f16.to_radians(), 2.698279, TOL_0);
     assert_approx_eq!((-332.31f16).to_radians(), -5.799903, TOL_0);
     assert_approx_eq!(180.0f16.to_radians(), pi, TOL_0);
     assert!(nan.to_radians().is_nan());
-    assert_eq!(inf.to_radians(), inf);
-    assert_eq!(neg_inf.to_radians(), neg_inf);
+    assert_biteq!(inf.to_radians(), inf);
+    assert_biteq!(neg_inf.to_radians(), neg_inf);
 }
 
 #[test]
@@ -541,10 +519,10 @@ fn test_float_bits_conv() {
     assert_eq!((12.5f16).to_bits(), 0x4a40);
     assert_eq!((1337f16).to_bits(), 0x6539);
     assert_eq!((-14.25f16).to_bits(), 0xcb20);
-    assert_approx_eq!(f16::from_bits(0x3c00), 1.0, TOL_0);
-    assert_approx_eq!(f16::from_bits(0x4a40), 12.5, TOL_0);
-    assert_approx_eq!(f16::from_bits(0x6539), 1337.0, TOL_P4);
-    assert_approx_eq!(f16::from_bits(0xcb20), -14.25, TOL_0);
+    assert_biteq!(f16::from_bits(0x3c00), 1.0);
+    assert_biteq!(f16::from_bits(0x4a40), 12.5);
+    assert_biteq!(f16::from_bits(0x6539), 1337.0);
+    assert_biteq!(f16::from_bits(0xcb20), -14.25);
 
     // Check that NaNs roundtrip their bits regardless of signaling-ness
     let masked_nan1 = f16::NAN.to_bits() ^ NAN_MASK1;
@@ -745,12 +723,12 @@ fn test_algebraic() {
 
 #[test]
 fn test_from() {
-    assert_eq!(f16::from(false), 0.0);
-    assert_eq!(f16::from(true), 1.0);
-    assert_eq!(f16::from(u8::MIN), 0.0);
-    assert_eq!(f16::from(42_u8), 42.0);
-    assert_eq!(f16::from(u8::MAX), 255.0);
-    assert_eq!(f16::from(i8::MIN), -128.0);
-    assert_eq!(f16::from(42_i8), 42.0);
-    assert_eq!(f16::from(i8::MAX), 127.0);
+    assert_biteq!(f16::from(false), 0.0);
+    assert_biteq!(f16::from(true), 1.0);
+    assert_biteq!(f16::from(u8::MIN), 0.0);
+    assert_biteq!(f16::from(42_u8), 42.0);
+    assert_biteq!(f16::from(u8::MAX), 255.0);
+    assert_biteq!(f16::from(i8::MIN), -128.0);
+    assert_biteq!(f16::from(42_i8), 42.0);
+    assert_biteq!(f16::from(i8::MAX), 127.0);
 }
diff --git a/library/coretests/tests/floats/f32.rs b/library/coretests/tests/floats/f32.rs
index 36f1937bedf..4e6509ead2b 100644
--- a/library/coretests/tests/floats/f32.rs
+++ b/library/coretests/tests/floats/f32.rs
@@ -23,17 +23,6 @@ const NAN_MASK1: u32 = 0x002a_aaaa;
 /// Second pattern over the mantissa
 const NAN_MASK2: u32 = 0x0055_5555;
 
-#[allow(unused_macros)]
-macro_rules! assert_f32_biteq {
-    ($left : expr, $right : expr) => {
-        let l: &f32 = &$left;
-        let r: &f32 = &$right;
-        let lb = l.to_bits();
-        let rb = r.to_bits();
-        assert_eq!(lb, rb, "float {l} ({lb:#010x}) is not bitequal to {r} ({rb:#010x})");
-    };
-}
-
 #[test]
 fn test_num_f32() {
     super::test_num(10f32, 2f32);
@@ -41,14 +30,14 @@ fn test_num_f32() {
 
 #[test]
 fn test_min_nan() {
-    assert_eq!(f32::NAN.min(2.0), 2.0);
-    assert_eq!(2.0f32.min(f32::NAN), 2.0);
+    assert_biteq!(f32::NAN.min(2.0), 2.0);
+    assert_biteq!(2.0f32.min(f32::NAN), 2.0);
 }
 
 #[test]
 fn test_max_nan() {
-    assert_eq!(f32::NAN.max(2.0), 2.0);
-    assert_eq!(2.0f32.max(f32::NAN), 2.0);
+    assert_biteq!(f32::NAN.max(2.0), 2.0);
+    assert_biteq!(2.0f32.max(f32::NAN), 2.0);
 }
 
 #[test]
@@ -104,7 +93,7 @@ fn test_neg_infinity() {
 #[test]
 fn test_zero() {
     let zero: f32 = 0.0f32;
-    assert_eq!(0.0, zero);
+    assert_biteq!(0.0, zero);
     assert!(!zero.is_infinite());
     assert!(zero.is_finite());
     assert!(zero.is_sign_positive());
@@ -118,6 +107,7 @@ fn test_zero() {
 fn test_neg_zero() {
     let neg_zero: f32 = -0.0;
     assert_eq!(0.0, neg_zero);
+    assert_biteq!(-0.0, neg_zero);
     assert!(!neg_zero.is_infinite());
     assert!(neg_zero.is_finite());
     assert!(!neg_zero.is_sign_positive());
@@ -130,7 +120,7 @@ fn test_neg_zero() {
 #[test]
 fn test_one() {
     let one: f32 = 1.0f32;
-    assert_eq!(1.0, one);
+    assert_biteq!(1.0, one);
     assert!(!one.is_infinite());
     assert!(one.is_finite());
     assert!(one.is_sign_positive());
@@ -215,111 +205,111 @@ fn test_classify() {
 
 #[test]
 fn test_floor() {
-    assert_approx_eq!(f32::math::floor(1.0f32), 1.0f32);
-    assert_approx_eq!(f32::math::floor(1.3f32), 1.0f32);
-    assert_approx_eq!(f32::math::floor(1.5f32), 1.0f32);
-    assert_approx_eq!(f32::math::floor(1.7f32), 1.0f32);
-    assert_approx_eq!(f32::math::floor(0.0f32), 0.0f32);
-    assert_approx_eq!(f32::math::floor(-0.0f32), -0.0f32);
-    assert_approx_eq!(f32::math::floor(-1.0f32), -1.0f32);
-    assert_approx_eq!(f32::math::floor(-1.3f32), -2.0f32);
-    assert_approx_eq!(f32::math::floor(-1.5f32), -2.0f32);
-    assert_approx_eq!(f32::math::floor(-1.7f32), -2.0f32);
+    assert_biteq!(f32::math::floor(1.0f32), 1.0f32);
+    assert_biteq!(f32::math::floor(1.3f32), 1.0f32);
+    assert_biteq!(f32::math::floor(1.5f32), 1.0f32);
+    assert_biteq!(f32::math::floor(1.7f32), 1.0f32);
+    assert_biteq!(f32::math::floor(0.0f32), 0.0f32);
+    assert_biteq!(f32::math::floor(-0.0f32), -0.0f32);
+    assert_biteq!(f32::math::floor(-1.0f32), -1.0f32);
+    assert_biteq!(f32::math::floor(-1.3f32), -2.0f32);
+    assert_biteq!(f32::math::floor(-1.5f32), -2.0f32);
+    assert_biteq!(f32::math::floor(-1.7f32), -2.0f32);
 }
 
 #[test]
 fn test_ceil() {
-    assert_approx_eq!(f32::math::ceil(1.0f32), 1.0f32);
-    assert_approx_eq!(f32::math::ceil(1.3f32), 2.0f32);
-    assert_approx_eq!(f32::math::ceil(1.5f32), 2.0f32);
-    assert_approx_eq!(f32::math::ceil(1.7f32), 2.0f32);
-    assert_approx_eq!(f32::math::ceil(0.0f32), 0.0f32);
-    assert_approx_eq!(f32::math::ceil(-0.0f32), -0.0f32);
-    assert_approx_eq!(f32::math::ceil(-1.0f32), -1.0f32);
-    assert_approx_eq!(f32::math::ceil(-1.3f32), -1.0f32);
-    assert_approx_eq!(f32::math::ceil(-1.5f32), -1.0f32);
-    assert_approx_eq!(f32::math::ceil(-1.7f32), -1.0f32);
+    assert_biteq!(f32::math::ceil(1.0f32), 1.0f32);
+    assert_biteq!(f32::math::ceil(1.3f32), 2.0f32);
+    assert_biteq!(f32::math::ceil(1.5f32), 2.0f32);
+    assert_biteq!(f32::math::ceil(1.7f32), 2.0f32);
+    assert_biteq!(f32::math::ceil(0.0f32), 0.0f32);
+    assert_biteq!(f32::math::ceil(-0.0f32), -0.0f32);
+    assert_biteq!(f32::math::ceil(-1.0f32), -1.0f32);
+    assert_biteq!(f32::math::ceil(-1.3f32), -1.0f32);
+    assert_biteq!(f32::math::ceil(-1.5f32), -1.0f32);
+    assert_biteq!(f32::math::ceil(-1.7f32), -1.0f32);
 }
 
 #[test]
 fn test_round() {
-    assert_approx_eq!(f32::math::round(2.5f32), 3.0f32);
-    assert_approx_eq!(f32::math::round(1.0f32), 1.0f32);
-    assert_approx_eq!(f32::math::round(1.3f32), 1.0f32);
-    assert_approx_eq!(f32::math::round(1.5f32), 2.0f32);
-    assert_approx_eq!(f32::math::round(1.7f32), 2.0f32);
-    assert_approx_eq!(f32::math::round(0.0f32), 0.0f32);
-    assert_approx_eq!(f32::math::round(-0.0f32), -0.0f32);
-    assert_approx_eq!(f32::math::round(-1.0f32), -1.0f32);
-    assert_approx_eq!(f32::math::round(-1.3f32), -1.0f32);
-    assert_approx_eq!(f32::math::round(-1.5f32), -2.0f32);
-    assert_approx_eq!(f32::math::round(-1.7f32), -2.0f32);
+    assert_biteq!(f32::math::round(2.5f32), 3.0f32);
+    assert_biteq!(f32::math::round(1.0f32), 1.0f32);
+    assert_biteq!(f32::math::round(1.3f32), 1.0f32);
+    assert_biteq!(f32::math::round(1.5f32), 2.0f32);
+    assert_biteq!(f32::math::round(1.7f32), 2.0f32);
+    assert_biteq!(f32::math::round(0.0f32), 0.0f32);
+    assert_biteq!(f32::math::round(-0.0f32), -0.0f32);
+    assert_biteq!(f32::math::round(-1.0f32), -1.0f32);
+    assert_biteq!(f32::math::round(-1.3f32), -1.0f32);
+    assert_biteq!(f32::math::round(-1.5f32), -2.0f32);
+    assert_biteq!(f32::math::round(-1.7f32), -2.0f32);
 }
 
 #[test]
 fn test_round_ties_even() {
-    assert_approx_eq!(f32::math::round_ties_even(2.5f32), 2.0f32);
-    assert_approx_eq!(f32::math::round_ties_even(1.0f32), 1.0f32);
-    assert_approx_eq!(f32::math::round_ties_even(1.3f32), 1.0f32);
-    assert_approx_eq!(f32::math::round_ties_even(1.5f32), 2.0f32);
-    assert_approx_eq!(f32::math::round_ties_even(1.7f32), 2.0f32);
-    assert_approx_eq!(f32::math::round_ties_even(0.0f32), 0.0f32);
-    assert_approx_eq!(f32::math::round_ties_even(-0.0f32), -0.0f32);
-    assert_approx_eq!(f32::math::round_ties_even(-1.0f32), -1.0f32);
-    assert_approx_eq!(f32::math::round_ties_even(-1.3f32), -1.0f32);
-    assert_approx_eq!(f32::math::round_ties_even(-1.5f32), -2.0f32);
-    assert_approx_eq!(f32::math::round_ties_even(-1.7f32), -2.0f32);
+    assert_biteq!(f32::math::round_ties_even(2.5f32), 2.0f32);
+    assert_biteq!(f32::math::round_ties_even(1.0f32), 1.0f32);
+    assert_biteq!(f32::math::round_ties_even(1.3f32), 1.0f32);
+    assert_biteq!(f32::math::round_ties_even(1.5f32), 2.0f32);
+    assert_biteq!(f32::math::round_ties_even(1.7f32), 2.0f32);
+    assert_biteq!(f32::math::round_ties_even(0.0f32), 0.0f32);
+    assert_biteq!(f32::math::round_ties_even(-0.0f32), -0.0f32);
+    assert_biteq!(f32::math::round_ties_even(-1.0f32), -1.0f32);
+    assert_biteq!(f32::math::round_ties_even(-1.3f32), -1.0f32);
+    assert_biteq!(f32::math::round_ties_even(-1.5f32), -2.0f32);
+    assert_biteq!(f32::math::round_ties_even(-1.7f32), -2.0f32);
 }
 
 #[test]
 fn test_trunc() {
-    assert_approx_eq!(f32::math::trunc(1.0f32), 1.0f32);
-    assert_approx_eq!(f32::math::trunc(1.3f32), 1.0f32);
-    assert_approx_eq!(f32::math::trunc(1.5f32), 1.0f32);
-    assert_approx_eq!(f32::math::trunc(1.7f32), 1.0f32);
-    assert_approx_eq!(f32::math::trunc(0.0f32), 0.0f32);
-    assert_approx_eq!(f32::math::trunc(-0.0f32), -0.0f32);
-    assert_approx_eq!(f32::math::trunc(-1.0f32), -1.0f32);
-    assert_approx_eq!(f32::math::trunc(-1.3f32), -1.0f32);
-    assert_approx_eq!(f32::math::trunc(-1.5f32), -1.0f32);
-    assert_approx_eq!(f32::math::trunc(-1.7f32), -1.0f32);
+    assert_biteq!(f32::math::trunc(1.0f32), 1.0f32);
+    assert_biteq!(f32::math::trunc(1.3f32), 1.0f32);
+    assert_biteq!(f32::math::trunc(1.5f32), 1.0f32);
+    assert_biteq!(f32::math::trunc(1.7f32), 1.0f32);
+    assert_biteq!(f32::math::trunc(0.0f32), 0.0f32);
+    assert_biteq!(f32::math::trunc(-0.0f32), -0.0f32);
+    assert_biteq!(f32::math::trunc(-1.0f32), -1.0f32);
+    assert_biteq!(f32::math::trunc(-1.3f32), -1.0f32);
+    assert_biteq!(f32::math::trunc(-1.5f32), -1.0f32);
+    assert_biteq!(f32::math::trunc(-1.7f32), -1.0f32);
 }
 
 #[test]
 fn test_fract() {
-    assert_approx_eq!(f32::math::fract(1.0f32), 0.0f32);
-    assert_approx_eq!(f32::math::fract(1.3f32), 0.3f32);
-    assert_approx_eq!(f32::math::fract(1.5f32), 0.5f32);
-    assert_approx_eq!(f32::math::fract(1.7f32), 0.7f32);
-    assert_approx_eq!(f32::math::fract(0.0f32), 0.0f32);
-    assert_approx_eq!(f32::math::fract(-0.0f32), -0.0f32);
-    assert_approx_eq!(f32::math::fract(-1.0f32), -0.0f32);
-    assert_approx_eq!(f32::math::fract(-1.3f32), -0.3f32);
-    assert_approx_eq!(f32::math::fract(-1.5f32), -0.5f32);
-    assert_approx_eq!(f32::math::fract(-1.7f32), -0.7f32);
+    assert_biteq!(f32::math::fract(1.0f32), 0.0f32);
+    assert_biteq!(f32::math::fract(1.3f32), 0.29999995f32);
+    assert_biteq!(f32::math::fract(1.5f32), 0.5f32);
+    assert_biteq!(f32::math::fract(1.7f32), 0.70000005f32);
+    assert_biteq!(f32::math::fract(0.0f32), 0.0f32);
+    assert_biteq!(f32::math::fract(-0.0f32), 0.0f32);
+    assert_biteq!(f32::math::fract(-1.0f32), 0.0f32);
+    assert_biteq!(f32::math::fract(-1.3f32), -0.29999995f32);
+    assert_biteq!(f32::math::fract(-1.5f32), -0.5f32);
+    assert_biteq!(f32::math::fract(-1.7f32), -0.70000005f32);
 }
 
 #[test]
 fn test_abs() {
-    assert_eq!(f32::INFINITY.abs(), f32::INFINITY);
-    assert_eq!(1f32.abs(), 1f32);
-    assert_eq!(0f32.abs(), 0f32);
-    assert_eq!((-0f32).abs(), 0f32);
-    assert_eq!((-1f32).abs(), 1f32);
-    assert_eq!(f32::NEG_INFINITY.abs(), f32::INFINITY);
-    assert_eq!((1f32 / f32::NEG_INFINITY).abs(), 0f32);
+    assert_biteq!(f32::INFINITY.abs(), f32::INFINITY);
+    assert_biteq!(1f32.abs(), 1f32);
+    assert_biteq!(0f32.abs(), 0f32);
+    assert_biteq!((-0f32).abs(), 0f32);
+    assert_biteq!((-1f32).abs(), 1f32);
+    assert_biteq!(f32::NEG_INFINITY.abs(), f32::INFINITY);
+    assert_biteq!((1f32 / f32::NEG_INFINITY).abs(), 0f32);
     assert!(f32::NAN.abs().is_nan());
 }
 
 #[test]
 fn test_signum() {
-    assert_eq!(f32::INFINITY.signum(), 1f32);
-    assert_eq!(1f32.signum(), 1f32);
-    assert_eq!(0f32.signum(), 1f32);
-    assert_eq!((-0f32).signum(), -1f32);
-    assert_eq!((-1f32).signum(), -1f32);
-    assert_eq!(f32::NEG_INFINITY.signum(), -1f32);
-    assert_eq!((1f32 / f32::NEG_INFINITY).signum(), -1f32);
+    assert_biteq!(f32::INFINITY.signum(), 1f32);
+    assert_biteq!(1f32.signum(), 1f32);
+    assert_biteq!(0f32.signum(), 1f32);
+    assert_biteq!((-0f32).signum(), -1f32);
+    assert_biteq!((-1f32).signum(), -1f32);
+    assert_biteq!(f32::NEG_INFINITY.signum(), -1f32);
+    assert_biteq!((1f32 / f32::NEG_INFINITY).signum(), -1f32);
     assert!(f32::NAN.signum().is_nan());
 }
 
@@ -356,27 +346,27 @@ fn test_next_up() {
     let max_down = f32::from_bits(MAX_DOWN_BITS);
     let largest_subnormal = f32::from_bits(LARGEST_SUBNORMAL_BITS);
     let smallest_normal = f32::from_bits(SMALLEST_NORMAL_BITS);
-    assert_f32_biteq!(f32::NEG_INFINITY.next_up(), f32::MIN);
-    assert_f32_biteq!(f32::MIN.next_up(), -max_down);
-    assert_f32_biteq!((-1.0 - f32::EPSILON).next_up(), -1.0);
-    assert_f32_biteq!((-smallest_normal).next_up(), -largest_subnormal);
-    assert_f32_biteq!((-tiny_up).next_up(), -tiny);
-    assert_f32_biteq!((-tiny).next_up(), -0.0f32);
-    assert_f32_biteq!((-0.0f32).next_up(), tiny);
-    assert_f32_biteq!(0.0f32.next_up(), tiny);
-    assert_f32_biteq!(tiny.next_up(), tiny_up);
-    assert_f32_biteq!(largest_subnormal.next_up(), smallest_normal);
-    assert_f32_biteq!(1.0f32.next_up(), 1.0 + f32::EPSILON);
-    assert_f32_biteq!(f32::MAX.next_up(), f32::INFINITY);
-    assert_f32_biteq!(f32::INFINITY.next_up(), f32::INFINITY);
+    assert_biteq!(f32::NEG_INFINITY.next_up(), f32::MIN);
+    assert_biteq!(f32::MIN.next_up(), -max_down);
+    assert_biteq!((-1.0f32 - f32::EPSILON).next_up(), -1.0f32);
+    assert_biteq!((-smallest_normal).next_up(), -largest_subnormal);
+    assert_biteq!((-tiny_up).next_up(), -tiny);
+    assert_biteq!((-tiny).next_up(), -0.0f32);
+    assert_biteq!((-0.0f32).next_up(), tiny);
+    assert_biteq!(0.0f32.next_up(), tiny);
+    assert_biteq!(tiny.next_up(), tiny_up);
+    assert_biteq!(largest_subnormal.next_up(), smallest_normal);
+    assert_biteq!(1.0f32.next_up(), 1.0 + f32::EPSILON);
+    assert_biteq!(f32::MAX.next_up(), f32::INFINITY);
+    assert_biteq!(f32::INFINITY.next_up(), f32::INFINITY);
 
     // Check that NaNs roundtrip.
     let nan0 = f32::NAN;
     let nan1 = f32::from_bits(f32::NAN.to_bits() ^ NAN_MASK1);
     let nan2 = f32::from_bits(f32::NAN.to_bits() ^ NAN_MASK2);
-    assert_f32_biteq!(nan0.next_up(), nan0);
-    assert_f32_biteq!(nan1.next_up(), nan1);
-    assert_f32_biteq!(nan2.next_up(), nan2);
+    assert_biteq!(nan0.next_up(), nan0);
+    assert_biteq!(nan1.next_up(), nan1);
+    assert_biteq!(nan2.next_up(), nan2);
 }
 
 #[test]
@@ -386,28 +376,28 @@ fn test_next_down() {
     let max_down = f32::from_bits(MAX_DOWN_BITS);
     let largest_subnormal = f32::from_bits(LARGEST_SUBNORMAL_BITS);
     let smallest_normal = f32::from_bits(SMALLEST_NORMAL_BITS);
-    assert_f32_biteq!(f32::NEG_INFINITY.next_down(), f32::NEG_INFINITY);
-    assert_f32_biteq!(f32::MIN.next_down(), f32::NEG_INFINITY);
-    assert_f32_biteq!((-max_down).next_down(), f32::MIN);
-    assert_f32_biteq!((-1.0f32).next_down(), -1.0 - f32::EPSILON);
-    assert_f32_biteq!((-largest_subnormal).next_down(), -smallest_normal);
-    assert_f32_biteq!((-tiny).next_down(), -tiny_up);
-    assert_f32_biteq!((-0.0f32).next_down(), -tiny);
-    assert_f32_biteq!((0.0f32).next_down(), -tiny);
-    assert_f32_biteq!(tiny.next_down(), 0.0f32);
-    assert_f32_biteq!(tiny_up.next_down(), tiny);
-    assert_f32_biteq!(smallest_normal.next_down(), largest_subnormal);
-    assert_f32_biteq!((1.0 + f32::EPSILON).next_down(), 1.0f32);
-    assert_f32_biteq!(f32::MAX.next_down(), max_down);
-    assert_f32_biteq!(f32::INFINITY.next_down(), f32::MAX);
+    assert_biteq!(f32::NEG_INFINITY.next_down(), f32::NEG_INFINITY);
+    assert_biteq!(f32::MIN.next_down(), f32::NEG_INFINITY);
+    assert_biteq!((-max_down).next_down(), f32::MIN);
+    assert_biteq!((-1.0f32).next_down(), -1.0 - f32::EPSILON);
+    assert_biteq!((-largest_subnormal).next_down(), -smallest_normal);
+    assert_biteq!((-tiny).next_down(), -tiny_up);
+    assert_biteq!((-0.0f32).next_down(), -tiny);
+    assert_biteq!((0.0f32).next_down(), -tiny);
+    assert_biteq!(tiny.next_down(), 0.0f32);
+    assert_biteq!(tiny_up.next_down(), tiny);
+    assert_biteq!(smallest_normal.next_down(), largest_subnormal);
+    assert_biteq!((1.0 + f32::EPSILON).next_down(), 1.0f32);
+    assert_biteq!(f32::MAX.next_down(), max_down);
+    assert_biteq!(f32::INFINITY.next_down(), f32::MAX);
 
     // Check that NaNs roundtrip.
     let nan0 = f32::NAN;
     let nan1 = f32::from_bits(f32::NAN.to_bits() ^ NAN_MASK1);
     let nan2 = f32::from_bits(f32::NAN.to_bits() ^ NAN_MASK2);
-    assert_f32_biteq!(nan0.next_down(), nan0);
-    assert_f32_biteq!(nan1.next_down(), nan1);
-    assert_f32_biteq!(nan2.next_down(), nan2);
+    assert_biteq!(nan0.next_down(), nan0);
+    assert_biteq!(nan1.next_down(), nan1);
+    assert_biteq!(nan2.next_down(), nan2);
 }
 
 // FIXME(#140515): mingw has an incorrect fma https://sourceforge.net/p/mingw-w64/bugs/848/
@@ -417,15 +407,15 @@ fn test_mul_add() {
     let nan: f32 = f32::NAN;
     let inf: f32 = f32::INFINITY;
     let neg_inf: f32 = f32::NEG_INFINITY;
-    assert_approx_eq!(f32::math::mul_add(12.3f32, 4.5, 6.7), 62.05);
-    assert_approx_eq!(f32::math::mul_add(-12.3f32, -4.5, -6.7), 48.65);
-    assert_approx_eq!(f32::math::mul_add(0.0f32, 8.9, 1.2), 1.2);
-    assert_approx_eq!(f32::math::mul_add(3.4f32, -0.0, 5.6), 5.6);
+    assert_biteq!(f32::math::mul_add(12.3f32, 4.5, 6.7), 62.05);
+    assert_biteq!(f32::math::mul_add(-12.3f32, -4.5, -6.7), 48.65);
+    assert_biteq!(f32::math::mul_add(0.0f32, 8.9, 1.2), 1.2);
+    assert_biteq!(f32::math::mul_add(3.4f32, -0.0, 5.6), 5.6);
     assert!(f32::math::mul_add(nan, 7.8, 9.0).is_nan());
-    assert_eq!(f32::math::mul_add(inf, 7.8, 9.0), inf);
-    assert_eq!(f32::math::mul_add(neg_inf, 7.8, 9.0), neg_inf);
-    assert_eq!(f32::math::mul_add(8.9f32, inf, 3.2), inf);
-    assert_eq!(f32::math::mul_add(-3.2f32, 2.4, neg_inf), neg_inf);
+    assert_biteq!(f32::math::mul_add(inf, 7.8, 9.0), inf);
+    assert_biteq!(f32::math::mul_add(neg_inf, 7.8, 9.0), neg_inf);
+    assert_biteq!(f32::math::mul_add(8.9f32, inf, 3.2), inf);
+    assert_biteq!(f32::math::mul_add(-3.2f32, 2.4, neg_inf), neg_inf);
 }
 
 #[test]
@@ -433,13 +423,13 @@ fn test_recip() {
     let nan: f32 = f32::NAN;
     let inf: f32 = f32::INFINITY;
     let neg_inf: f32 = f32::NEG_INFINITY;
-    assert_eq!(1.0f32.recip(), 1.0);
-    assert_eq!(2.0f32.recip(), 0.5);
-    assert_eq!((-0.4f32).recip(), -2.5);
-    assert_eq!(0.0f32.recip(), inf);
+    assert_biteq!(1.0f32.recip(), 1.0);
+    assert_biteq!(2.0f32.recip(), 0.5);
+    assert_biteq!((-0.4f32).recip(), -2.5);
+    assert_biteq!(0.0f32.recip(), inf);
     assert!(nan.recip().is_nan());
-    assert_eq!(inf.recip(), 0.0);
-    assert_eq!(neg_inf.recip(), 0.0);
+    assert_biteq!(inf.recip(), 0.0);
+    assert_biteq!(neg_inf.recip(), -0.0);
 }
 
 #[test]
@@ -447,13 +437,13 @@ fn test_powi() {
     let nan: f32 = f32::NAN;
     let inf: f32 = f32::INFINITY;
     let neg_inf: f32 = f32::NEG_INFINITY;
-    assert_eq!(1.0f32.powi(1), 1.0);
+    assert_biteq!(1.0f32.powi(1), 1.0);
     assert_approx_eq!((-3.1f32).powi(2), 9.61);
     assert_approx_eq!(5.9f32.powi(-2), 0.028727);
-    assert_eq!(8.3f32.powi(0), 1.0);
+    assert_biteq!(8.3f32.powi(0), 1.0);
     assert!(nan.powi(2).is_nan());
-    assert_eq!(inf.powi(3), inf);
-    assert_eq!(neg_inf.powi(2), inf);
+    assert_biteq!(inf.powi(3), inf);
+    assert_biteq!(neg_inf.powi(2), inf);
 }
 
 #[test]
@@ -461,10 +451,10 @@ fn test_sqrt_domain() {
     assert!(f32::NAN.sqrt().is_nan());
     assert!(f32::NEG_INFINITY.sqrt().is_nan());
     assert!((-1.0f32).sqrt().is_nan());
-    assert_eq!((-0.0f32).sqrt(), -0.0);
-    assert_eq!(0.0f32.sqrt(), 0.0);
-    assert_eq!(1.0f32.sqrt(), 1.0);
-    assert_eq!(f32::INFINITY.sqrt(), f32::INFINITY);
+    assert_biteq!((-0.0f32).sqrt(), -0.0);
+    assert_biteq!(0.0f32.sqrt(), 0.0);
+    assert_biteq!(1.0f32.sqrt(), 1.0);
+    assert_biteq!(f32::INFINITY.sqrt(), f32::INFINITY);
 }
 
 #[test]
@@ -473,13 +463,13 @@ fn test_to_degrees() {
     let nan: f32 = f32::NAN;
     let inf: f32 = f32::INFINITY;
     let neg_inf: f32 = f32::NEG_INFINITY;
-    assert_eq!(0.0f32.to_degrees(), 0.0);
+    assert_biteq!(0.0f32.to_degrees(), 0.0);
     assert_approx_eq!((-5.8f32).to_degrees(), -332.315521);
-    assert_eq!(pi.to_degrees(), 180.0);
+    assert_biteq!(pi.to_degrees(), 180.0);
     assert!(nan.to_degrees().is_nan());
-    assert_eq!(inf.to_degrees(), inf);
-    assert_eq!(neg_inf.to_degrees(), neg_inf);
-    assert_eq!(1_f32.to_degrees(), 57.2957795130823208767981548141051703);
+    assert_biteq!(inf.to_degrees(), inf);
+    assert_biteq!(neg_inf.to_degrees(), neg_inf);
+    assert_biteq!(1_f32.to_degrees(), 57.2957795130823208767981548141051703);
 }
 
 #[test]
@@ -488,13 +478,13 @@ fn test_to_radians() {
     let nan: f32 = f32::NAN;
     let inf: f32 = f32::INFINITY;
     let neg_inf: f32 = f32::NEG_INFINITY;
-    assert_eq!(0.0f32.to_radians(), 0.0);
+    assert_biteq!(0.0f32.to_radians(), 0.0);
     assert_approx_eq!(154.6f32.to_radians(), 2.698279);
     assert_approx_eq!((-332.31f32).to_radians(), -5.799903);
-    assert_eq!(180.0f32.to_radians(), pi);
+    assert_biteq!(180.0f32.to_radians(), pi);
     assert!(nan.to_radians().is_nan());
-    assert_eq!(inf.to_radians(), inf);
-    assert_eq!(neg_inf.to_radians(), neg_inf);
+    assert_biteq!(inf.to_radians(), inf);
+    assert_biteq!(neg_inf.to_radians(), neg_inf);
 }
 
 #[test]
@@ -503,10 +493,10 @@ fn test_float_bits_conv() {
     assert_eq!((12.5f32).to_bits(), 0x41480000);
     assert_eq!((1337f32).to_bits(), 0x44a72000);
     assert_eq!((-14.25f32).to_bits(), 0xc1640000);
-    assert_approx_eq!(f32::from_bits(0x3f800000), 1.0);
-    assert_approx_eq!(f32::from_bits(0x41480000), 12.5);
-    assert_approx_eq!(f32::from_bits(0x44a72000), 1337.0);
-    assert_approx_eq!(f32::from_bits(0xc1640000), -14.25);
+    assert_biteq!(f32::from_bits(0x3f800000), 1.0);
+    assert_biteq!(f32::from_bits(0x41480000), 12.5);
+    assert_biteq!(f32::from_bits(0x44a72000), 1337.0);
+    assert_biteq!(f32::from_bits(0xc1640000), -14.25);
 
     // Check that NaNs roundtrip their bits regardless of signaling-ness
     // 0xA is 0b1010; 0x5 is 0b0101 -- so these two together clobbers all the mantissa bits
diff --git a/library/coretests/tests/floats/f64.rs b/library/coretests/tests/floats/f64.rs
index 97051998353..74202a37409 100644
--- a/library/coretests/tests/floats/f64.rs
+++ b/library/coretests/tests/floats/f64.rs
@@ -23,17 +23,6 @@ const NAN_MASK1: u64 = 0x000a_aaaa_aaaa_aaaa;
 /// Second pattern over the mantissa
 const NAN_MASK2: u64 = 0x0005_5555_5555_5555;
 
-#[allow(unused_macros)]
-macro_rules! assert_f64_biteq {
-    ($left : expr, $right : expr) => {
-        let l: &f64 = &$left;
-        let r: &f64 = &$right;
-        let lb = l.to_bits();
-        let rb = r.to_bits();
-        assert_eq!(lb, rb, "float {l} ({lb:#018x}) is not bitequal to {r} ({rb:#018x})");
-    };
-}
-
 #[test]
 fn test_num_f64() {
     super::test_num(10f64, 2f64);
@@ -41,14 +30,14 @@ fn test_num_f64() {
 
 #[test]
 fn test_min_nan() {
-    assert_eq!(f64::NAN.min(2.0), 2.0);
-    assert_eq!(2.0f64.min(f64::NAN), 2.0);
+    assert_biteq!(f64::NAN.min(2.0), 2.0);
+    assert_biteq!(2.0f64.min(f64::NAN), 2.0);
 }
 
 #[test]
 fn test_max_nan() {
-    assert_eq!(f64::NAN.max(2.0), 2.0);
-    assert_eq!(2.0f64.max(f64::NAN), 2.0);
+    assert_biteq!(f64::NAN.max(2.0), 2.0);
+    assert_biteq!(2.0f64.max(f64::NAN), 2.0);
 }
 
 #[test]
@@ -92,7 +81,7 @@ fn test_neg_infinity() {
 #[test]
 fn test_zero() {
     let zero: f64 = 0.0f64;
-    assert_eq!(0.0, zero);
+    assert_biteq!(0.0, zero);
     assert!(!zero.is_infinite());
     assert!(zero.is_finite());
     assert!(zero.is_sign_positive());
@@ -106,6 +95,7 @@ fn test_zero() {
 fn test_neg_zero() {
     let neg_zero: f64 = -0.0;
     assert_eq!(0.0, neg_zero);
+    assert_biteq!(-0.0, neg_zero);
     assert!(!neg_zero.is_infinite());
     assert!(neg_zero.is_finite());
     assert!(!neg_zero.is_sign_positive());
@@ -118,7 +108,7 @@ fn test_neg_zero() {
 #[test]
 fn test_one() {
     let one: f64 = 1.0f64;
-    assert_eq!(1.0, one);
+    assert_biteq!(1.0, one);
     assert!(!one.is_infinite());
     assert!(one.is_finite());
     assert!(one.is_sign_positive());
@@ -202,111 +192,111 @@ fn test_classify() {
 
 #[test]
 fn test_floor() {
-    assert_approx_eq!(f64::math::floor(1.0f64), 1.0f64);
-    assert_approx_eq!(f64::math::floor(1.3f64), 1.0f64);
-    assert_approx_eq!(f64::math::floor(1.5f64), 1.0f64);
-    assert_approx_eq!(f64::math::floor(1.7f64), 1.0f64);
-    assert_approx_eq!(f64::math::floor(0.0f64), 0.0f64);
-    assert_approx_eq!(f64::math::floor(-0.0f64), -0.0f64);
-    assert_approx_eq!(f64::math::floor(-1.0f64), -1.0f64);
-    assert_approx_eq!(f64::math::floor(-1.3f64), -2.0f64);
-    assert_approx_eq!(f64::math::floor(-1.5f64), -2.0f64);
-    assert_approx_eq!(f64::math::floor(-1.7f64), -2.0f64);
+    assert_biteq!(f64::math::floor(1.0f64), 1.0f64);
+    assert_biteq!(f64::math::floor(1.3f64), 1.0f64);
+    assert_biteq!(f64::math::floor(1.5f64), 1.0f64);
+    assert_biteq!(f64::math::floor(1.7f64), 1.0f64);
+    assert_biteq!(f64::math::floor(0.0f64), 0.0f64);
+    assert_biteq!(f64::math::floor(-0.0f64), -0.0f64);
+    assert_biteq!(f64::math::floor(-1.0f64), -1.0f64);
+    assert_biteq!(f64::math::floor(-1.3f64), -2.0f64);
+    assert_biteq!(f64::math::floor(-1.5f64), -2.0f64);
+    assert_biteq!(f64::math::floor(-1.7f64), -2.0f64);
 }
 
 #[test]
 fn test_ceil() {
-    assert_approx_eq!(f64::math::ceil(1.0f64), 1.0f64);
-    assert_approx_eq!(f64::math::ceil(1.3f64), 2.0f64);
-    assert_approx_eq!(f64::math::ceil(1.5f64), 2.0f64);
-    assert_approx_eq!(f64::math::ceil(1.7f64), 2.0f64);
-    assert_approx_eq!(f64::math::ceil(0.0f64), 0.0f64);
-    assert_approx_eq!(f64::math::ceil(-0.0f64), -0.0f64);
-    assert_approx_eq!(f64::math::ceil(-1.0f64), -1.0f64);
-    assert_approx_eq!(f64::math::ceil(-1.3f64), -1.0f64);
-    assert_approx_eq!(f64::math::ceil(-1.5f64), -1.0f64);
-    assert_approx_eq!(f64::math::ceil(-1.7f64), -1.0f64);
+    assert_biteq!(f64::math::ceil(1.0f64), 1.0f64);
+    assert_biteq!(f64::math::ceil(1.3f64), 2.0f64);
+    assert_biteq!(f64::math::ceil(1.5f64), 2.0f64);
+    assert_biteq!(f64::math::ceil(1.7f64), 2.0f64);
+    assert_biteq!(f64::math::ceil(0.0f64), 0.0f64);
+    assert_biteq!(f64::math::ceil(-0.0f64), -0.0f64);
+    assert_biteq!(f64::math::ceil(-1.0f64), -1.0f64);
+    assert_biteq!(f64::math::ceil(-1.3f64), -1.0f64);
+    assert_biteq!(f64::math::ceil(-1.5f64), -1.0f64);
+    assert_biteq!(f64::math::ceil(-1.7f64), -1.0f64);
 }
 
 #[test]
 fn test_round() {
-    assert_approx_eq!(f64::math::round(2.5f64), 3.0f64);
-    assert_approx_eq!(f64::math::round(1.0f64), 1.0f64);
-    assert_approx_eq!(f64::math::round(1.3f64), 1.0f64);
-    assert_approx_eq!(f64::math::round(1.5f64), 2.0f64);
-    assert_approx_eq!(f64::math::round(1.7f64), 2.0f64);
-    assert_approx_eq!(f64::math::round(0.0f64), 0.0f64);
-    assert_approx_eq!(f64::math::round(-0.0f64), -0.0f64);
-    assert_approx_eq!(f64::math::round(-1.0f64), -1.0f64);
-    assert_approx_eq!(f64::math::round(-1.3f64), -1.0f64);
-    assert_approx_eq!(f64::math::round(-1.5f64), -2.0f64);
-    assert_approx_eq!(f64::math::round(-1.7f64), -2.0f64);
+    assert_biteq!(f64::math::round(2.5f64), 3.0f64);
+    assert_biteq!(f64::math::round(1.0f64), 1.0f64);
+    assert_biteq!(f64::math::round(1.3f64), 1.0f64);
+    assert_biteq!(f64::math::round(1.5f64), 2.0f64);
+    assert_biteq!(f64::math::round(1.7f64), 2.0f64);
+    assert_biteq!(f64::math::round(0.0f64), 0.0f64);
+    assert_biteq!(f64::math::round(-0.0f64), -0.0f64);
+    assert_biteq!(f64::math::round(-1.0f64), -1.0f64);
+    assert_biteq!(f64::math::round(-1.3f64), -1.0f64);
+    assert_biteq!(f64::math::round(-1.5f64), -2.0f64);
+    assert_biteq!(f64::math::round(-1.7f64), -2.0f64);
 }
 
 #[test]
 fn test_round_ties_even() {
-    assert_approx_eq!(f64::math::round_ties_even(2.5f64), 2.0f64);
-    assert_approx_eq!(f64::math::round_ties_even(1.0f64), 1.0f64);
-    assert_approx_eq!(f64::math::round_ties_even(1.3f64), 1.0f64);
-    assert_approx_eq!(f64::math::round_ties_even(1.5f64), 2.0f64);
-    assert_approx_eq!(f64::math::round_ties_even(1.7f64), 2.0f64);
-    assert_approx_eq!(f64::math::round_ties_even(0.0f64), 0.0f64);
-    assert_approx_eq!(f64::math::round_ties_even(-0.0f64), -0.0f64);
-    assert_approx_eq!(f64::math::round_ties_even(-1.0f64), -1.0f64);
-    assert_approx_eq!(f64::math::round_ties_even(-1.3f64), -1.0f64);
-    assert_approx_eq!(f64::math::round_ties_even(-1.5f64), -2.0f64);
-    assert_approx_eq!(f64::math::round_ties_even(-1.7f64), -2.0f64);
+    assert_biteq!(f64::math::round_ties_even(2.5f64), 2.0f64);
+    assert_biteq!(f64::math::round_ties_even(1.0f64), 1.0f64);
+    assert_biteq!(f64::math::round_ties_even(1.3f64), 1.0f64);
+    assert_biteq!(f64::math::round_ties_even(1.5f64), 2.0f64);
+    assert_biteq!(f64::math::round_ties_even(1.7f64), 2.0f64);
+    assert_biteq!(f64::math::round_ties_even(0.0f64), 0.0f64);
+    assert_biteq!(f64::math::round_ties_even(-0.0f64), -0.0f64);
+    assert_biteq!(f64::math::round_ties_even(-1.0f64), -1.0f64);
+    assert_biteq!(f64::math::round_ties_even(-1.3f64), -1.0f64);
+    assert_biteq!(f64::math::round_ties_even(-1.5f64), -2.0f64);
+    assert_biteq!(f64::math::round_ties_even(-1.7f64), -2.0f64);
 }
 
 #[test]
 fn test_trunc() {
-    assert_approx_eq!(f64::math::trunc(1.0f64), 1.0f64);
-    assert_approx_eq!(f64::math::trunc(1.3f64), 1.0f64);
-    assert_approx_eq!(f64::math::trunc(1.5f64), 1.0f64);
-    assert_approx_eq!(f64::math::trunc(1.7f64), 1.0f64);
-    assert_approx_eq!(f64::math::trunc(0.0f64), 0.0f64);
-    assert_approx_eq!(f64::math::trunc(-0.0f64), -0.0f64);
-    assert_approx_eq!(f64::math::trunc(-1.0f64), -1.0f64);
-    assert_approx_eq!(f64::math::trunc(-1.3f64), -1.0f64);
-    assert_approx_eq!(f64::math::trunc(-1.5f64), -1.0f64);
-    assert_approx_eq!(f64::math::trunc(-1.7f64), -1.0f64);
+    assert_biteq!(f64::math::trunc(1.0f64), 1.0f64);
+    assert_biteq!(f64::math::trunc(1.3f64), 1.0f64);
+    assert_biteq!(f64::math::trunc(1.5f64), 1.0f64);
+    assert_biteq!(f64::math::trunc(1.7f64), 1.0f64);
+    assert_biteq!(f64::math::trunc(0.0f64), 0.0f64);
+    assert_biteq!(f64::math::trunc(-0.0f64), -0.0f64);
+    assert_biteq!(f64::math::trunc(-1.0f64), -1.0f64);
+    assert_biteq!(f64::math::trunc(-1.3f64), -1.0f64);
+    assert_biteq!(f64::math::trunc(-1.5f64), -1.0f64);
+    assert_biteq!(f64::math::trunc(-1.7f64), -1.0f64);
 }
 
 #[test]
 fn test_fract() {
-    assert_approx_eq!(f64::math::fract(1.0f64), 0.0f64);
-    assert_approx_eq!(f64::math::fract(1.3f64), 0.3f64);
-    assert_approx_eq!(f64::math::fract(1.5f64), 0.5f64);
-    assert_approx_eq!(f64::math::fract(1.7f64), 0.7f64);
-    assert_approx_eq!(f64::math::fract(0.0f64), 0.0f64);
-    assert_approx_eq!(f64::math::fract(-0.0f64), -0.0f64);
-    assert_approx_eq!(f64::math::fract(-1.0f64), -0.0f64);
-    assert_approx_eq!(f64::math::fract(-1.3f64), -0.3f64);
-    assert_approx_eq!(f64::math::fract(-1.5f64), -0.5f64);
-    assert_approx_eq!(f64::math::fract(-1.7f64), -0.7f64);
+    assert_biteq!(f64::math::fract(1.0f64), 0.0f64);
+    assert_biteq!(f64::math::fract(1.3f64), 0.30000000000000004f64);
+    assert_biteq!(f64::math::fract(1.5f64), 0.5f64);
+    assert_biteq!(f64::math::fract(1.7f64), 0.7f64);
+    assert_biteq!(f64::math::fract(0.0f64), 0.0f64);
+    assert_biteq!(f64::math::fract(-0.0f64), 0.0f64);
+    assert_biteq!(f64::math::fract(-1.0f64), 0.0f64);
+    assert_biteq!(f64::math::fract(-1.3f64), -0.30000000000000004f64);
+    assert_biteq!(f64::math::fract(-1.5f64), -0.5f64);
+    assert_biteq!(f64::math::fract(-1.7f64), -0.69999999999999996f64);
 }
 
 #[test]
 fn test_abs() {
-    assert_eq!(f64::INFINITY.abs(), f64::INFINITY);
-    assert_eq!(1f64.abs(), 1f64);
-    assert_eq!(0f64.abs(), 0f64);
-    assert_eq!((-0f64).abs(), 0f64);
-    assert_eq!((-1f64).abs(), 1f64);
-    assert_eq!(f64::NEG_INFINITY.abs(), f64::INFINITY);
-    assert_eq!((1f64 / f64::NEG_INFINITY).abs(), 0f64);
+    assert_biteq!(f64::INFINITY.abs(), f64::INFINITY);
+    assert_biteq!(1f64.abs(), 1f64);
+    assert_biteq!(0f64.abs(), 0f64);
+    assert_biteq!((-0f64).abs(), 0f64);
+    assert_biteq!((-1f64).abs(), 1f64);
+    assert_biteq!(f64::NEG_INFINITY.abs(), f64::INFINITY);
+    assert_biteq!((1f64 / f64::NEG_INFINITY).abs(), 0f64);
     assert!(f64::NAN.abs().is_nan());
 }
 
 #[test]
 fn test_signum() {
-    assert_eq!(f64::INFINITY.signum(), 1f64);
-    assert_eq!(1f64.signum(), 1f64);
-    assert_eq!(0f64.signum(), 1f64);
-    assert_eq!((-0f64).signum(), -1f64);
-    assert_eq!((-1f64).signum(), -1f64);
-    assert_eq!(f64::NEG_INFINITY.signum(), -1f64);
-    assert_eq!((1f64 / f64::NEG_INFINITY).signum(), -1f64);
+    assert_biteq!(f64::INFINITY.signum(), 1f64);
+    assert_biteq!(1f64.signum(), 1f64);
+    assert_biteq!(0f64.signum(), 1f64);
+    assert_biteq!((-0f64).signum(), -1f64);
+    assert_biteq!((-1f64).signum(), -1f64);
+    assert_biteq!(f64::NEG_INFINITY.signum(), -1f64);
+    assert_biteq!((1f64 / f64::NEG_INFINITY).signum(), -1f64);
     assert!(f64::NAN.signum().is_nan());
 }
 
@@ -343,26 +333,26 @@ fn test_next_up() {
     let max_down = f64::from_bits(MAX_DOWN_BITS);
     let largest_subnormal = f64::from_bits(LARGEST_SUBNORMAL_BITS);
     let smallest_normal = f64::from_bits(SMALLEST_NORMAL_BITS);
-    assert_f64_biteq!(f64::NEG_INFINITY.next_up(), f64::MIN);
-    assert_f64_biteq!(f64::MIN.next_up(), -max_down);
-    assert_f64_biteq!((-1.0 - f64::EPSILON).next_up(), -1.0);
-    assert_f64_biteq!((-smallest_normal).next_up(), -largest_subnormal);
-    assert_f64_biteq!((-tiny_up).next_up(), -tiny);
-    assert_f64_biteq!((-tiny).next_up(), -0.0f64);
-    assert_f64_biteq!((-0.0f64).next_up(), tiny);
-    assert_f64_biteq!(0.0f64.next_up(), tiny);
-    assert_f64_biteq!(tiny.next_up(), tiny_up);
-    assert_f64_biteq!(largest_subnormal.next_up(), smallest_normal);
-    assert_f64_biteq!(1.0f64.next_up(), 1.0 + f64::EPSILON);
-    assert_f64_biteq!(f64::MAX.next_up(), f64::INFINITY);
-    assert_f64_biteq!(f64::INFINITY.next_up(), f64::INFINITY);
+    assert_biteq!(f64::NEG_INFINITY.next_up(), f64::MIN);
+    assert_biteq!(f64::MIN.next_up(), -max_down);
+    assert_biteq!((-1.0 - f64::EPSILON).next_up(), -1.0f64);
+    assert_biteq!((-smallest_normal).next_up(), -largest_subnormal);
+    assert_biteq!((-tiny_up).next_up(), -tiny);
+    assert_biteq!((-tiny).next_up(), -0.0f64);
+    assert_biteq!((-0.0f64).next_up(), tiny);
+    assert_biteq!(0.0f64.next_up(), tiny);
+    assert_biteq!(tiny.next_up(), tiny_up);
+    assert_biteq!(largest_subnormal.next_up(), smallest_normal);
+    assert_biteq!(1.0f64.next_up(), 1.0 + f64::EPSILON);
+    assert_biteq!(f64::MAX.next_up(), f64::INFINITY);
+    assert_biteq!(f64::INFINITY.next_up(), f64::INFINITY);
 
     let nan0 = f64::NAN;
     let nan1 = f64::from_bits(f64::NAN.to_bits() ^ NAN_MASK1);
     let nan2 = f64::from_bits(f64::NAN.to_bits() ^ NAN_MASK2);
-    assert_f64_biteq!(nan0.next_up(), nan0);
-    assert_f64_biteq!(nan1.next_up(), nan1);
-    assert_f64_biteq!(nan2.next_up(), nan2);
+    assert_biteq!(nan0.next_up(), nan0);
+    assert_biteq!(nan1.next_up(), nan1);
+    assert_biteq!(nan2.next_up(), nan2);
 }
 
 #[test]
@@ -372,27 +362,27 @@ fn test_next_down() {
     let max_down = f64::from_bits(MAX_DOWN_BITS);
     let largest_subnormal = f64::from_bits(LARGEST_SUBNORMAL_BITS);
     let smallest_normal = f64::from_bits(SMALLEST_NORMAL_BITS);
-    assert_f64_biteq!(f64::NEG_INFINITY.next_down(), f64::NEG_INFINITY);
-    assert_f64_biteq!(f64::MIN.next_down(), f64::NEG_INFINITY);
-    assert_f64_biteq!((-max_down).next_down(), f64::MIN);
-    assert_f64_biteq!((-1.0f64).next_down(), -1.0 - f64::EPSILON);
-    assert_f64_biteq!((-largest_subnormal).next_down(), -smallest_normal);
-    assert_f64_biteq!((-tiny).next_down(), -tiny_up);
-    assert_f64_biteq!((-0.0f64).next_down(), -tiny);
-    assert_f64_biteq!((0.0f64).next_down(), -tiny);
-    assert_f64_biteq!(tiny.next_down(), 0.0f64);
-    assert_f64_biteq!(tiny_up.next_down(), tiny);
-    assert_f64_biteq!(smallest_normal.next_down(), largest_subnormal);
-    assert_f64_biteq!((1.0 + f64::EPSILON).next_down(), 1.0f64);
-    assert_f64_biteq!(f64::MAX.next_down(), max_down);
-    assert_f64_biteq!(f64::INFINITY.next_down(), f64::MAX);
+    assert_biteq!(f64::NEG_INFINITY.next_down(), f64::NEG_INFINITY);
+    assert_biteq!(f64::MIN.next_down(), f64::NEG_INFINITY);
+    assert_biteq!((-max_down).next_down(), f64::MIN);
+    assert_biteq!((-1.0f64).next_down(), -1.0 - f64::EPSILON);
+    assert_biteq!((-largest_subnormal).next_down(), -smallest_normal);
+    assert_biteq!((-tiny).next_down(), -tiny_up);
+    assert_biteq!((-0.0f64).next_down(), -tiny);
+    assert_biteq!((0.0f64).next_down(), -tiny);
+    assert_biteq!(tiny.next_down(), 0.0f64);
+    assert_biteq!(tiny_up.next_down(), tiny);
+    assert_biteq!(smallest_normal.next_down(), largest_subnormal);
+    assert_biteq!((1.0 + f64::EPSILON).next_down(), 1.0f64);
+    assert_biteq!(f64::MAX.next_down(), max_down);
+    assert_biteq!(f64::INFINITY.next_down(), f64::MAX);
 
     let nan0 = f64::NAN;
     let nan1 = f64::from_bits(f64::NAN.to_bits() ^ NAN_MASK1);
     let nan2 = f64::from_bits(f64::NAN.to_bits() ^ NAN_MASK2);
-    assert_f64_biteq!(nan0.next_down(), nan0);
-    assert_f64_biteq!(nan1.next_down(), nan1);
-    assert_f64_biteq!(nan2.next_down(), nan2);
+    assert_biteq!(nan0.next_down(), nan0);
+    assert_biteq!(nan1.next_down(), nan1);
+    assert_biteq!(nan2.next_down(), nan2);
 }
 
 // FIXME(#140515): mingw has an incorrect fma https://sourceforge.net/p/mingw-w64/bugs/848/
@@ -402,15 +392,15 @@ fn test_mul_add() {
     let nan: f64 = f64::NAN;
     let inf: f64 = f64::INFINITY;
     let neg_inf: f64 = f64::NEG_INFINITY;
-    assert_approx_eq!(12.3f64.mul_add(4.5, 6.7), 62.05);
-    assert_approx_eq!((-12.3f64).mul_add(-4.5, -6.7), 48.65);
-    assert_approx_eq!(0.0f64.mul_add(8.9, 1.2), 1.2);
-    assert_approx_eq!(3.4f64.mul_add(-0.0, 5.6), 5.6);
+    assert_biteq!(12.3f64.mul_add(4.5, 6.7), 62.050000000000004);
+    assert_biteq!((-12.3f64).mul_add(-4.5, -6.7), 48.650000000000006);
+    assert_biteq!(0.0f64.mul_add(8.9, 1.2), 1.2);
+    assert_biteq!(3.4f64.mul_add(-0.0, 5.6), 5.6);
     assert!(nan.mul_add(7.8, 9.0).is_nan());
-    assert_eq!(inf.mul_add(7.8, 9.0), inf);
-    assert_eq!(neg_inf.mul_add(7.8, 9.0), neg_inf);
-    assert_eq!(8.9f64.mul_add(inf, 3.2), inf);
-    assert_eq!((-3.2f64).mul_add(2.4, neg_inf), neg_inf);
+    assert_biteq!(inf.mul_add(7.8, 9.0), inf);
+    assert_biteq!(neg_inf.mul_add(7.8, 9.0), neg_inf);
+    assert_biteq!(8.9f64.mul_add(inf, 3.2), inf);
+    assert_biteq!((-3.2f64).mul_add(2.4, neg_inf), neg_inf);
 }
 
 #[test]
@@ -418,13 +408,13 @@ fn test_recip() {
     let nan: f64 = f64::NAN;
     let inf: f64 = f64::INFINITY;
     let neg_inf: f64 = f64::NEG_INFINITY;
-    assert_eq!(1.0f64.recip(), 1.0);
-    assert_eq!(2.0f64.recip(), 0.5);
-    assert_eq!((-0.4f64).recip(), -2.5);
-    assert_eq!(0.0f64.recip(), inf);
+    assert_biteq!(1.0f64.recip(), 1.0);
+    assert_biteq!(2.0f64.recip(), 0.5);
+    assert_biteq!((-0.4f64).recip(), -2.5);
+    assert_biteq!(0.0f64.recip(), inf);
     assert!(nan.recip().is_nan());
-    assert_eq!(inf.recip(), 0.0);
-    assert_eq!(neg_inf.recip(), 0.0);
+    assert_biteq!(inf.recip(), 0.0);
+    assert_biteq!(neg_inf.recip(), -0.0);
 }
 
 #[test]
@@ -432,13 +422,13 @@ fn test_powi() {
     let nan: f64 = f64::NAN;
     let inf: f64 = f64::INFINITY;
     let neg_inf: f64 = f64::NEG_INFINITY;
-    assert_eq!(1.0f64.powi(1), 1.0);
+    assert_biteq!(1.0f64.powi(1), 1.0);
     assert_approx_eq!((-3.1f64).powi(2), 9.61);
     assert_approx_eq!(5.9f64.powi(-2), 0.028727);
-    assert_eq!(8.3f64.powi(0), 1.0);
+    assert_biteq!(8.3f64.powi(0), 1.0);
     assert!(nan.powi(2).is_nan());
-    assert_eq!(inf.powi(3), inf);
-    assert_eq!(neg_inf.powi(2), inf);
+    assert_biteq!(inf.powi(3), inf);
+    assert_biteq!(neg_inf.powi(2), inf);
 }
 
 #[test]
@@ -446,10 +436,10 @@ fn test_sqrt_domain() {
     assert!(f64::NAN.sqrt().is_nan());
     assert!(f64::NEG_INFINITY.sqrt().is_nan());
     assert!((-1.0f64).sqrt().is_nan());
-    assert_eq!((-0.0f64).sqrt(), -0.0);
-    assert_eq!(0.0f64.sqrt(), 0.0);
-    assert_eq!(1.0f64.sqrt(), 1.0);
-    assert_eq!(f64::INFINITY.sqrt(), f64::INFINITY);
+    assert_biteq!((-0.0f64).sqrt(), -0.0);
+    assert_biteq!(0.0f64.sqrt(), 0.0);
+    assert_biteq!(1.0f64.sqrt(), 1.0);
+    assert_biteq!(f64::INFINITY.sqrt(), f64::INFINITY);
 }
 
 #[test]
@@ -458,12 +448,12 @@ fn test_to_degrees() {
     let nan: f64 = f64::NAN;
     let inf: f64 = f64::INFINITY;
     let neg_inf: f64 = f64::NEG_INFINITY;
-    assert_eq!(0.0f64.to_degrees(), 0.0);
+    assert_biteq!(0.0f64.to_degrees(), 0.0);
     assert_approx_eq!((-5.8f64).to_degrees(), -332.315521);
-    assert_eq!(pi.to_degrees(), 180.0);
+    assert_biteq!(pi.to_degrees(), 180.0);
     assert!(nan.to_degrees().is_nan());
-    assert_eq!(inf.to_degrees(), inf);
-    assert_eq!(neg_inf.to_degrees(), neg_inf);
+    assert_biteq!(inf.to_degrees(), inf);
+    assert_biteq!(neg_inf.to_degrees(), neg_inf);
 }
 
 #[test]
@@ -472,13 +462,13 @@ fn test_to_radians() {
     let nan: f64 = f64::NAN;
     let inf: f64 = f64::INFINITY;
     let neg_inf: f64 = f64::NEG_INFINITY;
-    assert_eq!(0.0f64.to_radians(), 0.0);
+    assert_biteq!(0.0f64.to_radians(), 0.0);
     assert_approx_eq!(154.6f64.to_radians(), 2.698279);
     assert_approx_eq!((-332.31f64).to_radians(), -5.799903);
-    assert_eq!(180.0f64.to_radians(), pi);
+    assert_biteq!(180.0f64.to_radians(), pi);
     assert!(nan.to_radians().is_nan());
-    assert_eq!(inf.to_radians(), inf);
-    assert_eq!(neg_inf.to_radians(), neg_inf);
+    assert_biteq!(inf.to_radians(), inf);
+    assert_biteq!(neg_inf.to_radians(), neg_inf);
 }
 
 #[test]
@@ -487,10 +477,10 @@ fn test_float_bits_conv() {
     assert_eq!((12.5f64).to_bits(), 0x4029000000000000);
     assert_eq!((1337f64).to_bits(), 0x4094e40000000000);
     assert_eq!((-14.25f64).to_bits(), 0xc02c800000000000);
-    assert_approx_eq!(f64::from_bits(0x3ff0000000000000), 1.0);
-    assert_approx_eq!(f64::from_bits(0x4029000000000000), 12.5);
-    assert_approx_eq!(f64::from_bits(0x4094e40000000000), 1337.0);
-    assert_approx_eq!(f64::from_bits(0xc02c800000000000), -14.25);
+    assert_biteq!(f64::from_bits(0x3ff0000000000000), 1.0);
+    assert_biteq!(f64::from_bits(0x4029000000000000), 12.5);
+    assert_biteq!(f64::from_bits(0x4094e40000000000), 1337.0);
+    assert_biteq!(f64::from_bits(0xc02c800000000000), -14.25);
 
     // Check that NaNs roundtrip their bits regardless of signaling-ness
     let masked_nan1 = f64::NAN.to_bits() ^ NAN_MASK1;
diff --git a/library/coretests/tests/floats/mod.rs b/library/coretests/tests/floats/mod.rs
index 7de34271ad0..7e27028a2a2 100644
--- a/library/coretests/tests/floats/mod.rs
+++ b/library/coretests/tests/floats/mod.rs
@@ -15,6 +15,43 @@ macro_rules! assert_approx_eq {
     }};
 }
 
+/// Verify that floats have the same bitwise representation. Used to avoid the default `0.0 == -0.0`
+/// behavior, as well as to ensure exact NaN bitpatterns.
+macro_rules! assert_biteq {
+    (@inner $left:expr, $right:expr, $msg_sep:literal, $($tt:tt)*) => {{
+        let l = $left;
+        let r = $right;
+
+        // Hack to coerce left and right to the same type
+        let mut _eq_ty = l;
+        _eq_ty = r;
+
+        // Hack to get the width from a value
+        let bits = (l.to_bits() - l.to_bits()).leading_zeros();
+        assert!(
+            l.to_bits() == r.to_bits(),
+            "{msg}{nl}l: {l:?} ({lb:#0width$x})\nr: {r:?} ({rb:#0width$x})",
+            msg = format_args!($($tt)*),
+            nl = $msg_sep,
+            lb = l.to_bits(),
+            rb = r.to_bits(),
+            width = ((bits / 4) + 2) as usize,
+        );
+
+        if !l.is_nan() && !r.is_nan() {
+            // Also check that standard equality holds, since most tests use `assert_biteq` rather
+            // than `assert_eq`.
+            assert_eq!(l, r)
+        }
+    }};
+    ($left:expr, $right:expr , $($tt:tt)*) => {
+        assert_biteq!(@inner $left, $right, "\n", $($tt)*)
+    };
+    ($left:expr, $right:expr $(,)?) => {
+        assert_biteq!(@inner $left, $right, "", "")
+    };
+}
+
 /// Helper function for testing numeric operations
 pub fn test_num<T>(ten: T, two: T)
 where