Rollup merge of #146380 - rperier:unify_and_dedup_bits_conv_float_tests, r=tgross35
Unify and deduplicate bits conv float tests cc rust-lang/rust#141726 This is a proposal to unify and deduplicate the bits conv tests for f16, f32, f64 and f128
This commit is contained in:
commit
c69a792137
5 changed files with 63 additions and 110 deletions
|
|
@ -17,12 +17,6 @@ const TOL: f128 = 1e-12;
|
|||
#[allow(unused)]
|
||||
const TOL_PRECISE: f128 = 1e-28;
|
||||
|
||||
/// First pattern over the mantissa
|
||||
const NAN_MASK1: u128 = 0x0000aaaaaaaaaaaaaaaaaaaaaaaaaaaa;
|
||||
|
||||
/// Second pattern over the mantissa
|
||||
const NAN_MASK2: u128 = 0x00005555555555555555555555555555;
|
||||
|
||||
// FIXME(f16_f128,miri): many of these have to be disabled since miri does not yet support
|
||||
// the intrinsics.
|
||||
|
||||
|
|
@ -54,28 +48,6 @@ fn test_max_recip() {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_float_bits_conv() {
|
||||
assert_eq!((1f128).to_bits(), 0x3fff0000000000000000000000000000);
|
||||
assert_eq!((12.5f128).to_bits(), 0x40029000000000000000000000000000);
|
||||
assert_eq!((1337f128).to_bits(), 0x40094e40000000000000000000000000);
|
||||
assert_eq!((-14.25f128).to_bits(), 0xc002c800000000000000000000000000);
|
||||
assert_biteq!(f128::from_bits(0x3fff0000000000000000000000000000), 1.0);
|
||||
assert_biteq!(f128::from_bits(0x40029000000000000000000000000000), 12.5);
|
||||
assert_biteq!(f128::from_bits(0x40094e40000000000000000000000000), 1337.0);
|
||||
assert_biteq!(f128::from_bits(0xc002c800000000000000000000000000), -14.25);
|
||||
|
||||
// Check that NaNs roundtrip their bits regardless of signaling-ness
|
||||
// 0xA is 0b1010; 0x5 is 0b0101 -- so these two together clobbers all the mantissa bits
|
||||
let masked_nan1 = f128::NAN.to_bits() ^ NAN_MASK1;
|
||||
let masked_nan2 = f128::NAN.to_bits() ^ NAN_MASK2;
|
||||
assert!(f128::from_bits(masked_nan1).is_nan());
|
||||
assert!(f128::from_bits(masked_nan2).is_nan());
|
||||
|
||||
assert_eq!(f128::from_bits(masked_nan1).to_bits(), masked_nan1);
|
||||
assert_eq!(f128::from_bits(masked_nan2).to_bits(), masked_nan2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_from() {
|
||||
assert_biteq!(f128::from(false), 0.0);
|
||||
|
|
|
|||
|
|
@ -19,12 +19,6 @@ const TOL_P2: f16 = 0.5;
|
|||
#[allow(unused)]
|
||||
const TOL_P4: f16 = 10.0;
|
||||
|
||||
/// First pattern over the mantissa
|
||||
const NAN_MASK1: u16 = 0x02aa;
|
||||
|
||||
/// Second pattern over the mantissa
|
||||
const NAN_MASK2: u16 = 0x0155;
|
||||
|
||||
// FIXME(f16_f128,miri): many of these have to be disabled since miri does not yet support
|
||||
// the intrinsics.
|
||||
|
||||
|
|
@ -52,27 +46,6 @@ fn test_max_recip() {
|
|||
assert_approx_eq!(f16::MAX.recip(), 1.526624e-5f16, 1e-4);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_float_bits_conv() {
|
||||
assert_eq!((1f16).to_bits(), 0x3c00);
|
||||
assert_eq!((12.5f16).to_bits(), 0x4a40);
|
||||
assert_eq!((1337f16).to_bits(), 0x6539);
|
||||
assert_eq!((-14.25f16).to_bits(), 0xcb20);
|
||||
assert_biteq!(f16::from_bits(0x3c00), 1.0);
|
||||
assert_biteq!(f16::from_bits(0x4a40), 12.5);
|
||||
assert_biteq!(f16::from_bits(0x6539), 1337.0);
|
||||
assert_biteq!(f16::from_bits(0xcb20), -14.25);
|
||||
|
||||
// Check that NaNs roundtrip their bits regardless of signaling-ness
|
||||
let masked_nan1 = f16::NAN.to_bits() ^ NAN_MASK1;
|
||||
let masked_nan2 = f16::NAN.to_bits() ^ NAN_MASK2;
|
||||
assert!(f16::from_bits(masked_nan1).is_nan());
|
||||
assert!(f16::from_bits(masked_nan2).is_nan());
|
||||
|
||||
assert_eq!(f16::from_bits(masked_nan1).to_bits(), masked_nan1);
|
||||
assert_eq!(f16::from_bits(masked_nan2).to_bits(), masked_nan2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_from() {
|
||||
assert_biteq!(f16::from(false), 0.0);
|
||||
|
|
|
|||
|
|
@ -2,12 +2,6 @@ use core::f32;
|
|||
|
||||
use super::assert_biteq;
|
||||
|
||||
/// First pattern over the mantissa
|
||||
const NAN_MASK1: u32 = 0x002a_aaaa;
|
||||
|
||||
/// Second pattern over the mantissa
|
||||
const NAN_MASK2: u32 = 0x0055_5555;
|
||||
|
||||
// FIXME(#140515): mingw has an incorrect fma https://sourceforge.net/p/mingw-w64/bugs/848/
|
||||
#[cfg_attr(all(target_os = "windows", target_env = "gnu", not(target_abi = "llvm")), ignore)]
|
||||
#[test]
|
||||
|
|
@ -25,25 +19,3 @@ fn test_mul_add() {
|
|||
assert_biteq!(f32::math::mul_add(8.9f32, inf, 3.2), inf);
|
||||
assert_biteq!(f32::math::mul_add(-3.2f32, 2.4, neg_inf), neg_inf);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_float_bits_conv() {
|
||||
assert_eq!((1f32).to_bits(), 0x3f800000);
|
||||
assert_eq!((12.5f32).to_bits(), 0x41480000);
|
||||
assert_eq!((1337f32).to_bits(), 0x44a72000);
|
||||
assert_eq!((-14.25f32).to_bits(), 0xc1640000);
|
||||
assert_biteq!(f32::from_bits(0x3f800000), 1.0);
|
||||
assert_biteq!(f32::from_bits(0x41480000), 12.5);
|
||||
assert_biteq!(f32::from_bits(0x44a72000), 1337.0);
|
||||
assert_biteq!(f32::from_bits(0xc1640000), -14.25);
|
||||
|
||||
// Check that NaNs roundtrip their bits regardless of signaling-ness
|
||||
// 0xA is 0b1010; 0x5 is 0b0101 -- so these two together clobbers all the mantissa bits
|
||||
let masked_nan1 = f32::NAN.to_bits() ^ NAN_MASK1;
|
||||
let masked_nan2 = f32::NAN.to_bits() ^ NAN_MASK2;
|
||||
assert!(f32::from_bits(masked_nan1).is_nan());
|
||||
assert!(f32::from_bits(masked_nan2).is_nan());
|
||||
|
||||
assert_eq!(f32::from_bits(masked_nan1).to_bits(), masked_nan1);
|
||||
assert_eq!(f32::from_bits(masked_nan2).to_bits(), masked_nan2);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,12 +2,6 @@ use core::f64;
|
|||
|
||||
use super::assert_biteq;
|
||||
|
||||
/// First pattern over the mantissa
|
||||
const NAN_MASK1: u64 = 0x000a_aaaa_aaaa_aaaa;
|
||||
|
||||
/// Second pattern over the mantissa
|
||||
const NAN_MASK2: u64 = 0x0005_5555_5555_5555;
|
||||
|
||||
// FIXME(#140515): mingw has an incorrect fma https://sourceforge.net/p/mingw-w64/bugs/848/
|
||||
#[cfg_attr(all(target_os = "windows", target_env = "gnu", not(target_abi = "llvm")), ignore)]
|
||||
#[test]
|
||||
|
|
@ -25,24 +19,3 @@ fn test_mul_add() {
|
|||
assert_biteq!(8.9f64.mul_add(inf, 3.2), inf);
|
||||
assert_biteq!((-3.2f64).mul_add(2.4, neg_inf), neg_inf);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_float_bits_conv() {
|
||||
assert_eq!((1f64).to_bits(), 0x3ff0000000000000);
|
||||
assert_eq!((12.5f64).to_bits(), 0x4029000000000000);
|
||||
assert_eq!((1337f64).to_bits(), 0x4094e40000000000);
|
||||
assert_eq!((-14.25f64).to_bits(), 0xc02c800000000000);
|
||||
assert_biteq!(f64::from_bits(0x3ff0000000000000), 1.0);
|
||||
assert_biteq!(f64::from_bits(0x4029000000000000), 12.5);
|
||||
assert_biteq!(f64::from_bits(0x4094e40000000000), 1337.0);
|
||||
assert_biteq!(f64::from_bits(0xc02c800000000000), -14.25);
|
||||
|
||||
// Check that NaNs roundtrip their bits regardless of signaling-ness
|
||||
let masked_nan1 = f64::NAN.to_bits() ^ NAN_MASK1;
|
||||
let masked_nan2 = f64::NAN.to_bits() ^ NAN_MASK2;
|
||||
assert!(f64::from_bits(masked_nan1).is_nan());
|
||||
assert!(f64::from_bits(masked_nan2).is_nan());
|
||||
|
||||
assert_eq!(f64::from_bits(masked_nan1).to_bits(), masked_nan1);
|
||||
assert_eq!(f64::from_bits(masked_nan2).to_bits(), masked_nan2);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,6 +30,10 @@ trait TestableFloat: Sized {
|
|||
const EPS_ADD: Self;
|
||||
const EPS_MUL: Self;
|
||||
const EPS_DIV: Self;
|
||||
const RAW_1: Self;
|
||||
const RAW_12_DOT_5: Self;
|
||||
const RAW_1337: Self;
|
||||
const RAW_MINUS_14_DOT_25: Self;
|
||||
}
|
||||
|
||||
impl TestableFloat for f16 {
|
||||
|
|
@ -50,6 +54,10 @@ impl TestableFloat for f16 {
|
|||
const EPS_ADD: Self = if cfg!(miri) { 1e1 } else { 0.0 };
|
||||
const EPS_MUL: Self = if cfg!(miri) { 1e3 } else { 0.0 };
|
||||
const EPS_DIV: Self = if cfg!(miri) { 1e0 } else { 0.0 };
|
||||
const RAW_1: Self = Self::from_bits(0x3c00);
|
||||
const RAW_12_DOT_5: Self = Self::from_bits(0x4a40);
|
||||
const RAW_1337: Self = Self::from_bits(0x6539);
|
||||
const RAW_MINUS_14_DOT_25: Self = Self::from_bits(0xcb20);
|
||||
}
|
||||
|
||||
impl TestableFloat for f32 {
|
||||
|
|
@ -72,6 +80,10 @@ impl TestableFloat for f32 {
|
|||
const EPS_ADD: Self = if cfg!(miri) { 1e-3 } else { 0.0 };
|
||||
const EPS_MUL: Self = if cfg!(miri) { 1e-1 } else { 0.0 };
|
||||
const EPS_DIV: Self = if cfg!(miri) { 1e-4 } else { 0.0 };
|
||||
const RAW_1: Self = Self::from_bits(0x3f800000);
|
||||
const RAW_12_DOT_5: Self = Self::from_bits(0x41480000);
|
||||
const RAW_1337: Self = Self::from_bits(0x44a72000);
|
||||
const RAW_MINUS_14_DOT_25: Self = Self::from_bits(0xc1640000);
|
||||
}
|
||||
|
||||
impl TestableFloat for f64 {
|
||||
|
|
@ -90,6 +102,10 @@ impl TestableFloat for f64 {
|
|||
const EPS_ADD: Self = if cfg!(miri) { 1e-6 } else { 0.0 };
|
||||
const EPS_MUL: Self = if cfg!(miri) { 1e-6 } else { 0.0 };
|
||||
const EPS_DIV: Self = if cfg!(miri) { 1e-6 } else { 0.0 };
|
||||
const RAW_1: Self = Self::from_bits(0x3ff0000000000000);
|
||||
const RAW_12_DOT_5: Self = Self::from_bits(0x4029000000000000);
|
||||
const RAW_1337: Self = Self::from_bits(0x4094e40000000000);
|
||||
const RAW_MINUS_14_DOT_25: Self = Self::from_bits(0xc02c800000000000);
|
||||
}
|
||||
|
||||
impl TestableFloat for f128 {
|
||||
|
|
@ -108,6 +124,10 @@ impl TestableFloat for f128 {
|
|||
const EPS_ADD: Self = if cfg!(miri) { 1e-6 } else { 0.0 };
|
||||
const EPS_MUL: Self = if cfg!(miri) { 1e-6 } else { 0.0 };
|
||||
const EPS_DIV: Self = if cfg!(miri) { 1e-6 } else { 0.0 };
|
||||
const RAW_1: Self = Self::from_bits(0x3fff0000000000000000000000000000);
|
||||
const RAW_12_DOT_5: Self = Self::from_bits(0x40029000000000000000000000000000);
|
||||
const RAW_1337: Self = Self::from_bits(0x40094e40000000000000000000000000);
|
||||
const RAW_MINUS_14_DOT_25: Self = Self::from_bits(0xc002c800000000000000000000000000);
|
||||
}
|
||||
|
||||
/// Determine the tolerance for values of the argument type.
|
||||
|
|
@ -250,6 +270,8 @@ macro_rules! float_test {
|
|||
$( $( #[$f16_meta] )+ )?
|
||||
fn test_f16() {
|
||||
type $fty = f16;
|
||||
#[allow(unused)]
|
||||
const fn flt (x: $fty) -> $fty { x }
|
||||
$test
|
||||
}
|
||||
|
||||
|
|
@ -257,6 +279,8 @@ macro_rules! float_test {
|
|||
$( $( #[$f32_meta] )+ )?
|
||||
fn test_f32() {
|
||||
type $fty = f32;
|
||||
#[allow(unused)]
|
||||
const fn flt (x: $fty) -> $fty { x }
|
||||
$test
|
||||
}
|
||||
|
||||
|
|
@ -264,6 +288,8 @@ macro_rules! float_test {
|
|||
$( $( #[$f64_meta] )+ )?
|
||||
fn test_f64() {
|
||||
type $fty = f64;
|
||||
#[allow(unused)]
|
||||
const fn flt (x: $fty) -> $fty { x }
|
||||
$test
|
||||
}
|
||||
|
||||
|
|
@ -271,6 +297,8 @@ macro_rules! float_test {
|
|||
$( $( #[$f128_meta] )+ )?
|
||||
fn test_f128() {
|
||||
type $fty = f128;
|
||||
#[allow(unused)]
|
||||
const fn flt (x: $fty) -> $fty { x }
|
||||
$test
|
||||
}
|
||||
|
||||
|
|
@ -293,6 +321,8 @@ macro_rules! float_test {
|
|||
$( $( #[$f16_const_meta] )+ )?
|
||||
fn test_f16() {
|
||||
type $fty = f16;
|
||||
#[allow(unused)]
|
||||
const fn flt (x: $fty) -> $fty { x }
|
||||
const { $test }
|
||||
}
|
||||
|
||||
|
|
@ -300,6 +330,8 @@ macro_rules! float_test {
|
|||
$( $( #[$f32_const_meta] )+ )?
|
||||
fn test_f32() {
|
||||
type $fty = f32;
|
||||
#[allow(unused)]
|
||||
const fn flt (x: $fty) -> $fty { x }
|
||||
const { $test }
|
||||
}
|
||||
|
||||
|
|
@ -307,6 +339,8 @@ macro_rules! float_test {
|
|||
$( $( #[$f64_const_meta] )+ )?
|
||||
fn test_f64() {
|
||||
type $fty = f64;
|
||||
#[allow(unused)]
|
||||
const fn flt (x: $fty) -> $fty { x }
|
||||
const { $test }
|
||||
}
|
||||
|
||||
|
|
@ -314,6 +348,8 @@ macro_rules! float_test {
|
|||
$( $( #[$f128_const_meta] )+ )?
|
||||
fn test_f128() {
|
||||
type $fty = f128;
|
||||
#[allow(unused)]
|
||||
const fn flt (x: $fty) -> $fty { x }
|
||||
const { $test }
|
||||
}
|
||||
}
|
||||
|
|
@ -1479,3 +1515,30 @@ float_test! {
|
|||
assert_approx_eq!(a.algebraic_rem(b), a % b, Float::EPS_DIV);
|
||||
}
|
||||
}
|
||||
|
||||
float_test! {
|
||||
name: to_bits_conv,
|
||||
attrs: {
|
||||
f16: #[cfg(target_has_reliable_f16)],
|
||||
f128: #[cfg(target_has_reliable_f128)],
|
||||
},
|
||||
test<Float> {
|
||||
assert_biteq!(flt(1.0), Float::RAW_1);
|
||||
assert_biteq!(flt(12.5), Float::RAW_12_DOT_5);
|
||||
assert_biteq!(flt(1337.0), Float::RAW_1337);
|
||||
assert_biteq!(flt(-14.25), Float::RAW_MINUS_14_DOT_25);
|
||||
assert_biteq!(Float::RAW_1, 1.0);
|
||||
assert_biteq!(Float::RAW_12_DOT_5, 12.5);
|
||||
assert_biteq!(Float::RAW_1337, 1337.0);
|
||||
assert_biteq!(Float::RAW_MINUS_14_DOT_25, -14.25);
|
||||
|
||||
// Check that NaNs roundtrip their bits regardless of signaling-ness
|
||||
let masked_nan1 = Float::NAN.to_bits() ^ Float::NAN_MASK1;
|
||||
let masked_nan2 = Float::NAN.to_bits() ^ Float::NAN_MASK2;
|
||||
assert!(Float::from_bits(masked_nan1).is_nan());
|
||||
assert!(Float::from_bits(masked_nan2).is_nan());
|
||||
|
||||
assert_biteq!(Float::from_bits(masked_nan1), Float::from_bits(masked_nan1));
|
||||
assert_biteq!(Float::from_bits(masked_nan2), Float::from_bits(masked_nan2));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue