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
This commit is contained in:
commit
0d2bf86284
2 changed files with 548 additions and 353 deletions
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue