diff --git a/library/coretests/tests/floats/f128.rs b/library/coretests/tests/floats/f128.rs index 38df09a91c103..36d6a20a94427 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,160 +36,9 @@ 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() { diff --git a/library/coretests/tests/floats/f16.rs b/library/coretests/tests/floats/f16.rs index f6749d796cca9..351c008a37bab 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,151 +42,9 @@ 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() { diff --git a/library/coretests/tests/floats/f32.rs b/library/coretests/tests/floats/f32.rs index f5d5723fea455..267b0e4e29434 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}; @@ -30,148 +29,6 @@ const NAN_MASK2: u32 = 0x0055_5555; /// They serve as a way to get an idea of the real precision of floating point operations on different platforms. 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); diff --git a/library/coretests/tests/floats/f64.rs b/library/coretests/tests/floats/f64.rs index 34af87c241e91..735b7a7651519 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}; @@ -25,147 +24,6 @@ const NAN_MASK1: u64 = 0x000a_aaaa_aaaa_aaaa; /// Second pattern over the mantissa 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); diff --git a/library/coretests/tests/floats/mod.rs b/library/coretests/tests/floats/mod.rs index 36743a7d6df9e..43431bba6954b 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(_x: T) -> T { - T::LIM +const fn lim_for_ty(_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,30 +243,42 @@ macro_rules! float_test { }; } -/// Helper function for testing numeric operations -pub fn test_num(ten: T, two: T) -where - T: PartialEq - + Add - + Sub - + Mul - + Div - + Rem - + 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 { + 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 { + let two: Float = 2.0; + let ten: Float = 10.0; + assert_biteq!(ten.rem(two), ten % two); + } +} + float_test! { name: nan, attrs: { @@ -273,6 +299,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 { + 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 { + 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 { + 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 { + 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 { + 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 { + 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 { + 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 { + 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 { + 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 { + 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: { diff --git a/library/coretests/tests/lib.rs b/library/coretests/tests/lib.rs index fdef736c0c0f7..e2249bd7f6a11 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)]