about summary refs log tree commit diff
path: root/library
diff options
context:
space:
mode:
authorSamuel Tardieu <sam@rfc1149.net>2025-07-16 17:06:40 +0200
committerGitHub <noreply@github.com>2025-07-16 17:06:40 +0200
commit096a66d8d8c6cc2e494fb5d10084d3053794d0e8 (patch)
treecbecf415b2342a1165cc35975bb8fffd7e2272c9 /library
parent7b5e08f8ef03ef3b56c65c3c80a0eb0c47884864 (diff)
parent79769f2d5babdfc8ca0c88045fdedcf312a3d83d (diff)
downloadrust-096a66d8d8c6cc2e494fb5d10084d3053794d0e8.tar.gz
rust-096a66d8d8c6cc2e494fb5d10084d3053794d0e8.zip
Rollup merge of #143738 - rocurley:float_tests_refactor_2, r=tgross35
Move several float tests to floats/mod.rs

This PR moves several tests to `floats/mod.rs`, as discussed in https://github.com/rust-lang/rust/issues/141726. The tests moved are:

- `test_num_f*`
- `test_infinity`
- `test_neg_infinity`
- `test_zero`
- `test_neg_zero`
- `test_one`
- `test_is_nan`
- `test_is_infinite`
- `test_is_finite`
- `test_is_normal`
- `test_classify`

Each test is its own commit, so it may be easiest to review each commit individually.

r? tgross35
Diffstat (limited to 'library')
-rw-r--r--library/coretests/tests/floats/f128.rs153
-rw-r--r--library/coretests/tests/floats/f16.rs143
-rw-r--r--library/coretests/tests/floats/f32.rs143
-rw-r--r--library/coretests/tests/floats/f64.rs142
-rw-r--r--library/coretests/tests/floats/mod.rs301
-rw-r--r--library/coretests/tests/lib.rs1
6 files changed, 268 insertions, 615 deletions
diff --git a/library/coretests/tests/floats/f128.rs b/library/coretests/tests/floats/f128.rs
index 38df09a91c1..36d6a20a944 100644
--- a/library/coretests/tests/floats/f128.rs
+++ b/library/coretests/tests/floats/f128.rs
@@ -1,9 +1,7 @@
 // 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;
 
 use super::{assert_approx_eq, assert_biteq};
 
@@ -38,161 +36,10 @@ const NAN_MASK1: u128 = 0x0000aaaaaaaaaaaaaaaaaaaaaaaaaaaa;
 /// Second pattern over the mantissa
 const NAN_MASK2: u128 = 0x00005555555555555555555555555555;
 
-#[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_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]
-fn test_infinity() {
-    let inf: f128 = f128::INFINITY;
-    assert!(inf.is_infinite());
-    assert!(!inf.is_finite());
-    assert!(inf.is_sign_positive());
-    assert!(!inf.is_sign_negative());
-    assert!(!inf.is_nan());
-    assert!(!inf.is_normal());
-    assert_eq!(Fp::Infinite, inf.classify());
-}
-
-#[test]
-fn test_neg_infinity() {
-    let neg_inf: f128 = f128::NEG_INFINITY;
-    assert!(neg_inf.is_infinite());
-    assert!(!neg_inf.is_finite());
-    assert!(!neg_inf.is_sign_positive());
-    assert!(neg_inf.is_sign_negative());
-    assert!(!neg_inf.is_nan());
-    assert!(!neg_inf.is_normal());
-    assert_eq!(Fp::Infinite, neg_inf.classify());
-}
-
-#[test]
-fn test_zero() {
-    let zero: f128 = 0.0f128;
-    assert_biteq!(0.0, zero);
-    assert!(!zero.is_infinite());
-    assert!(zero.is_finite());
-    assert!(zero.is_sign_positive());
-    assert!(!zero.is_sign_negative());
-    assert!(!zero.is_nan());
-    assert!(!zero.is_normal());
-    assert_eq!(Fp::Zero, zero.classify());
-}
-
-#[test]
-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());
-    assert!(neg_zero.is_sign_negative());
-    assert!(!neg_zero.is_nan());
-    assert!(!neg_zero.is_normal());
-    assert_eq!(Fp::Zero, neg_zero.classify());
-}
-
-#[test]
-fn test_one() {
-    let one: f128 = 1.0f128;
-    assert_biteq!(1.0, one);
-    assert!(!one.is_infinite());
-    assert!(one.is_finite());
-    assert!(one.is_sign_positive());
-    assert!(!one.is_sign_negative());
-    assert!(!one.is_nan());
-    assert!(one.is_normal());
-    assert_eq!(Fp::Normal, one.classify());
-}
-
-#[test]
-fn test_is_nan() {
-    let nan: f128 = f128::NAN;
-    let inf: f128 = f128::INFINITY;
-    let neg_inf: f128 = f128::NEG_INFINITY;
-    assert!(nan.is_nan());
-    assert!(!0.0f128.is_nan());
-    assert!(!5.3f128.is_nan());
-    assert!(!(-10.732f128).is_nan());
-    assert!(!inf.is_nan());
-    assert!(!neg_inf.is_nan());
-}
-
-#[test]
-fn test_is_infinite() {
-    let nan: f128 = f128::NAN;
-    let inf: f128 = f128::INFINITY;
-    let neg_inf: f128 = f128::NEG_INFINITY;
-    assert!(!nan.is_infinite());
-    assert!(inf.is_infinite());
-    assert!(neg_inf.is_infinite());
-    assert!(!0.0f128.is_infinite());
-    assert!(!42.8f128.is_infinite());
-    assert!(!(-109.2f128).is_infinite());
-}
-
-#[test]
-fn test_is_finite() {
-    let nan: f128 = f128::NAN;
-    let inf: f128 = f128::INFINITY;
-    let neg_inf: f128 = f128::NEG_INFINITY;
-    assert!(!nan.is_finite());
-    assert!(!inf.is_finite());
-    assert!(!neg_inf.is_finite());
-    assert!(0.0f128.is_finite());
-    assert!(42.8f128.is_finite());
-    assert!((-109.2f128).is_finite());
-}
-
-#[test]
-fn test_is_normal() {
-    let nan: f128 = f128::NAN;
-    let inf: f128 = f128::INFINITY;
-    let neg_inf: f128 = f128::NEG_INFINITY;
-    let zero: f128 = 0.0f128;
-    let neg_zero: f128 = -0.0;
-    assert!(!nan.is_normal());
-    assert!(!inf.is_normal());
-    assert!(!neg_inf.is_normal());
-    assert!(!zero.is_normal());
-    assert!(!neg_zero.is_normal());
-    assert!(1f128.is_normal());
-    assert!(1e-4931f128.is_normal());
-    assert!(!1e-4932f128.is_normal());
-}
-
-#[test]
-fn test_classify() {
-    let nan: f128 = f128::NAN;
-    let inf: f128 = f128::INFINITY;
-    let neg_inf: f128 = f128::NEG_INFINITY;
-    let zero: f128 = 0.0f128;
-    let neg_zero: f128 = -0.0;
-    assert_eq!(nan.classify(), Fp::Nan);
-    assert_eq!(inf.classify(), Fp::Infinite);
-    assert_eq!(neg_inf.classify(), Fp::Infinite);
-    assert_eq!(zero.classify(), Fp::Zero);
-    assert_eq!(neg_zero.classify(), Fp::Zero);
-    assert_eq!(1f128.classify(), Fp::Normal);
-    assert_eq!(1e-4931f128.classify(), Fp::Normal);
-    assert_eq!(1e-4932f128.classify(), Fp::Subnormal);
-}
-
-#[test]
 #[cfg(any(miri, target_has_reliable_f128_math))]
 fn test_abs() {
     assert_biteq!(f128::INFINITY.abs(), f128::INFINITY);
diff --git a/library/coretests/tests/floats/f16.rs b/library/coretests/tests/floats/f16.rs
index f6749d796cc..351c008a37b 100644
--- a/library/coretests/tests/floats/f16.rs
+++ b/library/coretests/tests/floats/f16.rs
@@ -2,7 +2,6 @@
 #![cfg(target_has_reliable_f16)]
 
 use std::f16::consts;
-use std::num::FpCategory as Fp;
 
 use super::{assert_approx_eq, assert_biteq};
 
@@ -43,152 +42,10 @@ const NAN_MASK1: u16 = 0x02aa;
 /// Second pattern over the mantissa
 const NAN_MASK2: u16 = 0x0155;
 
-#[test]
-fn test_num_f16() {
-    super::test_num(10f16, 2f16);
-}
-
 // FIXME(f16_f128,miri): many of these have to be disabled since miri does not yet support
 // the intrinsics.
 
 #[test]
-fn test_infinity() {
-    let inf: f16 = f16::INFINITY;
-    assert!(inf.is_infinite());
-    assert!(!inf.is_finite());
-    assert!(inf.is_sign_positive());
-    assert!(!inf.is_sign_negative());
-    assert!(!inf.is_nan());
-    assert!(!inf.is_normal());
-    assert_eq!(Fp::Infinite, inf.classify());
-}
-
-#[test]
-fn test_neg_infinity() {
-    let neg_inf: f16 = f16::NEG_INFINITY;
-    assert!(neg_inf.is_infinite());
-    assert!(!neg_inf.is_finite());
-    assert!(!neg_inf.is_sign_positive());
-    assert!(neg_inf.is_sign_negative());
-    assert!(!neg_inf.is_nan());
-    assert!(!neg_inf.is_normal());
-    assert_eq!(Fp::Infinite, neg_inf.classify());
-}
-
-#[test]
-fn test_zero() {
-    let zero: f16 = 0.0f16;
-    assert_biteq!(0.0, zero);
-    assert!(!zero.is_infinite());
-    assert!(zero.is_finite());
-    assert!(zero.is_sign_positive());
-    assert!(!zero.is_sign_negative());
-    assert!(!zero.is_nan());
-    assert!(!zero.is_normal());
-    assert_eq!(Fp::Zero, zero.classify());
-}
-
-#[test]
-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());
-    assert!(neg_zero.is_sign_negative());
-    assert!(!neg_zero.is_nan());
-    assert!(!neg_zero.is_normal());
-    assert_eq!(Fp::Zero, neg_zero.classify());
-}
-
-#[test]
-fn test_one() {
-    let one: f16 = 1.0f16;
-    assert_biteq!(1.0, one);
-    assert!(!one.is_infinite());
-    assert!(one.is_finite());
-    assert!(one.is_sign_positive());
-    assert!(!one.is_sign_negative());
-    assert!(!one.is_nan());
-    assert!(one.is_normal());
-    assert_eq!(Fp::Normal, one.classify());
-}
-
-#[test]
-fn test_is_nan() {
-    let nan: f16 = f16::NAN;
-    let inf: f16 = f16::INFINITY;
-    let neg_inf: f16 = f16::NEG_INFINITY;
-    assert!(nan.is_nan());
-    assert!(!0.0f16.is_nan());
-    assert!(!5.3f16.is_nan());
-    assert!(!(-10.732f16).is_nan());
-    assert!(!inf.is_nan());
-    assert!(!neg_inf.is_nan());
-}
-
-#[test]
-fn test_is_infinite() {
-    let nan: f16 = f16::NAN;
-    let inf: f16 = f16::INFINITY;
-    let neg_inf: f16 = f16::NEG_INFINITY;
-    assert!(!nan.is_infinite());
-    assert!(inf.is_infinite());
-    assert!(neg_inf.is_infinite());
-    assert!(!0.0f16.is_infinite());
-    assert!(!42.8f16.is_infinite());
-    assert!(!(-109.2f16).is_infinite());
-}
-
-#[test]
-fn test_is_finite() {
-    let nan: f16 = f16::NAN;
-    let inf: f16 = f16::INFINITY;
-    let neg_inf: f16 = f16::NEG_INFINITY;
-    assert!(!nan.is_finite());
-    assert!(!inf.is_finite());
-    assert!(!neg_inf.is_finite());
-    assert!(0.0f16.is_finite());
-    assert!(42.8f16.is_finite());
-    assert!((-109.2f16).is_finite());
-}
-
-#[test]
-fn test_is_normal() {
-    let nan: f16 = f16::NAN;
-    let inf: f16 = f16::INFINITY;
-    let neg_inf: f16 = f16::NEG_INFINITY;
-    let zero: f16 = 0.0f16;
-    let neg_zero: f16 = -0.0;
-    assert!(!nan.is_normal());
-    assert!(!inf.is_normal());
-    assert!(!neg_inf.is_normal());
-    assert!(!zero.is_normal());
-    assert!(!neg_zero.is_normal());
-    assert!(1f16.is_normal());
-    assert!(1e-4f16.is_normal());
-    assert!(!1e-5f16.is_normal());
-}
-
-#[test]
-fn test_classify() {
-    let nan: f16 = f16::NAN;
-    let inf: f16 = f16::INFINITY;
-    let neg_inf: f16 = f16::NEG_INFINITY;
-    let zero: f16 = 0.0f16;
-    let neg_zero: f16 = -0.0;
-    assert_eq!(nan.classify(), Fp::Nan);
-    assert_eq!(inf.classify(), Fp::Infinite);
-    assert_eq!(neg_inf.classify(), Fp::Infinite);
-    assert_eq!(zero.classify(), Fp::Zero);
-    assert_eq!(neg_zero.classify(), Fp::Zero);
-    assert_eq!(1f16.classify(), Fp::Normal);
-    assert_eq!(1e-4f16.classify(), Fp::Normal);
-    assert_eq!(1e-5f16.classify(), Fp::Subnormal);
-}
-
-#[test]
 #[cfg(any(miri, target_has_reliable_f16_math))]
 fn test_abs() {
     assert_biteq!(f16::INFINITY.abs(), f16::INFINITY);
diff --git a/library/coretests/tests/floats/f32.rs b/library/coretests/tests/floats/f32.rs
index f5d5723fea4..267b0e4e294 100644
--- a/library/coretests/tests/floats/f32.rs
+++ b/library/coretests/tests/floats/f32.rs
@@ -1,6 +1,5 @@
 use core::f32;
 use core::f32::consts;
-use core::num::FpCategory as Fp;
 
 use super::{assert_approx_eq, assert_biteq};
 
@@ -31,148 +30,6 @@ const NAN_MASK2: u32 = 0x0055_5555;
 const APPROX_DELTA: f32 = if cfg!(miri) { 1e-4 } else { 1e-6 };
 
 #[test]
-fn test_num_f32() {
-    super::test_num(10f32, 2f32);
-}
-
-#[test]
-fn test_infinity() {
-    let inf: f32 = f32::INFINITY;
-    assert!(inf.is_infinite());
-    assert!(!inf.is_finite());
-    assert!(inf.is_sign_positive());
-    assert!(!inf.is_sign_negative());
-    assert!(!inf.is_nan());
-    assert!(!inf.is_normal());
-    assert_eq!(Fp::Infinite, inf.classify());
-}
-
-#[test]
-fn test_neg_infinity() {
-    let neg_inf: f32 = f32::NEG_INFINITY;
-    assert!(neg_inf.is_infinite());
-    assert!(!neg_inf.is_finite());
-    assert!(!neg_inf.is_sign_positive());
-    assert!(neg_inf.is_sign_negative());
-    assert!(!neg_inf.is_nan());
-    assert!(!neg_inf.is_normal());
-    assert_eq!(Fp::Infinite, neg_inf.classify());
-}
-
-#[test]
-fn test_zero() {
-    let zero: f32 = 0.0f32;
-    assert_biteq!(0.0, zero);
-    assert!(!zero.is_infinite());
-    assert!(zero.is_finite());
-    assert!(zero.is_sign_positive());
-    assert!(!zero.is_sign_negative());
-    assert!(!zero.is_nan());
-    assert!(!zero.is_normal());
-    assert_eq!(Fp::Zero, zero.classify());
-}
-
-#[test]
-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());
-    assert!(neg_zero.is_sign_negative());
-    assert!(!neg_zero.is_nan());
-    assert!(!neg_zero.is_normal());
-    assert_eq!(Fp::Zero, neg_zero.classify());
-}
-
-#[test]
-fn test_one() {
-    let one: f32 = 1.0f32;
-    assert_biteq!(1.0, one);
-    assert!(!one.is_infinite());
-    assert!(one.is_finite());
-    assert!(one.is_sign_positive());
-    assert!(!one.is_sign_negative());
-    assert!(!one.is_nan());
-    assert!(one.is_normal());
-    assert_eq!(Fp::Normal, one.classify());
-}
-
-#[test]
-fn test_is_nan() {
-    let nan: f32 = f32::NAN;
-    let inf: f32 = f32::INFINITY;
-    let neg_inf: f32 = f32::NEG_INFINITY;
-    assert!(nan.is_nan());
-    assert!(!0.0f32.is_nan());
-    assert!(!5.3f32.is_nan());
-    assert!(!(-10.732f32).is_nan());
-    assert!(!inf.is_nan());
-    assert!(!neg_inf.is_nan());
-}
-
-#[test]
-fn test_is_infinite() {
-    let nan: f32 = f32::NAN;
-    let inf: f32 = f32::INFINITY;
-    let neg_inf: f32 = f32::NEG_INFINITY;
-    assert!(!nan.is_infinite());
-    assert!(inf.is_infinite());
-    assert!(neg_inf.is_infinite());
-    assert!(!0.0f32.is_infinite());
-    assert!(!42.8f32.is_infinite());
-    assert!(!(-109.2f32).is_infinite());
-}
-
-#[test]
-fn test_is_finite() {
-    let nan: f32 = f32::NAN;
-    let inf: f32 = f32::INFINITY;
-    let neg_inf: f32 = f32::NEG_INFINITY;
-    assert!(!nan.is_finite());
-    assert!(!inf.is_finite());
-    assert!(!neg_inf.is_finite());
-    assert!(0.0f32.is_finite());
-    assert!(42.8f32.is_finite());
-    assert!((-109.2f32).is_finite());
-}
-
-#[test]
-fn test_is_normal() {
-    let nan: f32 = f32::NAN;
-    let inf: f32 = f32::INFINITY;
-    let neg_inf: f32 = f32::NEG_INFINITY;
-    let zero: f32 = 0.0f32;
-    let neg_zero: f32 = -0.0;
-    assert!(!nan.is_normal());
-    assert!(!inf.is_normal());
-    assert!(!neg_inf.is_normal());
-    assert!(!zero.is_normal());
-    assert!(!neg_zero.is_normal());
-    assert!(1f32.is_normal());
-    assert!(1e-37f32.is_normal());
-    assert!(!1e-38f32.is_normal());
-}
-
-#[test]
-fn test_classify() {
-    let nan: f32 = f32::NAN;
-    let inf: f32 = f32::INFINITY;
-    let neg_inf: f32 = f32::NEG_INFINITY;
-    let zero: f32 = 0.0f32;
-    let neg_zero: f32 = -0.0;
-    assert_eq!(nan.classify(), Fp::Nan);
-    assert_eq!(inf.classify(), Fp::Infinite);
-    assert_eq!(neg_inf.classify(), Fp::Infinite);
-    assert_eq!(zero.classify(), Fp::Zero);
-    assert_eq!(neg_zero.classify(), Fp::Zero);
-    assert_eq!(1f32.classify(), Fp::Normal);
-    assert_eq!(1e-37f32.classify(), Fp::Normal);
-    assert_eq!(1e-38f32.classify(), Fp::Subnormal);
-}
-
-#[test]
 fn test_abs() {
     assert_biteq!(f32::INFINITY.abs(), f32::INFINITY);
     assert_biteq!(1f32.abs(), 1f32);
diff --git a/library/coretests/tests/floats/f64.rs b/library/coretests/tests/floats/f64.rs
index 34af87c241e..735b7a76515 100644
--- a/library/coretests/tests/floats/f64.rs
+++ b/library/coretests/tests/floats/f64.rs
@@ -1,6 +1,5 @@
 use core::f64;
 use core::f64::consts;
-use core::num::FpCategory as Fp;
 
 use super::{assert_approx_eq, assert_biteq};
 
@@ -26,147 +25,6 @@ const NAN_MASK1: u64 = 0x000a_aaaa_aaaa_aaaa;
 const NAN_MASK2: u64 = 0x0005_5555_5555_5555;
 
 #[test]
-fn test_num_f64() {
-    super::test_num(10f64, 2f64);
-}
-
-#[test]
-fn test_infinity() {
-    let inf: f64 = f64::INFINITY;
-    assert!(inf.is_infinite());
-    assert!(!inf.is_finite());
-    assert!(inf.is_sign_positive());
-    assert!(!inf.is_sign_negative());
-    assert!(!inf.is_nan());
-    assert!(!inf.is_normal());
-    assert_eq!(Fp::Infinite, inf.classify());
-}
-
-#[test]
-fn test_neg_infinity() {
-    let neg_inf: f64 = f64::NEG_INFINITY;
-    assert!(neg_inf.is_infinite());
-    assert!(!neg_inf.is_finite());
-    assert!(!neg_inf.is_sign_positive());
-    assert!(neg_inf.is_sign_negative());
-    assert!(!neg_inf.is_nan());
-    assert!(!neg_inf.is_normal());
-    assert_eq!(Fp::Infinite, neg_inf.classify());
-}
-
-#[test]
-fn test_zero() {
-    let zero: f64 = 0.0f64;
-    assert_biteq!(0.0, zero);
-    assert!(!zero.is_infinite());
-    assert!(zero.is_finite());
-    assert!(zero.is_sign_positive());
-    assert!(!zero.is_sign_negative());
-    assert!(!zero.is_nan());
-    assert!(!zero.is_normal());
-    assert_eq!(Fp::Zero, zero.classify());
-}
-
-#[test]
-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());
-    assert!(neg_zero.is_sign_negative());
-    assert!(!neg_zero.is_nan());
-    assert!(!neg_zero.is_normal());
-    assert_eq!(Fp::Zero, neg_zero.classify());
-}
-
-#[test]
-fn test_one() {
-    let one: f64 = 1.0f64;
-    assert_biteq!(1.0, one);
-    assert!(!one.is_infinite());
-    assert!(one.is_finite());
-    assert!(one.is_sign_positive());
-    assert!(!one.is_sign_negative());
-    assert!(!one.is_nan());
-    assert!(one.is_normal());
-    assert_eq!(Fp::Normal, one.classify());
-}
-
-#[test]
-fn test_is_nan() {
-    let nan: f64 = f64::NAN;
-    let inf: f64 = f64::INFINITY;
-    let neg_inf: f64 = f64::NEG_INFINITY;
-    assert!(nan.is_nan());
-    assert!(!0.0f64.is_nan());
-    assert!(!5.3f64.is_nan());
-    assert!(!(-10.732f64).is_nan());
-    assert!(!inf.is_nan());
-    assert!(!neg_inf.is_nan());
-}
-
-#[test]
-fn test_is_infinite() {
-    let nan: f64 = f64::NAN;
-    let inf: f64 = f64::INFINITY;
-    let neg_inf: f64 = f64::NEG_INFINITY;
-    assert!(!nan.is_infinite());
-    assert!(inf.is_infinite());
-    assert!(neg_inf.is_infinite());
-    assert!(!0.0f64.is_infinite());
-    assert!(!42.8f64.is_infinite());
-    assert!(!(-109.2f64).is_infinite());
-}
-
-#[test]
-fn test_is_finite() {
-    let nan: f64 = f64::NAN;
-    let inf: f64 = f64::INFINITY;
-    let neg_inf: f64 = f64::NEG_INFINITY;
-    assert!(!nan.is_finite());
-    assert!(!inf.is_finite());
-    assert!(!neg_inf.is_finite());
-    assert!(0.0f64.is_finite());
-    assert!(42.8f64.is_finite());
-    assert!((-109.2f64).is_finite());
-}
-
-#[test]
-fn test_is_normal() {
-    let nan: f64 = f64::NAN;
-    let inf: f64 = f64::INFINITY;
-    let neg_inf: f64 = f64::NEG_INFINITY;
-    let zero: f64 = 0.0f64;
-    let neg_zero: f64 = -0.0;
-    assert!(!nan.is_normal());
-    assert!(!inf.is_normal());
-    assert!(!neg_inf.is_normal());
-    assert!(!zero.is_normal());
-    assert!(!neg_zero.is_normal());
-    assert!(1f64.is_normal());
-    assert!(1e-307f64.is_normal());
-    assert!(!1e-308f64.is_normal());
-}
-
-#[test]
-fn test_classify() {
-    let nan: f64 = f64::NAN;
-    let inf: f64 = f64::INFINITY;
-    let neg_inf: f64 = f64::NEG_INFINITY;
-    let zero: f64 = 0.0f64;
-    let neg_zero: f64 = -0.0;
-    assert_eq!(nan.classify(), Fp::Nan);
-    assert_eq!(inf.classify(), Fp::Infinite);
-    assert_eq!(neg_inf.classify(), Fp::Infinite);
-    assert_eq!(zero.classify(), Fp::Zero);
-    assert_eq!(neg_zero.classify(), Fp::Zero);
-    assert_eq!(1e-307f64.classify(), Fp::Normal);
-    assert_eq!(1e-308f64.classify(), Fp::Subnormal);
-}
-
-#[test]
 fn test_abs() {
     assert_biteq!(f64::INFINITY.abs(), f64::INFINITY);
     assert_biteq!(1f64.abs(), 1f64);
diff --git a/library/coretests/tests/floats/mod.rs b/library/coretests/tests/floats/mod.rs
index 36743a7d6df..43431bba695 100644
--- a/library/coretests/tests/floats/mod.rs
+++ b/library/coretests/tests/floats/mod.rs
@@ -1,28 +1,40 @@
-use std::fmt;
 use std::num::FpCategory as Fp;
 use std::ops::{Add, Div, Mul, Rem, Sub};
 
-/// Set the default tolerance for float comparison based on the type.
-trait Approx {
-    const LIM: Self;
+trait TestableFloat {
+    /// Set the default tolerance for float comparison based on the type.
+    const APPROX: Self;
+    const MIN_POSITIVE_NORMAL: Self;
+    const MAX_SUBNORMAL: Self;
 }
 
-impl Approx for f16 {
-    const LIM: Self = 1e-3;
+impl TestableFloat for f16 {
+    const APPROX: Self = 1e-3;
+    const MIN_POSITIVE_NORMAL: Self = Self::MIN_POSITIVE;
+    const MAX_SUBNORMAL: Self = Self::MIN_POSITIVE.next_down();
 }
-impl Approx for f32 {
-    const LIM: Self = 1e-6;
+
+impl TestableFloat for f32 {
+    const APPROX: Self = 1e-6;
+    const MIN_POSITIVE_NORMAL: Self = Self::MIN_POSITIVE;
+    const MAX_SUBNORMAL: Self = Self::MIN_POSITIVE.next_down();
 }
-impl Approx for f64 {
-    const LIM: Self = 1e-6;
+
+impl TestableFloat for f64 {
+    const APPROX: Self = 1e-6;
+    const MIN_POSITIVE_NORMAL: Self = Self::MIN_POSITIVE;
+    const MAX_SUBNORMAL: Self = Self::MIN_POSITIVE.next_down();
 }
-impl Approx for f128 {
-    const LIM: Self = 1e-9;
+
+impl TestableFloat for f128 {
+    const APPROX: Self = 1e-9;
+    const MIN_POSITIVE_NORMAL: Self = Self::MIN_POSITIVE;
+    const MAX_SUBNORMAL: Self = Self::MIN_POSITIVE.next_down();
 }
 
 /// Determine the tolerance for values of the argument type.
-const fn lim_for_ty<T: Approx + Copy>(_x: T) -> T {
-    T::LIM
+const fn lim_for_ty<T: TestableFloat + Copy>(_x: T) -> T {
+    T::APPROX
 }
 
 // We have runtime ("rt") and const versions of these macros.
@@ -187,9 +199,11 @@ macro_rules! float_test {
             $( $( #[$const_meta] )+ )?
             mod const_ {
                 #[allow(unused)]
-                use super::Approx;
+                use super::TestableFloat;
                 #[allow(unused)]
                 use std::num::FpCategory as Fp;
+                #[allow(unused)]
+                use std::ops::{Add, Div, Mul, Rem, Sub};
                 // Shadow the runtime versions of the macro with const-compatible versions.
                 #[allow(unused)]
                 use $crate::floats::{
@@ -229,31 +243,43 @@ macro_rules! float_test {
     };
 }
 
-/// Helper function for testing numeric operations
-pub fn test_num<T>(ten: T, two: T)
-where
-    T: PartialEq
-        + Add<Output = T>
-        + Sub<Output = T>
-        + Mul<Output = T>
-        + Div<Output = T>
-        + Rem<Output = T>
-        + fmt::Debug
-        + Copy,
-{
-    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_eq!(ten.rem(two), ten % two);
-}
-
 mod f128;
 mod f16;
 mod f32;
 mod f64;
 
 float_test! {
+    name: num,
+    attrs: {
+        f16: #[cfg(any(miri, target_has_reliable_f16))],
+        f128: #[cfg(any(miri, target_has_reliable_f128))],
+    },
+    test<Float> {
+        let two: Float = 2.0;
+        let ten: Float = 10.0;
+        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);
+    }
+}
+
+// FIXME(f16_f128): merge into `num` once the required `fmodl`/`fmodf128` function is available on
+// all platforms.
+float_test! {
+    name: num_rem,
+    attrs: {
+        f16: #[cfg(any(miri, target_has_reliable_f16_math))],
+        f128: #[cfg(any(miri, target_has_reliable_f128_math))],
+    },
+    test<Float> {
+        let two: Float = 2.0;
+        let ten: Float = 10.0;
+        assert_biteq!(ten.rem(two), ten % two);
+    }
+}
+
+float_test! {
     name: nan,
     attrs: {
         f16: #[cfg(any(miri, target_has_reliable_f16))],
@@ -274,6 +300,213 @@ float_test! {
 }
 
 float_test! {
+    name: infinity,
+    attrs: {
+        f16: #[cfg(any(miri, target_has_reliable_f16))],
+        f128: #[cfg(any(miri, target_has_reliable_f128))],
+    },
+    test<Float> {
+        let inf: Float = Float::INFINITY;
+        assert!(inf.is_infinite());
+        assert!(!inf.is_finite());
+        assert!(inf.is_sign_positive());
+        assert!(!inf.is_sign_negative());
+        assert!(!inf.is_nan());
+        assert!(!inf.is_normal());
+        assert!(matches!(inf.classify(), Fp::Infinite));
+    }
+}
+
+float_test! {
+    name: neg_infinity,
+    attrs: {
+        f16: #[cfg(any(miri, target_has_reliable_f16))],
+        f128: #[cfg(any(miri, target_has_reliable_f128))],
+    },
+    test<Float> {
+        let neg_inf: Float = Float::NEG_INFINITY;
+        assert!(neg_inf.is_infinite());
+        assert!(!neg_inf.is_finite());
+        assert!(!neg_inf.is_sign_positive());
+        assert!(neg_inf.is_sign_negative());
+        assert!(!neg_inf.is_nan());
+        assert!(!neg_inf.is_normal());
+        assert!(matches!(neg_inf.classify(), Fp::Infinite));
+    }
+}
+
+float_test! {
+    name: zero,
+    attrs: {
+        f16: #[cfg(any(miri, target_has_reliable_f16))],
+        f128: #[cfg(any(miri, target_has_reliable_f128))],
+    },
+    test<Float> {
+        let zero: Float = 0.0;
+        assert_biteq!(0.0, zero);
+        assert!(!zero.is_infinite());
+        assert!(zero.is_finite());
+        assert!(zero.is_sign_positive());
+        assert!(!zero.is_sign_negative());
+        assert!(!zero.is_nan());
+        assert!(!zero.is_normal());
+        assert!(matches!(zero.classify(), Fp::Zero));
+    }
+}
+
+float_test! {
+    name: neg_zero,
+    attrs: {
+        f16: #[cfg(any(miri, target_has_reliable_f16))],
+        f128: #[cfg(any(miri, target_has_reliable_f128))],
+    },
+    test<Float> {
+        let neg_zero: Float = -0.0;
+        assert!(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());
+        assert!(neg_zero.is_sign_negative());
+        assert!(!neg_zero.is_nan());
+        assert!(!neg_zero.is_normal());
+        assert!(matches!(neg_zero.classify(), Fp::Zero));
+    }
+}
+
+float_test! {
+    name: one,
+    attrs: {
+        f16: #[cfg(any(miri, target_has_reliable_f16))],
+        f128: #[cfg(any(miri, target_has_reliable_f128))],
+    },
+    test<Float> {
+        let one: Float = 1.0;
+        assert_biteq!(1.0, one);
+        assert!(!one.is_infinite());
+        assert!(one.is_finite());
+        assert!(one.is_sign_positive());
+        assert!(!one.is_sign_negative());
+        assert!(!one.is_nan());
+        assert!(one.is_normal());
+        assert!(matches!(one.classify(), Fp::Normal));
+    }
+}
+
+float_test! {
+    name: is_nan,
+    attrs: {
+        f16: #[cfg(any(miri, target_has_reliable_f16))],
+        f128: #[cfg(any(miri, target_has_reliable_f128))],
+    },
+    test<Float> {
+        let nan: Float = Float::NAN;
+        let inf: Float = Float::INFINITY;
+        let neg_inf: Float = Float::NEG_INFINITY;
+        let zero: Float = 0.0;
+        let pos: Float = 5.3;
+        let neg: Float = -10.732;
+        assert!(nan.is_nan());
+        assert!(!zero.is_nan());
+        assert!(!pos.is_nan());
+        assert!(!neg.is_nan());
+        assert!(!inf.is_nan());
+        assert!(!neg_inf.is_nan());
+    }
+}
+
+float_test! {
+    name: is_infinite,
+    attrs: {
+        f16: #[cfg(any(miri, target_has_reliable_f16))],
+        f128: #[cfg(any(miri, target_has_reliable_f128))],
+    },
+    test<Float> {
+        let nan: Float = Float::NAN;
+        let inf: Float = Float::INFINITY;
+        let neg_inf: Float = Float::NEG_INFINITY;
+        let zero: Float = 0.0;
+        let pos: Float = 42.8;
+        let neg: Float = -109.2;
+        assert!(!nan.is_infinite());
+        assert!(inf.is_infinite());
+        assert!(neg_inf.is_infinite());
+        assert!(!zero.is_infinite());
+        assert!(!pos.is_infinite());
+        assert!(!neg.is_infinite());
+    }
+}
+
+float_test! {
+    name: is_finite,
+    attrs: {
+        f16: #[cfg(any(miri, target_has_reliable_f16))],
+        f128: #[cfg(any(miri, target_has_reliable_f128))],
+    },
+    test<Float> {
+        let nan: Float = Float::NAN;
+        let inf: Float = Float::INFINITY;
+        let neg_inf: Float = Float::NEG_INFINITY;
+        let zero: Float = 0.0;
+        let pos: Float = 42.8;
+        let neg: Float = -109.2;
+        assert!(!nan.is_finite());
+        assert!(!inf.is_finite());
+        assert!(!neg_inf.is_finite());
+        assert!(zero.is_finite());
+        assert!(pos.is_finite());
+        assert!(neg.is_finite());
+    }
+}
+
+float_test! {
+    name: is_normal,
+    attrs: {
+        f16: #[cfg(any(miri, target_has_reliable_f16))],
+        f128: #[cfg(any(miri, target_has_reliable_f128))],
+    },
+    test<Float> {
+        let nan: Float = Float::NAN;
+        let inf: Float = Float::INFINITY;
+        let neg_inf: Float = Float::NEG_INFINITY;
+        let zero: Float = 0.0;
+        let neg_zero: Float = -0.0;
+        let one : Float = 1.0;
+        assert!(!nan.is_normal());
+        assert!(!inf.is_normal());
+        assert!(!neg_inf.is_normal());
+        assert!(!zero.is_normal());
+        assert!(!neg_zero.is_normal());
+        assert!(one.is_normal());
+        assert!(Float::MIN_POSITIVE_NORMAL.is_normal());
+        assert!(!Float::MAX_SUBNORMAL.is_normal());
+    }
+}
+
+float_test! {
+    name: classify,
+    attrs: {
+        f16: #[cfg(any(miri, target_has_reliable_f16))],
+    },
+    test<Float> {
+        let nan: Float = Float::NAN;
+        let inf: Float = Float::INFINITY;
+        let neg_inf: Float = Float::NEG_INFINITY;
+        let zero: Float = 0.0;
+        let neg_zero: Float = -0.0;
+        let one: Float = 1.0;
+        assert!(matches!(nan.classify(), Fp::Nan));
+        assert!(matches!(inf.classify(), Fp::Infinite));
+        assert!(matches!(neg_inf.classify(), Fp::Infinite));
+        assert!(matches!(zero.classify(), Fp::Zero));
+        assert!(matches!(neg_zero.classify(), Fp::Zero));
+        assert!(matches!(one.classify(), Fp::Normal));
+        assert!(matches!(Float::MIN_POSITIVE_NORMAL.classify(), Fp::Normal));
+        assert!(matches!(Float::MAX_SUBNORMAL.classify(), Fp::Subnormal));
+    }
+}
+
+float_test! {
     name: min,
     attrs: {
         f16: #[cfg(any(miri, target_has_reliable_f16_math))],
diff --git a/library/coretests/tests/lib.rs b/library/coretests/tests/lib.rs
index fdef736c0c0..e2249bd7f6a 100644
--- a/library/coretests/tests/lib.rs
+++ b/library/coretests/tests/lib.rs
@@ -20,6 +20,7 @@
 #![feature(const_destruct)]
 #![feature(const_eval_select)]
 #![feature(const_float_round_methods)]
+#![feature(const_ops)]
 #![feature(const_ref_cell)]
 #![feature(const_trait_impl)]
 #![feature(core_float_math)]