about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJacob Pratt <jacob@jhpratt.dev>2025-06-07 07:05:46 +0200
committerGitHub <noreply@github.com>2025-06-07 07:05:46 +0200
commit0d2bf86284c257f42949be172dc802bfe0493d26 (patch)
treeb10e0a52393fa36aebad7b327982d86923c8407e
parent1c8b09639caf2a9a0cfc73a96142ebe3d2952729 (diff)
parent7742d0e230b602a0a73d38b32de47449f3306450 (diff)
downloadrust-0d2bf86284c257f42949be172dc802bfe0493d26.tar.gz
rust-0d2bf86284c257f42949be172dc802bfe0493d26.zip
Rollup merge of #141857 - RalfJung:coretests-floats, r=tgross35
coretests: move float tests from num to floats module and use a more flexible macro to generate them

This makes some progress on https://github.com/rust-lang/rust/issues/141726 by moving the float tests in `num` to `floats` and using a newer, more flexible macro to generate them. We also newly run these tests on f16 and f128 in const, and at runtime in Miri and for hosts where that works well enough.

I didn't yet deduplicate any tests or port the existing `floats::f*` tests to the macro, that can happen in a future PR.

try-job: x86_64-gnu-aux
-rw-r--r--library/coretests/tests/floats/mod.rs548
-rw-r--r--library/coretests/tests/num/mod.rs353
2 files changed, 548 insertions, 353 deletions
diff --git a/library/coretests/tests/floats/mod.rs b/library/coretests/tests/floats/mod.rs
index 7e27028a2a2..f9b6c85f871 100644
--- a/library/coretests/tests/floats/mod.rs
+++ b/library/coretests/tests/floats/mod.rs
@@ -52,6 +52,119 @@ macro_rules! assert_biteq {
     };
 }
 
+mod const_asserts {
+    // Shadow some assert implementations that would otherwise not compile in a const-context.
+    // Every macro added here also needs to be added in the `float_test!` macro below.
+    macro_rules! assert_eq {
+        ($left:expr, $right:expr $(,)?) => {
+            std::assert!($left == $right)
+        };
+        ($left:expr, $right:expr, $($arg:tt)+) => {
+            std::assert!($left == $right, $($arg)+)
+        };
+    }
+
+    pub(crate) use assert_eq;
+}
+
+/// Generate float tests for all our float types, for compile-time and run-time behavior.
+///
+/// By default all tests run for all float types. Configuration can be applied via `attrs`.
+///
+/// ```ignore (this is only a sketch)
+/// float_test! {
+///     name: fn_name, /* function under test */
+///     attrs: {
+///         // Apply a configuration to the test for a single type
+///         f16: #[cfg(target_has_reliable_f16_math)],
+///         // Types can be excluded with `cfg(false)`
+///         f64: #[cfg(false)],
+///     },
+///     test<Float> {
+///         /* write tests here, using `Float` as the type */
+///     }
+/// }
+macro_rules! float_test {
+    (
+        name: $name:ident,
+        attrs: {
+            $(const: #[ $($const_meta:meta),+ ] ,)?
+            $(f16: #[ $($f16_meta:meta),+ ] ,)?
+            $(const f16: #[ $($f16_const_meta:meta),+ ] ,)?
+            $(f32: #[ $($f32_meta:meta),+ ] ,)?
+            $(const f32: #[ $($f32_const_meta:meta),+ ] ,)?
+            $(f64: #[ $($f64_meta:meta),+ ] ,)?
+            $(const f64: #[ $($f64_const_meta:meta),+ ] ,)?
+            $(f128: #[ $($f128_meta:meta),+ ] ,)?
+            $(const f128: #[ $($f128_const_meta:meta),+ ] ,)?
+        },
+        test<$fty:ident> $test:block
+    ) => {
+        mod $name {
+            #[test]
+            $( $( #[$f16_meta] )+ )?
+            fn test_f16() {
+                type $fty = f16;
+                $test
+            }
+
+            #[test]
+            $( $( #[$f32_meta] )+ )?
+            fn test_f32() {
+                type $fty = f32;
+                $test
+            }
+
+            #[test]
+            $( $( #[$f64_meta] )+ )?
+            fn test_f64() {
+                type $fty = f64;
+                $test
+            }
+
+            #[test]
+            $( $( #[$f128_meta] )+ )?
+            fn test_f128() {
+                type $fty = f128;
+                $test
+            }
+
+            $( $( #[$const_meta] )+ )?
+            mod const_ {
+                use $crate::floats::const_asserts::assert_eq;
+
+                #[test]
+                $( $( #[$f16_const_meta] )+ )?
+                fn test_f16() {
+                    type $fty = f16;
+                    const { $test }
+                }
+
+                #[test]
+                $( $( #[$f32_const_meta] )+ )?
+                fn test_f32() {
+                    type $fty = f32;
+                    const { $test }
+                }
+
+                #[test]
+                $( $( #[$f64_const_meta] )+ )?
+                fn test_f64() {
+                    type $fty = f64;
+                    const { $test }
+                }
+
+                #[test]
+                $( $( #[$f128_const_meta] )+ )?
+                fn test_f128() {
+                    type $fty = f128;
+                    const { $test }
+                }
+            }
+        }
+    };
+}
+
 /// Helper function for testing numeric operations
 pub fn test_num<T>(ten: T, two: T)
 where
@@ -75,3 +188,438 @@ mod f128;
 mod f16;
 mod f32;
 mod f64;
+
+float_test! {
+    name: min,
+    attrs: {
+        f16: #[cfg(any(miri, target_has_reliable_f16_math))],
+        f128: #[cfg(any(miri, target_has_reliable_f128_math))],
+    },
+    test<Float> {
+        assert_eq!((0.0 as Float).min(0.0), 0.0);
+        assert!((0.0 as Float).min(0.0).is_sign_positive());
+        assert_eq!((-0.0 as Float).min(-0.0), -0.0);
+        assert!((-0.0 as Float).min(-0.0).is_sign_negative());
+        assert_eq!((9.0 as Float).min(9.0), 9.0);
+        assert_eq!((-9.0 as Float).min(0.0), -9.0);
+        assert_eq!((0.0 as Float).min(9.0), 0.0);
+        assert!((0.0 as Float).min(9.0).is_sign_positive());
+        assert_eq!((-0.0 as Float).min(9.0), -0.0);
+        assert!((-0.0 as Float).min(9.0).is_sign_negative());
+        assert_eq!((-0.0 as Float).min(-9.0), -9.0);
+        assert_eq!(Float::INFINITY.min(9.0), 9.0);
+        assert_eq!((9.0 as Float).min(Float::INFINITY), 9.0);
+        assert_eq!(Float::INFINITY.min(-9.0), -9.0);
+        assert_eq!((-9.0 as Float).min(Float::INFINITY), -9.0);
+        assert_eq!(Float::NEG_INFINITY.min(9.0), Float::NEG_INFINITY);
+        assert_eq!((9.0 as Float).min(Float::NEG_INFINITY), Float::NEG_INFINITY);
+        assert_eq!(Float::NEG_INFINITY.min(-9.0), Float::NEG_INFINITY);
+        assert_eq!((-9.0 as Float).min(Float::NEG_INFINITY), Float::NEG_INFINITY);
+        assert_eq!(Float::NAN.min(9.0), 9.0);
+        assert_eq!(Float::NAN.min(-9.0), -9.0);
+        assert_eq!((9.0 as Float).min(Float::NAN), 9.0);
+        assert_eq!((-9.0 as Float).min(Float::NAN), -9.0);
+        assert!(Float::NAN.min(Float::NAN).is_nan());
+    }
+}
+
+float_test! {
+    name: max,
+    attrs: {
+        f16: #[cfg(any(miri, target_has_reliable_f16_math))],
+        f128: #[cfg(any(miri, target_has_reliable_f128_math))],
+    },
+    test<Float> {
+        assert_eq!((0.0 as Float).max(0.0), 0.0);
+        assert!((0.0 as Float).max(0.0).is_sign_positive());
+        assert_eq!((-0.0 as Float).max(-0.0), -0.0);
+        assert!((-0.0 as Float).max(-0.0).is_sign_negative());
+        assert_eq!((9.0 as Float).max(9.0), 9.0);
+        assert_eq!((-9.0 as Float).max(0.0), 0.0);
+        assert!((-9.0 as Float).max(0.0).is_sign_positive());
+        assert_eq!((-9.0 as Float).max(-0.0), -0.0);
+        assert!((-9.0 as Float).max(-0.0).is_sign_negative());
+        assert_eq!((0.0 as Float).max(9.0), 9.0);
+        assert_eq!((0.0 as Float).max(-9.0), 0.0);
+        assert!((0.0 as Float).max(-9.0).is_sign_positive());
+        assert_eq!((-0.0 as Float).max(-9.0), -0.0);
+        assert!((-0.0 as Float).max(-9.0).is_sign_negative());
+        assert_eq!(Float::INFINITY.max(9.0), Float::INFINITY);
+        assert_eq!((9.0 as Float).max(Float::INFINITY), Float::INFINITY);
+        assert_eq!(Float::INFINITY.max(-9.0), Float::INFINITY);
+        assert_eq!((-9.0 as Float).max(Float::INFINITY), Float::INFINITY);
+        assert_eq!(Float::NEG_INFINITY.max(9.0), 9.0);
+        assert_eq!((9.0 as Float).max(Float::NEG_INFINITY), 9.0);
+        assert_eq!(Float::NEG_INFINITY.max(-9.0), -9.0);
+        assert_eq!((-9.0 as Float).max(Float::NEG_INFINITY), -9.0);
+        assert_eq!(Float::NAN.max(9.0), 9.0);
+        assert_eq!(Float::NAN.max(-9.0), -9.0);
+        assert_eq!((9.0 as Float).max(Float::NAN), 9.0);
+        assert_eq!((-9.0 as Float).max(Float::NAN), -9.0);
+        assert!(Float::NAN.max(Float::NAN).is_nan());
+    }
+}
+
+float_test! {
+    name: minimum,
+    attrs: {
+        f16: #[cfg(any(miri, target_has_reliable_f16_math))],
+        f128: #[cfg(any(miri, target_has_reliable_f128_math))],
+    },
+    test<Float> {
+        assert_eq!((0.0 as Float).minimum(0.0), 0.0);
+        assert!((0.0 as Float).minimum(0.0).is_sign_positive());
+        assert_eq!((-0.0 as Float).minimum(0.0), -0.0);
+        assert!((-0.0 as Float).minimum(0.0).is_sign_negative());
+        assert_eq!((-0.0 as Float).minimum(-0.0), -0.0);
+        assert!((-0.0 as Float).minimum(-0.0).is_sign_negative());
+        assert_eq!((9.0 as Float).minimum(9.0), 9.0);
+        assert_eq!((-9.0 as Float).minimum(0.0), -9.0);
+        assert_eq!((0.0 as Float).minimum(9.0), 0.0);
+        assert!((0.0 as Float).minimum(9.0).is_sign_positive());
+        assert_eq!((-0.0 as Float).minimum(9.0), -0.0);
+        assert!((-0.0 as Float).minimum(9.0).is_sign_negative());
+        assert_eq!((-0.0 as Float).minimum(-9.0), -9.0);
+        assert_eq!(Float::INFINITY.minimum(9.0), 9.0);
+        assert_eq!((9.0 as Float).minimum(Float::INFINITY), 9.0);
+        assert_eq!(Float::INFINITY.minimum(-9.0), -9.0);
+        assert_eq!((-9.0 as Float).minimum(Float::INFINITY), -9.0);
+        assert_eq!(Float::NEG_INFINITY.minimum(9.0), Float::NEG_INFINITY);
+        assert_eq!((9.0 as Float).minimum(Float::NEG_INFINITY), Float::NEG_INFINITY);
+        assert_eq!(Float::NEG_INFINITY.minimum(-9.0), Float::NEG_INFINITY);
+        assert_eq!((-9.0 as Float).minimum(Float::NEG_INFINITY), Float::NEG_INFINITY);
+        assert!(Float::NAN.minimum(9.0).is_nan());
+        assert!(Float::NAN.minimum(-9.0).is_nan());
+        assert!((9.0 as Float).minimum(Float::NAN).is_nan());
+        assert!((-9.0 as Float).minimum(Float::NAN).is_nan());
+        assert!(Float::NAN.minimum(Float::NAN).is_nan());
+    }
+}
+
+float_test! {
+    name: maximum,
+    attrs: {
+        f16: #[cfg(any(miri, target_has_reliable_f16_math))],
+        f128: #[cfg(any(miri, target_has_reliable_f128_math))],
+    },
+    test<Float> {
+        assert_eq!((0.0 as Float).maximum(0.0), 0.0);
+        assert!((0.0 as Float).maximum(0.0).is_sign_positive());
+        assert_eq!((-0.0 as Float).maximum(0.0), 0.0);
+        assert!((-0.0 as Float).maximum(0.0).is_sign_positive());
+        assert_eq!((-0.0 as Float).maximum(-0.0), -0.0);
+        assert!((-0.0 as Float).maximum(-0.0).is_sign_negative());
+        assert_eq!((9.0 as Float).maximum(9.0), 9.0);
+        assert_eq!((-9.0 as Float).maximum(0.0), 0.0);
+        assert!((-9.0 as Float).maximum(0.0).is_sign_positive());
+        assert_eq!((-9.0 as Float).maximum(-0.0), -0.0);
+        assert!((-9.0 as Float).maximum(-0.0).is_sign_negative());
+        assert_eq!((0.0 as Float).maximum(9.0), 9.0);
+        assert_eq!((0.0 as Float).maximum(-9.0), 0.0);
+        assert!((0.0 as Float).maximum(-9.0).is_sign_positive());
+        assert_eq!((-0.0 as Float).maximum(-9.0), -0.0);
+        assert!((-0.0 as Float).maximum(-9.0).is_sign_negative());
+        assert_eq!(Float::INFINITY.maximum(9.0), Float::INFINITY);
+        assert_eq!((9.0 as Float).maximum(Float::INFINITY), Float::INFINITY);
+        assert_eq!(Float::INFINITY.maximum(-9.0), Float::INFINITY);
+        assert_eq!((-9.0 as Float).maximum(Float::INFINITY), Float::INFINITY);
+        assert_eq!(Float::NEG_INFINITY.maximum(9.0), 9.0);
+        assert_eq!((9.0 as Float).maximum(Float::NEG_INFINITY), 9.0);
+        assert_eq!(Float::NEG_INFINITY.maximum(-9.0), -9.0);
+        assert_eq!((-9.0 as Float).maximum(Float::NEG_INFINITY), -9.0);
+        assert!(Float::NAN.maximum(9.0).is_nan());
+        assert!(Float::NAN.maximum(-9.0).is_nan());
+        assert!((9.0 as Float).maximum(Float::NAN).is_nan());
+        assert!((-9.0 as Float).maximum(Float::NAN).is_nan());
+        assert!(Float::NAN.maximum(Float::NAN).is_nan());
+    }
+}
+
+float_test! {
+    name: midpoint,
+    attrs: {
+        f16: #[cfg(any(miri, target_has_reliable_f16_math))],
+        f128: #[cfg(any(miri, target_has_reliable_f128_math))],
+    },
+    test<Float> {
+        assert_eq!((0.5 as Float).midpoint(0.5), 0.5);
+        assert_eq!((0.5 as Float).midpoint(2.5), 1.5);
+        assert_eq!((3.0 as Float).midpoint(4.0), 3.5);
+        assert_eq!((-3.0 as Float).midpoint(4.0), 0.5);
+        assert_eq!((3.0 as Float).midpoint(-4.0), -0.5);
+        assert_eq!((-3.0 as Float).midpoint(-4.0), -3.5);
+        assert_eq!((0.0 as Float).midpoint(0.0), 0.0);
+        assert_eq!((-0.0 as Float).midpoint(-0.0), -0.0);
+        assert_eq!((-5.0 as Float).midpoint(5.0), 0.0);
+        assert_eq!(Float::MAX.midpoint(Float::MIN), 0.0);
+        assert_eq!(Float::MIN.midpoint(Float::MAX), -0.0);
+        assert_eq!(Float::MAX.midpoint(Float::MIN_POSITIVE), Float::MAX / 2.);
+        assert_eq!((-Float::MAX).midpoint(Float::MIN_POSITIVE), -Float::MAX / 2.);
+        assert_eq!(Float::MAX.midpoint(-Float::MIN_POSITIVE), Float::MAX / 2.);
+        assert_eq!((-Float::MAX).midpoint(-Float::MIN_POSITIVE), -Float::MAX / 2.);
+        assert_eq!((Float::MIN_POSITIVE).midpoint(Float::MAX), Float::MAX / 2.);
+        assert_eq!((Float::MIN_POSITIVE).midpoint(-Float::MAX), -Float::MAX / 2.);
+        assert_eq!((-Float::MIN_POSITIVE).midpoint(Float::MAX), Float::MAX / 2.);
+        assert_eq!((-Float::MIN_POSITIVE).midpoint(-Float::MAX), -Float::MAX / 2.);
+        assert_eq!(Float::MAX.midpoint(Float::MAX), Float::MAX);
+        assert_eq!(
+            (Float::MIN_POSITIVE).midpoint(Float::MIN_POSITIVE),
+            Float::MIN_POSITIVE
+        );
+        assert_eq!(
+            (-Float::MIN_POSITIVE).midpoint(-Float::MIN_POSITIVE),
+            -Float::MIN_POSITIVE
+        );
+        assert_eq!(Float::MAX.midpoint(5.0), Float::MAX / 2.0 + 2.5);
+        assert_eq!(Float::MAX.midpoint(-5.0), Float::MAX / 2.0 - 2.5);
+        assert_eq!(Float::INFINITY.midpoint(Float::INFINITY), Float::INFINITY);
+        assert_eq!(
+            Float::NEG_INFINITY.midpoint(Float::NEG_INFINITY),
+            Float::NEG_INFINITY
+        );
+        assert!(Float::NAN.midpoint(1.0).is_nan());
+        assert!((1.0 as Float).midpoint(Float::NAN).is_nan());
+        assert!(Float::NAN.midpoint(Float::NAN).is_nan());
+    }
+}
+
+// Separate test since the `for` loops cannot be run in `const`.
+float_test! {
+    name: midpoint_large_magnitude,
+    attrs: {
+        const: #[cfg(false)],
+        // FIXME(f16_f128): `powi` does not work in Miri for these types
+        f16: #[cfg(all(not(miri), target_has_reliable_f16_math))],
+        f128: #[cfg(all(not(miri), target_has_reliable_f128_math))],
+    },
+    test<Float> {
+        // test if large differences in magnitude are still correctly computed.
+        // NOTE: that because of how small x and y are, x + y can never overflow
+        // so (x + y) / 2.0 is always correct
+        // in particular, `2.pow(i)` will  never be at the max exponent, so it could
+        // be safely doubled, while j is significantly smaller.
+        for i in Float::MAX_EXP.saturating_sub(64)..Float::MAX_EXP {
+            for j in 0..64u8 {
+                let large = (2.0 as Float).powi(i);
+                // a much smaller number, such that there is no chance of overflow to test
+                // potential double rounding in midpoint's implementation.
+                let small = (2.0 as Float).powi(Float::MAX_EXP - 1)
+                    * Float::EPSILON
+                    * Float::from(j);
+
+                let naive = (large + small) / 2.0;
+                let midpoint = large.midpoint(small);
+
+                assert_eq!(naive, midpoint);
+            }
+        }
+    }
+}
+
+float_test! {
+    name: abs,
+    attrs: {
+        f16: #[cfg(any(miri, target_has_reliable_f16_math))],
+        f128: #[cfg(any(miri, target_has_reliable_f128_math))],
+    },
+    test<Float> {
+        assert_eq!((-1.0 as Float).abs(), 1.0);
+        assert_eq!((1.0 as Float).abs(), 1.0);
+        assert_eq!(Float::NEG_INFINITY.abs(), Float::INFINITY);
+        assert_eq!(Float::INFINITY.abs(), Float::INFINITY);
+    }
+}
+
+float_test! {
+    name: copysign,
+    attrs: {
+        f16: #[cfg(any(miri, target_has_reliable_f16_math))],
+        f128: #[cfg(any(miri, target_has_reliable_f128_math))],
+    },
+    test<Float> {
+        assert_eq!((1.0 as Float).copysign(-2.0), -1.0);
+        assert_eq!((-1.0 as Float).copysign(2.0), 1.0);
+        assert_eq!(Float::INFINITY.copysign(-0.0), Float::NEG_INFINITY);
+        assert_eq!(Float::NEG_INFINITY.copysign(0.0), Float::INFINITY);
+    }
+}
+
+float_test! {
+    name: rem_euclid,
+    attrs: {
+        const: #[cfg(false)],
+        f16: #[cfg(any(miri, target_has_reliable_f16_math))],
+        f128: #[cfg(any(miri, target_has_reliable_f128_math))],
+    },
+    test<Float> {
+        assert!(Float::INFINITY.rem_euclid(42.0 as Float).is_nan());
+        assert_eq!((42.0 as Float).rem_euclid(Float::INFINITY), (42.0 as Float));
+        assert!((42.0 as Float).rem_euclid(Float::NAN).is_nan());
+        assert!(Float::INFINITY.rem_euclid(Float::INFINITY).is_nan());
+        assert!(Float::INFINITY.rem_euclid(Float::NAN).is_nan());
+        assert!(Float::NAN.rem_euclid(Float::INFINITY).is_nan());
+    }
+}
+
+float_test! {
+    name: div_euclid,
+    attrs: {
+        const: #[cfg(false)],
+        f16: #[cfg(any(miri, target_has_reliable_f16_math))],
+        f128: #[cfg(any(miri, target_has_reliable_f128_math))],
+    },
+    test<Float> {
+        assert_eq!((42.0 as Float).div_euclid(Float::INFINITY), 0.0);
+        assert!((42.0 as Float).div_euclid(Float::NAN).is_nan());
+        assert!(Float::INFINITY.div_euclid(Float::INFINITY).is_nan());
+        assert!(Float::INFINITY.div_euclid(Float::NAN).is_nan());
+        assert!(Float::NAN.div_euclid(Float::INFINITY).is_nan());
+    }
+}
+
+float_test! {
+    name: floor,
+    attrs: {
+        f16: #[cfg(any(miri, target_has_reliable_f16_math))],
+        f128: #[cfg(any(miri, target_has_reliable_f128_math))],
+    },
+    test<Float> {
+        assert_eq!((0.0 as Float).floor(), 0.0);
+        assert!((0.0 as Float).floor().is_sign_positive());
+        assert_eq!((-0.0 as Float).floor(), -0.0);
+        assert!((-0.0 as Float).floor().is_sign_negative());
+        assert_eq!((0.5 as Float).floor(), 0.0);
+        assert_eq!((-0.5 as Float).floor(), -1.0);
+        assert_eq!((1.5 as Float).floor(), 1.0);
+        assert_eq!(Float::MAX.floor(), Float::MAX);
+        assert_eq!(Float::MIN.floor(), Float::MIN);
+        assert_eq!(Float::MIN_POSITIVE.floor(), 0.0);
+        assert_eq!((-Float::MIN_POSITIVE).floor(), -1.0);
+        assert!(Float::NAN.floor().is_nan());
+        assert_eq!(Float::INFINITY.floor(), Float::INFINITY);
+        assert_eq!(Float::NEG_INFINITY.floor(), Float::NEG_INFINITY);
+    }
+}
+
+float_test! {
+    name: ceil,
+    attrs: {
+        f16: #[cfg(any(miri, target_has_reliable_f16_math))],
+        f128: #[cfg(any(miri, target_has_reliable_f128_math))],
+    },
+    test<Float> {
+        assert_eq!((0.0 as Float).ceil(), 0.0);
+        assert!((0.0 as Float).ceil().is_sign_positive());
+        assert_eq!((-0.0 as Float).ceil(), 0.0);
+        assert!((-0.0 as Float).ceil().is_sign_negative());
+        assert_eq!((0.5 as Float).ceil(), 1.0);
+        assert_eq!((-0.5 as Float).ceil(), 0.0);
+        assert_eq!(Float::MAX.ceil(), Float::MAX);
+        assert_eq!(Float::MIN.ceil(), Float::MIN);
+        assert_eq!(Float::MIN_POSITIVE.ceil(), 1.0);
+        assert_eq!((-Float::MIN_POSITIVE).ceil(), 0.0);
+        assert!(Float::NAN.ceil().is_nan());
+        assert_eq!(Float::INFINITY.ceil(), Float::INFINITY);
+        assert_eq!(Float::NEG_INFINITY.ceil(), Float::NEG_INFINITY);
+    }
+}
+
+float_test! {
+    name: round,
+    attrs: {
+        f16: #[cfg(any(miri, target_has_reliable_f16_math))],
+        f128: #[cfg(any(miri, target_has_reliable_f128_math))],
+    },
+    test<Float> {
+        assert_eq!((0.0 as Float).round(), 0.0);
+        assert!((0.0 as Float).round().is_sign_positive());
+        assert_eq!((-0.0 as Float).round(), -0.0);
+        assert!((-0.0 as Float).round().is_sign_negative());
+        assert_eq!((0.5 as Float).round(), 1.0);
+        assert_eq!((-0.5 as Float).round(), -1.0);
+        assert_eq!(Float::MAX.round(), Float::MAX);
+        assert_eq!(Float::MIN.round(), Float::MIN);
+        assert_eq!(Float::MIN_POSITIVE.round(), 0.0);
+        assert_eq!((-Float::MIN_POSITIVE).round(), 0.0);
+        assert!(Float::NAN.round().is_nan());
+        assert_eq!(Float::INFINITY.round(), Float::INFINITY);
+        assert_eq!(Float::NEG_INFINITY.round(), Float::NEG_INFINITY);
+    }
+}
+
+float_test! {
+    name: round_ties_even,
+    attrs: {
+        f16: #[cfg(any(miri, target_has_reliable_f16_math))],
+        f128: #[cfg(any(miri, target_has_reliable_f128_math))],
+    },
+    test<Float> {
+        assert_eq!((0.0 as Float).round_ties_even(), 0.0);
+        assert!((0.0 as Float).round_ties_even().is_sign_positive());
+        assert_eq!((-0.0 as Float).round_ties_even(), -0.0);
+        assert!((-0.0 as Float).round_ties_even().is_sign_negative());
+        assert_eq!((0.5 as Float).round_ties_even(), 0.0);
+        assert!((0.5 as Float).round_ties_even().is_sign_positive());
+        assert_eq!((-0.5 as Float).round_ties_even(), -0.0);
+        assert!((-0.5 as Float).round_ties_even().is_sign_negative());
+        assert_eq!(Float::MAX.round_ties_even(), Float::MAX);
+        assert_eq!(Float::MIN.round_ties_even(), Float::MIN);
+        assert_eq!(Float::MIN_POSITIVE.round_ties_even(), 0.0);
+        assert_eq!((-Float::MIN_POSITIVE).round_ties_even(), 0.0);
+        assert!(Float::NAN.round_ties_even().is_nan());
+        assert_eq!(Float::INFINITY.round_ties_even(), Float::INFINITY);
+        assert_eq!(Float::NEG_INFINITY.round_ties_even(), Float::NEG_INFINITY);
+    }
+}
+
+float_test! {
+    name: trunc,
+    attrs: {
+        f16: #[cfg(any(miri, target_has_reliable_f16_math))],
+        f128: #[cfg(any(miri, target_has_reliable_f128_math))],
+    },
+    test<Float> {
+        assert_eq!((0.0 as Float).trunc(), 0.0);
+        assert!((0.0 as Float).trunc().is_sign_positive());
+        assert_eq!((-0.0 as Float).trunc(), -0.0);
+        assert!((-0.0 as Float).trunc().is_sign_negative());
+        assert_eq!((0.5 as Float).trunc(), 0.0);
+        assert!((0.5 as Float).trunc().is_sign_positive());
+        assert_eq!((-0.5 as Float).trunc(), -0.0);
+        assert!((-0.5 as Float).trunc().is_sign_negative());
+        assert_eq!(Float::MAX.trunc(), Float::MAX);
+        assert_eq!(Float::MIN.trunc(), Float::MIN);
+        assert_eq!(Float::MIN_POSITIVE.trunc(), 0.0);
+        assert_eq!((-Float::MIN_POSITIVE).trunc(), 0.0);
+        assert!(Float::NAN.trunc().is_nan());
+        assert_eq!(Float::INFINITY.trunc(), Float::INFINITY);
+        assert_eq!(Float::NEG_INFINITY.trunc(), Float::NEG_INFINITY);
+    }
+}
+
+float_test! {
+    name: fract,
+    attrs: {
+        f16: #[cfg(any(miri, target_has_reliable_f16_math))],
+        f128: #[cfg(any(miri, target_has_reliable_f128_math))],
+    },
+    test<Float> {
+        assert_eq!((0.0 as Float).fract(), 0.0);
+        assert!((0.0 as Float).fract().is_sign_positive());
+        assert_eq!((-0.0 as Float).fract(), 0.0);
+        assert!((-0.0 as Float).fract().is_sign_positive());
+        assert_eq!((0.5 as Float).fract(), 0.5);
+        assert!((0.5 as Float).fract().is_sign_positive());
+        assert_eq!((-0.5 as Float).fract(), -0.5);
+        assert!((-0.5 as Float).fract().is_sign_negative());
+        assert_eq!(Float::MAX.fract(), 0.0);
+        assert_eq!(Float::MIN.fract(), 0.0);
+        assert_eq!(Float::MIN_POSITIVE.fract(), Float::MIN_POSITIVE);
+        assert!(Float::MIN_POSITIVE.fract().is_sign_positive());
+        assert_eq!((-Float::MIN_POSITIVE).fract(), -Float::MIN_POSITIVE);
+        assert!((-Float::MIN_POSITIVE).fract().is_sign_negative());
+        assert!(Float::NAN.fract().is_nan());
+        assert!(Float::INFINITY.fract().is_nan());
+        assert!(Float::NEG_INFINITY.fract().is_nan());
+    }
+}
diff --git a/library/coretests/tests/num/mod.rs b/library/coretests/tests/num/mod.rs
index c68b569f86b..6611aa57866 100644
--- a/library/coretests/tests/num/mod.rs
+++ b/library/coretests/tests/num/mod.rs
@@ -730,356 +730,3 @@ assume_usize_width! {
         }
     }
 }
-
-// FIXME(141726): there is a lot of duplication between the following tests and
-// the tests in `coretests/tests/floats/f*.rs`
-// See issue https://github.com/rust-lang/rust/issues/141726 for more details.
-macro_rules! test_float {
-    ($modname: ident, $fassert: ident, $fty: ty) => {
-        mod $modname {
-            #[test]
-            fn min() {
-                $fassert!((0.0 as $fty).min(0.0), 0.0);
-                $fassert!((0.0 as $fty).min(0.0).is_sign_positive());
-                $fassert!((-0.0 as $fty).min(-0.0), -0.0);
-                $fassert!((-0.0 as $fty).min(-0.0).is_sign_negative());
-                $fassert!((9.0 as $fty).min(9.0), 9.0);
-                $fassert!((-9.0 as $fty).min(0.0), -9.0);
-                $fassert!((0.0 as $fty).min(9.0), 0.0);
-                $fassert!((0.0 as $fty).min(9.0).is_sign_positive());
-                $fassert!((-0.0 as $fty).min(9.0), -0.0);
-                $fassert!((-0.0 as $fty).min(9.0).is_sign_negative());
-                $fassert!((-0.0 as $fty).min(-9.0), -9.0);
-                $fassert!(<$fty>::INFINITY.min(9.0), 9.0);
-                $fassert!((9.0 as $fty).min(<$fty>::INFINITY), 9.0);
-                $fassert!(<$fty>::INFINITY.min(-9.0), -9.0);
-                $fassert!((-9.0 as $fty).min(<$fty>::INFINITY), -9.0);
-                $fassert!(<$fty>::NEG_INFINITY.min(9.0), <$fty>::NEG_INFINITY);
-                $fassert!((9.0 as $fty).min(<$fty>::NEG_INFINITY), <$fty>::NEG_INFINITY);
-                $fassert!(<$fty>::NEG_INFINITY.min(-9.0), <$fty>::NEG_INFINITY);
-                $fassert!((-9.0 as $fty).min(<$fty>::NEG_INFINITY), <$fty>::NEG_INFINITY);
-                $fassert!(<$fty>::NAN.min(9.0), 9.0);
-                $fassert!(<$fty>::NAN.min(-9.0), -9.0);
-                $fassert!((9.0 as $fty).min(<$fty>::NAN), 9.0);
-                $fassert!((-9.0 as $fty).min(<$fty>::NAN), -9.0);
-                $fassert!(<$fty>::NAN.min(<$fty>::NAN).is_nan());
-            }
-            #[test]
-            fn max() {
-                $fassert!((0.0 as $fty).max(0.0), 0.0);
-                $fassert!((0.0 as $fty).max(0.0).is_sign_positive());
-                $fassert!((-0.0 as $fty).max(-0.0), -0.0);
-                $fassert!((-0.0 as $fty).max(-0.0).is_sign_negative());
-                $fassert!((9.0 as $fty).max(9.0), 9.0);
-                $fassert!((-9.0 as $fty).max(0.0), 0.0);
-                $fassert!((-9.0 as $fty).max(0.0).is_sign_positive());
-                $fassert!((-9.0 as $fty).max(-0.0), -0.0);
-                $fassert!((-9.0 as $fty).max(-0.0).is_sign_negative());
-                $fassert!((0.0 as $fty).max(9.0), 9.0);
-                $fassert!((0.0 as $fty).max(-9.0), 0.0);
-                $fassert!((0.0 as $fty).max(-9.0).is_sign_positive());
-                $fassert!((-0.0 as $fty).max(-9.0), -0.0);
-                $fassert!((-0.0 as $fty).max(-9.0).is_sign_negative());
-                $fassert!(<$fty>::INFINITY.max(9.0), <$fty>::INFINITY);
-                $fassert!((9.0 as $fty).max(<$fty>::INFINITY), <$fty>::INFINITY);
-                $fassert!(<$fty>::INFINITY.max(-9.0), <$fty>::INFINITY);
-                $fassert!((-9.0 as $fty).max(<$fty>::INFINITY), <$fty>::INFINITY);
-                $fassert!(<$fty>::NEG_INFINITY.max(9.0), 9.0);
-                $fassert!((9.0 as $fty).max(<$fty>::NEG_INFINITY), 9.0);
-                $fassert!(<$fty>::NEG_INFINITY.max(-9.0), -9.0);
-                $fassert!((-9.0 as $fty).max(<$fty>::NEG_INFINITY), -9.0);
-                $fassert!(<$fty>::NAN.max(9.0), 9.0);
-                $fassert!(<$fty>::NAN.max(-9.0), -9.0);
-                $fassert!((9.0 as $fty).max(<$fty>::NAN), 9.0);
-                $fassert!((-9.0 as $fty).max(<$fty>::NAN), -9.0);
-                $fassert!(<$fty>::NAN.max(<$fty>::NAN).is_nan());
-            }
-            #[test]
-            fn minimum() {
-                $fassert!((0.0 as $fty).minimum(0.0), 0.0);
-                $fassert!((0.0 as $fty).minimum(0.0).is_sign_positive());
-                $fassert!((-0.0 as $fty).minimum(0.0), -0.0);
-                $fassert!((-0.0 as $fty).minimum(0.0).is_sign_negative());
-                $fassert!((-0.0 as $fty).minimum(-0.0), -0.0);
-                $fassert!((-0.0 as $fty).minimum(-0.0).is_sign_negative());
-                $fassert!((9.0 as $fty).minimum(9.0), 9.0);
-                $fassert!((-9.0 as $fty).minimum(0.0), -9.0);
-                $fassert!((0.0 as $fty).minimum(9.0), 0.0);
-                $fassert!((0.0 as $fty).minimum(9.0).is_sign_positive());
-                $fassert!((-0.0 as $fty).minimum(9.0), -0.0);
-                $fassert!((-0.0 as $fty).minimum(9.0).is_sign_negative());
-                $fassert!((-0.0 as $fty).minimum(-9.0), -9.0);
-                $fassert!(<$fty>::INFINITY.minimum(9.0), 9.0);
-                $fassert!((9.0 as $fty).minimum(<$fty>::INFINITY), 9.0);
-                $fassert!(<$fty>::INFINITY.minimum(-9.0), -9.0);
-                $fassert!((-9.0 as $fty).minimum(<$fty>::INFINITY), -9.0);
-                $fassert!(<$fty>::NEG_INFINITY.minimum(9.0), <$fty>::NEG_INFINITY);
-                $fassert!((9.0 as $fty).minimum(<$fty>::NEG_INFINITY), <$fty>::NEG_INFINITY);
-                $fassert!(<$fty>::NEG_INFINITY.minimum(-9.0), <$fty>::NEG_INFINITY);
-                $fassert!((-9.0 as $fty).minimum(<$fty>::NEG_INFINITY), <$fty>::NEG_INFINITY);
-                $fassert!(<$fty>::NAN.minimum(9.0).is_nan());
-                $fassert!(<$fty>::NAN.minimum(-9.0).is_nan());
-                $fassert!((9.0 as $fty).minimum(<$fty>::NAN).is_nan());
-                $fassert!((-9.0 as $fty).minimum(<$fty>::NAN).is_nan());
-                $fassert!(<$fty>::NAN.minimum(<$fty>::NAN).is_nan());
-            }
-            #[test]
-            fn maximum() {
-                $fassert!((0.0 as $fty).maximum(0.0), 0.0);
-                $fassert!((0.0 as $fty).maximum(0.0).is_sign_positive());
-                $fassert!((-0.0 as $fty).maximum(0.0), 0.0);
-                $fassert!((-0.0 as $fty).maximum(0.0).is_sign_positive());
-                $fassert!((-0.0 as $fty).maximum(-0.0), -0.0);
-                $fassert!((-0.0 as $fty).maximum(-0.0).is_sign_negative());
-                $fassert!((9.0 as $fty).maximum(9.0), 9.0);
-                $fassert!((-9.0 as $fty).maximum(0.0), 0.0);
-                $fassert!((-9.0 as $fty).maximum(0.0).is_sign_positive());
-                $fassert!((-9.0 as $fty).maximum(-0.0), -0.0);
-                $fassert!((-9.0 as $fty).maximum(-0.0).is_sign_negative());
-                $fassert!((0.0 as $fty).maximum(9.0), 9.0);
-                $fassert!((0.0 as $fty).maximum(-9.0), 0.0);
-                $fassert!((0.0 as $fty).maximum(-9.0).is_sign_positive());
-                $fassert!((-0.0 as $fty).maximum(-9.0), -0.0);
-                $fassert!((-0.0 as $fty).maximum(-9.0).is_sign_negative());
-                $fassert!(<$fty>::INFINITY.maximum(9.0), <$fty>::INFINITY);
-                $fassert!((9.0 as $fty).maximum(<$fty>::INFINITY), <$fty>::INFINITY);
-                $fassert!(<$fty>::INFINITY.maximum(-9.0), <$fty>::INFINITY);
-                $fassert!((-9.0 as $fty).maximum(<$fty>::INFINITY), <$fty>::INFINITY);
-                $fassert!(<$fty>::NEG_INFINITY.maximum(9.0), 9.0);
-                $fassert!((9.0 as $fty).maximum(<$fty>::NEG_INFINITY), 9.0);
-                $fassert!(<$fty>::NEG_INFINITY.maximum(-9.0), -9.0);
-                $fassert!((-9.0 as $fty).maximum(<$fty>::NEG_INFINITY), -9.0);
-                $fassert!(<$fty>::NAN.maximum(9.0).is_nan());
-                $fassert!(<$fty>::NAN.maximum(-9.0).is_nan());
-                $fassert!((9.0 as $fty).maximum(<$fty>::NAN).is_nan());
-                $fassert!((-9.0 as $fty).maximum(<$fty>::NAN).is_nan());
-                $fassert!(<$fty>::NAN.maximum(<$fty>::NAN).is_nan());
-            }
-            #[test]
-            fn midpoint() {
-                $fassert!((0.5 as $fty).midpoint(0.5), 0.5);
-                $fassert!((0.5 as $fty).midpoint(2.5), 1.5);
-                $fassert!((3.0 as $fty).midpoint(4.0), 3.5);
-                $fassert!((-3.0 as $fty).midpoint(4.0), 0.5);
-                $fassert!((3.0 as $fty).midpoint(-4.0), -0.5);
-                $fassert!((-3.0 as $fty).midpoint(-4.0), -3.5);
-                $fassert!((0.0 as $fty).midpoint(0.0), 0.0);
-                $fassert!((-0.0 as $fty).midpoint(-0.0), -0.0);
-                $fassert!((-5.0 as $fty).midpoint(5.0), 0.0);
-                $fassert!(<$fty>::MAX.midpoint(<$fty>::MIN), 0.0);
-                $fassert!(<$fty>::MIN.midpoint(<$fty>::MAX), -0.0);
-                $fassert!(<$fty>::MAX.midpoint(<$fty>::MIN_POSITIVE), <$fty>::MAX / 2.);
-                $fassert!((-<$fty>::MAX).midpoint(<$fty>::MIN_POSITIVE), -<$fty>::MAX / 2.);
-                $fassert!(<$fty>::MAX.midpoint(-<$fty>::MIN_POSITIVE), <$fty>::MAX / 2.);
-                $fassert!((-<$fty>::MAX).midpoint(-<$fty>::MIN_POSITIVE), -<$fty>::MAX / 2.);
-                $fassert!((<$fty>::MIN_POSITIVE).midpoint(<$fty>::MAX), <$fty>::MAX / 2.);
-                $fassert!((<$fty>::MIN_POSITIVE).midpoint(-<$fty>::MAX), -<$fty>::MAX / 2.);
-                $fassert!((-<$fty>::MIN_POSITIVE).midpoint(<$fty>::MAX), <$fty>::MAX / 2.);
-                $fassert!((-<$fty>::MIN_POSITIVE).midpoint(-<$fty>::MAX), -<$fty>::MAX / 2.);
-                $fassert!(<$fty>::MAX.midpoint(<$fty>::MAX), <$fty>::MAX);
-                $fassert!(
-                    (<$fty>::MIN_POSITIVE).midpoint(<$fty>::MIN_POSITIVE),
-                    <$fty>::MIN_POSITIVE
-                );
-                $fassert!(
-                    (-<$fty>::MIN_POSITIVE).midpoint(-<$fty>::MIN_POSITIVE),
-                    -<$fty>::MIN_POSITIVE
-                );
-                $fassert!(<$fty>::MAX.midpoint(5.0), <$fty>::MAX / 2.0 + 2.5);
-                $fassert!(<$fty>::MAX.midpoint(-5.0), <$fty>::MAX / 2.0 - 2.5);
-                $fassert!(<$fty>::INFINITY.midpoint(<$fty>::INFINITY), <$fty>::INFINITY);
-                $fassert!(
-                    <$fty>::NEG_INFINITY.midpoint(<$fty>::NEG_INFINITY),
-                    <$fty>::NEG_INFINITY
-                );
-                $fassert!(<$fty>::NAN.midpoint(1.0).is_nan());
-                $fassert!((1.0 as $fty).midpoint(<$fty>::NAN).is_nan());
-                $fassert!(<$fty>::NAN.midpoint(<$fty>::NAN).is_nan());
-
-                // test if large differences in magnitude are still correctly computed.
-                // NOTE: that because of how small x and y are, x + y can never overflow
-                // so (x + y) / 2.0 is always correct
-                // in particular, `2.pow(i)` will  never be at the max exponent, so it could
-                // be safely doubled, while j is significantly smaller.
-                for i in <$fty>::MAX_EXP.saturating_sub(64)..<$fty>::MAX_EXP {
-                    for j in 0..64u8 {
-                        let large = (2.0 as $fty).powi(i);
-                        // a much smaller number, such that there is no chance of overflow to test
-                        // potential double rounding in midpoint's implementation.
-                        let small = (2.0 as $fty).powi(<$fty>::MAX_EXP - 1)
-                            * <$fty>::EPSILON
-                            * <$fty>::from(j);
-
-                        let naive = (large + small) / 2.0;
-                        let midpoint = large.midpoint(small);
-
-                        assert_eq!(naive, midpoint);
-                    }
-                }
-            }
-            #[test]
-            fn abs() {
-                $fassert!((-1.0 as $fty).abs(), 1.0);
-                $fassert!((1.0 as $fty).abs(), 1.0);
-                $fassert!(<$fty>::NEG_INFINITY.abs(), <$fty>::INFINITY);
-                $fassert!(<$fty>::INFINITY.abs(), <$fty>::INFINITY);
-            }
-            #[test]
-            fn copysign() {
-                $fassert!((1.0 as $fty).copysign(-2.0), -1.0);
-                $fassert!((-1.0 as $fty).copysign(2.0), 1.0);
-                $fassert!(<$fty>::INFINITY.copysign(-0.0), <$fty>::NEG_INFINITY);
-                $fassert!(<$fty>::NEG_INFINITY.copysign(0.0), <$fty>::INFINITY);
-            }
-            #[test]
-            fn rem_euclid() {
-                // FIXME: Use $fassert when rem_euclid becomes const
-                assert!(<$fty>::INFINITY.rem_euclid((42.0 as $fty)).is_nan());
-                assert_eq!((42.0 as $fty).rem_euclid(<$fty>::INFINITY), (42.0 as $fty));
-                assert!((42.0 as $fty).rem_euclid(<$fty>::NAN).is_nan());
-                assert!(<$fty>::INFINITY.rem_euclid(<$fty>::INFINITY).is_nan());
-                assert!(<$fty>::INFINITY.rem_euclid(<$fty>::NAN).is_nan());
-                assert!(<$fty>::NAN.rem_euclid(<$fty>::INFINITY).is_nan());
-            }
-            #[test]
-            fn div_euclid() {
-                // FIXME: Use $fassert when div_euclid becomes const
-                assert_eq!((42.0 as $fty).div_euclid(<$fty>::INFINITY), 0.0);
-                assert!((42.0 as $fty).div_euclid(<$fty>::NAN).is_nan());
-                assert!(<$fty>::INFINITY.div_euclid(<$fty>::INFINITY).is_nan());
-                assert!(<$fty>::INFINITY.div_euclid(<$fty>::NAN).is_nan());
-                assert!(<$fty>::NAN.div_euclid(<$fty>::INFINITY).is_nan());
-            }
-            #[test]
-            fn floor() {
-                $fassert!((0.0 as $fty).floor(), 0.0);
-                $fassert!((0.0 as $fty).floor().is_sign_positive());
-                $fassert!((-0.0 as $fty).floor(), -0.0);
-                $fassert!((-0.0 as $fty).floor().is_sign_negative());
-                $fassert!((0.5 as $fty).floor(), 0.0);
-                $fassert!((-0.5 as $fty).floor(), -1.0);
-                $fassert!((1.5 as $fty).floor(), 1.0);
-                $fassert!(<$fty>::MAX.floor(), <$fty>::MAX);
-                $fassert!(<$fty>::MIN.floor(), <$fty>::MIN);
-                $fassert!(<$fty>::MIN_POSITIVE.floor(), 0.0);
-                $fassert!((-<$fty>::MIN_POSITIVE).floor(), -1.0);
-                $fassert!(<$fty>::NAN.floor().is_nan());
-                $fassert!(<$fty>::INFINITY.floor(), <$fty>::INFINITY);
-                $fassert!(<$fty>::NEG_INFINITY.floor(), <$fty>::NEG_INFINITY);
-            }
-            #[test]
-            fn ceil() {
-                $fassert!((0.0 as $fty).ceil(), 0.0);
-                $fassert!((0.0 as $fty).ceil().is_sign_positive());
-                $fassert!((-0.0 as $fty).ceil(), 0.0);
-                $fassert!((-0.0 as $fty).ceil().is_sign_negative());
-                $fassert!((0.5 as $fty).ceil(), 1.0);
-                $fassert!((-0.5 as $fty).ceil(), 0.0);
-                $fassert!(<$fty>::MAX.ceil(), <$fty>::MAX);
-                $fassert!(<$fty>::MIN.ceil(), <$fty>::MIN);
-                $fassert!(<$fty>::MIN_POSITIVE.ceil(), 1.0);
-                $fassert!((-<$fty>::MIN_POSITIVE).ceil(), 0.0);
-                $fassert!(<$fty>::NAN.ceil().is_nan());
-                $fassert!(<$fty>::INFINITY.ceil(), <$fty>::INFINITY);
-                $fassert!(<$fty>::NEG_INFINITY.ceil(), <$fty>::NEG_INFINITY);
-            }
-            #[test]
-            fn round() {
-                $fassert!((0.0 as $fty).round(), 0.0);
-                $fassert!((0.0 as $fty).round().is_sign_positive());
-                $fassert!((-0.0 as $fty).round(), -0.0);
-                $fassert!((-0.0 as $fty).round().is_sign_negative());
-                $fassert!((0.5 as $fty).round(), 1.0);
-                $fassert!((-0.5 as $fty).round(), -1.0);
-                $fassert!(<$fty>::MAX.round(), <$fty>::MAX);
-                $fassert!(<$fty>::MIN.round(), <$fty>::MIN);
-                $fassert!(<$fty>::MIN_POSITIVE.round(), 0.0);
-                $fassert!((-<$fty>::MIN_POSITIVE).round(), 0.0);
-                $fassert!(<$fty>::NAN.round().is_nan());
-                $fassert!(<$fty>::INFINITY.round(), <$fty>::INFINITY);
-                $fassert!(<$fty>::NEG_INFINITY.round(), <$fty>::NEG_INFINITY);
-            }
-            #[test]
-            fn round_ties_even() {
-                $fassert!((0.0 as $fty).round_ties_even(), 0.0);
-                $fassert!((0.0 as $fty).round_ties_even().is_sign_positive());
-                $fassert!((-0.0 as $fty).round_ties_even(), -0.0);
-                $fassert!((-0.0 as $fty).round_ties_even().is_sign_negative());
-                $fassert!((0.5 as $fty).round_ties_even(), 0.0);
-                $fassert!((0.5 as $fty).round_ties_even().is_sign_positive());
-                $fassert!((-0.5 as $fty).round_ties_even(), -0.0);
-                $fassert!((-0.5 as $fty).round_ties_even().is_sign_negative());
-                $fassert!(<$fty>::MAX.round_ties_even(), <$fty>::MAX);
-                $fassert!(<$fty>::MIN.round_ties_even(), <$fty>::MIN);
-                $fassert!(<$fty>::MIN_POSITIVE.round_ties_even(), 0.0);
-                $fassert!((-<$fty>::MIN_POSITIVE).round_ties_even(), 0.0);
-                $fassert!(<$fty>::NAN.round_ties_even().is_nan());
-                $fassert!(<$fty>::INFINITY.round_ties_even(), <$fty>::INFINITY);
-                $fassert!(<$fty>::NEG_INFINITY.round_ties_even(), <$fty>::NEG_INFINITY);
-            }
-            #[test]
-            fn trunc() {
-                $fassert!((0.0 as $fty).trunc(), 0.0);
-                $fassert!((0.0 as $fty).trunc().is_sign_positive());
-                $fassert!((-0.0 as $fty).trunc(), -0.0);
-                $fassert!((-0.0 as $fty).trunc().is_sign_negative());
-                $fassert!((0.5 as $fty).trunc(), 0.0);
-                $fassert!((0.5 as $fty).trunc().is_sign_positive());
-                $fassert!((-0.5 as $fty).trunc(), -0.0);
-                $fassert!((-0.5 as $fty).trunc().is_sign_negative());
-                $fassert!(<$fty>::MAX.trunc(), <$fty>::MAX);
-                $fassert!(<$fty>::MIN.trunc(), <$fty>::MIN);
-                $fassert!(<$fty>::MIN_POSITIVE.trunc(), 0.0);
-                $fassert!((-<$fty>::MIN_POSITIVE).trunc(), 0.0);
-                $fassert!(<$fty>::NAN.trunc().is_nan());
-                $fassert!(<$fty>::INFINITY.trunc(), <$fty>::INFINITY);
-                $fassert!(<$fty>::NEG_INFINITY.trunc(), <$fty>::NEG_INFINITY);
-            }
-            #[test]
-            fn fract() {
-                $fassert!((0.0 as $fty).fract(), 0.0);
-                $fassert!((0.0 as $fty).fract().is_sign_positive());
-                $fassert!((-0.0 as $fty).fract(), 0.0);
-                $fassert!((-0.0 as $fty).fract().is_sign_positive());
-                $fassert!((0.5 as $fty).fract(), 0.5);
-                $fassert!((0.5 as $fty).fract().is_sign_positive());
-                $fassert!((-0.5 as $fty).fract(), -0.5);
-                $fassert!((-0.5 as $fty).fract().is_sign_negative());
-                $fassert!(<$fty>::MAX.fract(), 0.0);
-                $fassert!(<$fty>::MIN.fract(), 0.0);
-                $fassert!(<$fty>::MIN_POSITIVE.fract(), <$fty>::MIN_POSITIVE);
-                $fassert!(<$fty>::MIN_POSITIVE.fract().is_sign_positive());
-                $fassert!((-<$fty>::MIN_POSITIVE).fract(), -<$fty>::MIN_POSITIVE);
-                $fassert!((-<$fty>::MIN_POSITIVE).fract().is_sign_negative());
-                $fassert!(<$fty>::NAN.fract().is_nan());
-                $fassert!(<$fty>::INFINITY.fract().is_nan());
-                $fassert!(<$fty>::NEG_INFINITY.fract().is_nan());
-            }
-        }
-    };
-}
-
-// Custom assert macro that distribute between assert! and assert_eq! in a non-const context
-macro_rules! float_assert {
-    ($b:expr) => {
-        assert!($b);
-    };
-    ($left:expr, $right:expr) => {
-        assert_eq!($left, $right);
-    };
-}
-
-// Custom assert macro that only uses assert! in a const context
-macro_rules! float_const_assert {
-    ($b:expr) => {
-        assert!(const { $b });
-    };
-    ($left:expr, $right:expr) => {
-        assert!(const { $left == $right });
-    };
-}
-
-test_float!(f32, float_assert, f32);
-test_float!(f32_const, float_const_assert, f32);
-test_float!(f64, float_assert, f64);
-test_float!(f64_const, float_const_assert, f64);