Rollup merge of #148206 - xonx4l:deduplicate-float-tests, r=tgross35
Deduplicated float tests and unified in floats/mod.rs In this PR Float tests are deduplicated and are unified in floats/mod.rs, as discussed in https://github.com/rust-lang/rust/issues/141726. The moved float tests are: -> test_powf -> test_exp -> test_exp2 -> test_ln -> test_log_generic -> test_log2 -> test_log10 -> test_asinh -> test_acosh -> test_atanh -> test_gamma -> test_ln_gamma Closes: https://github.com/rust-lang/rust/issues/141726
This commit is contained in:
commit
bff3e9edcc
10 changed files with 712 additions and 1346 deletions
File diff suppressed because it is too large
Load diff
|
|
@ -52,6 +52,8 @@
|
|||
#![feature(f16)]
|
||||
#![feature(f128)]
|
||||
#![feature(float_algebraic)]
|
||||
#![feature(float_bits_const)]
|
||||
#![feature(float_gamma)]
|
||||
#![feature(float_minimum_maximum)]
|
||||
#![feature(flt2dec)]
|
||||
#![feature(fmt_internals)]
|
||||
|
|
|
|||
|
|
@ -146,10 +146,6 @@ harness = false
|
|||
name = "sync"
|
||||
path = "tests/sync/lib.rs"
|
||||
|
||||
[[test]]
|
||||
name = "floats"
|
||||
path = "tests/floats/lib.rs"
|
||||
|
||||
[[test]]
|
||||
name = "thread_local"
|
||||
path = "tests/thread_local/lib.rs"
|
||||
|
|
|
|||
|
|
@ -1,320 +0,0 @@
|
|||
#![cfg(target_has_reliable_f128)]
|
||||
|
||||
use std::f128::consts;
|
||||
use std::ops::{Add, Div, Mul, Sub};
|
||||
|
||||
// Note these tolerances make sense around zero, but not for more extreme exponents.
|
||||
|
||||
/// Default tolerances. Works for values that should be near precise but not exact. Roughly
|
||||
/// the precision carried by `100 * 100`.
|
||||
#[cfg(not(miri))]
|
||||
#[cfg(target_has_reliable_f128_math)]
|
||||
const TOL: f128 = 1e-12;
|
||||
|
||||
/// For operations that are near exact, usually not involving math of different
|
||||
/// signs.
|
||||
const TOL_PRECISE: f128 = 1e-28;
|
||||
|
||||
/// Tolerances for math that is allowed to be imprecise, usually due to multiple chained
|
||||
/// operations.
|
||||
#[cfg(not(miri))]
|
||||
#[cfg(target_has_reliable_f128_math)]
|
||||
const TOL_IMPR: f128 = 1e-10;
|
||||
|
||||
/// Compare by representation
|
||||
#[allow(unused_macros)]
|
||||
macro_rules! assert_f128_biteq {
|
||||
($a:expr, $b:expr) => {
|
||||
let (l, r): (&f128, &f128) = (&$a, &$b);
|
||||
let lb = l.to_bits();
|
||||
let rb = r.to_bits();
|
||||
assert_eq!(lb, rb, "float {l:?} is not bitequal to {r:?}.\na: {lb:#034x}\nb: {rb:#034x}");
|
||||
};
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_num_f128() {
|
||||
// FIXME(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_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);
|
||||
}
|
||||
|
||||
// Many math functions allow for less accurate results, so the next tolerance up is used
|
||||
|
||||
#[test]
|
||||
#[cfg(not(miri))]
|
||||
#[cfg(target_has_reliable_f128_math)]
|
||||
fn test_powf() {
|
||||
let nan: f128 = f128::NAN;
|
||||
let inf: f128 = f128::INFINITY;
|
||||
let neg_inf: f128 = f128::NEG_INFINITY;
|
||||
assert_eq!(1.0f128.powf(1.0), 1.0);
|
||||
assert_approx_eq!(3.4f128.powf(4.5), 246.40818323761892815995637964326426756, TOL_IMPR);
|
||||
assert_approx_eq!(2.7f128.powf(-3.2), 0.041652009108526178281070304373500889273, TOL_IMPR);
|
||||
assert_approx_eq!((-3.1f128).powf(2.0), 9.6100000000000005506706202140776519387, TOL_IMPR);
|
||||
assert_approx_eq!(5.9f128.powf(-2.0), 0.028727377190462507313100483690639638451, TOL_IMPR);
|
||||
assert_eq!(8.3f128.powf(0.0), 1.0);
|
||||
assert!(nan.powf(2.0).is_nan());
|
||||
assert_eq!(inf.powf(2.0), inf);
|
||||
assert_eq!(neg_inf.powf(3.0), neg_inf);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(miri))]
|
||||
#[cfg(target_has_reliable_f128_math)]
|
||||
fn test_exp() {
|
||||
assert_eq!(1.0, 0.0f128.exp());
|
||||
assert_approx_eq!(consts::E, 1.0f128.exp(), TOL);
|
||||
assert_approx_eq!(148.41315910257660342111558004055227962348775, 5.0f128.exp(), TOL);
|
||||
|
||||
let inf: f128 = f128::INFINITY;
|
||||
let neg_inf: f128 = f128::NEG_INFINITY;
|
||||
let nan: f128 = f128::NAN;
|
||||
assert_eq!(inf, inf.exp());
|
||||
assert_eq!(0.0, neg_inf.exp());
|
||||
assert!(nan.exp().is_nan());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(miri))]
|
||||
#[cfg(target_has_reliable_f128_math)]
|
||||
fn test_exp2() {
|
||||
assert_eq!(32.0, 5.0f128.exp2());
|
||||
assert_eq!(1.0, 0.0f128.exp2());
|
||||
|
||||
let inf: f128 = f128::INFINITY;
|
||||
let neg_inf: f128 = f128::NEG_INFINITY;
|
||||
let nan: f128 = f128::NAN;
|
||||
assert_eq!(inf, inf.exp2());
|
||||
assert_eq!(0.0, neg_inf.exp2());
|
||||
assert!(nan.exp2().is_nan());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(miri))]
|
||||
#[cfg(target_has_reliable_f128_math)]
|
||||
fn test_ln() {
|
||||
let nan: f128 = f128::NAN;
|
||||
let inf: f128 = f128::INFINITY;
|
||||
let neg_inf: f128 = f128::NEG_INFINITY;
|
||||
assert_approx_eq!(1.0f128.exp().ln(), 1.0, TOL);
|
||||
assert!(nan.ln().is_nan());
|
||||
assert_eq!(inf.ln(), inf);
|
||||
assert!(neg_inf.ln().is_nan());
|
||||
assert!((-2.3f128).ln().is_nan());
|
||||
assert_eq!((-0.0f128).ln(), neg_inf);
|
||||
assert_eq!(0.0f128.ln(), neg_inf);
|
||||
assert_approx_eq!(4.0f128.ln(), 1.3862943611198906188344642429163531366, TOL);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(miri))]
|
||||
#[cfg(target_has_reliable_f128_math)]
|
||||
fn test_log() {
|
||||
let nan: f128 = f128::NAN;
|
||||
let inf: f128 = f128::INFINITY;
|
||||
let neg_inf: f128 = f128::NEG_INFINITY;
|
||||
assert_eq!(10.0f128.log(10.0), 1.0);
|
||||
assert_approx_eq!(2.3f128.log(3.5), 0.66485771361478710036766645911922010272, TOL);
|
||||
assert_eq!(1.0f128.exp().log(1.0f128.exp()), 1.0);
|
||||
assert!(1.0f128.log(1.0).is_nan());
|
||||
assert!(1.0f128.log(-13.9).is_nan());
|
||||
assert!(nan.log(2.3).is_nan());
|
||||
assert_eq!(inf.log(10.0), inf);
|
||||
assert!(neg_inf.log(8.8).is_nan());
|
||||
assert!((-2.3f128).log(0.1).is_nan());
|
||||
assert_eq!((-0.0f128).log(2.0), neg_inf);
|
||||
assert_eq!(0.0f128.log(7.0), neg_inf);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(miri))]
|
||||
#[cfg(target_has_reliable_f128_math)]
|
||||
fn test_log2() {
|
||||
let nan: f128 = f128::NAN;
|
||||
let inf: f128 = f128::INFINITY;
|
||||
let neg_inf: f128 = f128::NEG_INFINITY;
|
||||
assert_approx_eq!(10.0f128.log2(), 3.32192809488736234787031942948939017, TOL);
|
||||
assert_approx_eq!(2.3f128.log2(), 1.2016338611696504130002982471978765921, TOL);
|
||||
assert_approx_eq!(1.0f128.exp().log2(), 1.4426950408889634073599246810018921381, TOL);
|
||||
assert!(nan.log2().is_nan());
|
||||
assert_eq!(inf.log2(), inf);
|
||||
assert!(neg_inf.log2().is_nan());
|
||||
assert!((-2.3f128).log2().is_nan());
|
||||
assert_eq!((-0.0f128).log2(), neg_inf);
|
||||
assert_eq!(0.0f128.log2(), neg_inf);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(miri))]
|
||||
#[cfg(target_has_reliable_f128_math)]
|
||||
fn test_log10() {
|
||||
let nan: f128 = f128::NAN;
|
||||
let inf: f128 = f128::INFINITY;
|
||||
let neg_inf: f128 = f128::NEG_INFINITY;
|
||||
assert_eq!(10.0f128.log10(), 1.0);
|
||||
assert_approx_eq!(2.3f128.log10(), 0.36172783601759284532595218865859309898, TOL);
|
||||
assert_approx_eq!(1.0f128.exp().log10(), 0.43429448190325182765112891891660508222, TOL);
|
||||
assert_eq!(1.0f128.log10(), 0.0);
|
||||
assert!(nan.log10().is_nan());
|
||||
assert_eq!(inf.log10(), inf);
|
||||
assert!(neg_inf.log10().is_nan());
|
||||
assert!((-2.3f128).log10().is_nan());
|
||||
assert_eq!((-0.0f128).log10(), neg_inf);
|
||||
assert_eq!(0.0f128.log10(), neg_inf);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(miri))]
|
||||
#[cfg(target_has_reliable_f128_math)]
|
||||
fn test_asinh() {
|
||||
// Lower accuracy results are allowed, use increased tolerances
|
||||
assert_eq!(0.0f128.asinh(), 0.0f128);
|
||||
assert_eq!((-0.0f128).asinh(), -0.0f128);
|
||||
|
||||
let inf: f128 = f128::INFINITY;
|
||||
let neg_inf: f128 = f128::NEG_INFINITY;
|
||||
let nan: f128 = f128::NAN;
|
||||
assert_eq!(inf.asinh(), inf);
|
||||
assert_eq!(neg_inf.asinh(), neg_inf);
|
||||
assert!(nan.asinh().is_nan());
|
||||
assert!((-0.0f128).asinh().is_sign_negative());
|
||||
|
||||
// issue 63271
|
||||
assert_approx_eq!(2.0f128.asinh(), 1.443635475178810342493276740273105f128, TOL_IMPR);
|
||||
assert_approx_eq!((-2.0f128).asinh(), -1.443635475178810342493276740273105f128, TOL_IMPR);
|
||||
// regression test for the catastrophic cancellation fixed in 72486
|
||||
assert_approx_eq!(
|
||||
(-67452098.07139316f128).asinh(),
|
||||
-18.720075426274544393985484294000831757220,
|
||||
TOL_IMPR
|
||||
);
|
||||
|
||||
// test for low accuracy from issue 104548
|
||||
assert_approx_eq!(60.0f128, 60.0f128.sinh().asinh(), TOL_IMPR);
|
||||
// mul needed for approximate comparison to be meaningful
|
||||
assert_approx_eq!(1.0f128, 1e-15f128.sinh().asinh() * 1e15f128, TOL_IMPR);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(miri))]
|
||||
#[cfg(target_has_reliable_f128_math)]
|
||||
fn test_acosh() {
|
||||
assert_eq!(1.0f128.acosh(), 0.0f128);
|
||||
assert!(0.999f128.acosh().is_nan());
|
||||
|
||||
let inf: f128 = f128::INFINITY;
|
||||
let neg_inf: f128 = f128::NEG_INFINITY;
|
||||
let nan: f128 = f128::NAN;
|
||||
assert_eq!(inf.acosh(), inf);
|
||||
assert!(neg_inf.acosh().is_nan());
|
||||
assert!(nan.acosh().is_nan());
|
||||
assert_approx_eq!(2.0f128.acosh(), 1.31695789692481670862504634730796844f128, TOL_IMPR);
|
||||
assert_approx_eq!(3.0f128.acosh(), 1.76274717403908605046521864995958461f128, TOL_IMPR);
|
||||
|
||||
// test for low accuracy from issue 104548
|
||||
assert_approx_eq!(60.0f128, 60.0f128.cosh().acosh(), TOL_IMPR);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(miri))]
|
||||
#[cfg(target_has_reliable_f128_math)]
|
||||
fn test_atanh() {
|
||||
assert_eq!(0.0f128.atanh(), 0.0f128);
|
||||
assert_eq!((-0.0f128).atanh(), -0.0f128);
|
||||
|
||||
let inf: f128 = f128::INFINITY;
|
||||
let neg_inf: f128 = f128::NEG_INFINITY;
|
||||
let nan: f128 = f128::NAN;
|
||||
assert_eq!(1.0f128.atanh(), inf);
|
||||
assert_eq!((-1.0f128).atanh(), neg_inf);
|
||||
assert!(2f128.atanh().atanh().is_nan());
|
||||
assert!((-2f128).atanh().atanh().is_nan());
|
||||
assert!(inf.atanh().is_nan());
|
||||
assert!(neg_inf.atanh().is_nan());
|
||||
assert!(nan.atanh().is_nan());
|
||||
assert_approx_eq!(0.5f128.atanh(), 0.54930614433405484569762261846126285f128, TOL_IMPR);
|
||||
assert_approx_eq!((-0.5f128).atanh(), -0.54930614433405484569762261846126285f128, TOL_IMPR);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(miri))]
|
||||
#[cfg(target_has_reliable_f128_math)]
|
||||
fn test_gamma() {
|
||||
// precision can differ among platforms
|
||||
assert_approx_eq!(1.0f128.gamma(), 1.0f128, TOL_IMPR);
|
||||
assert_approx_eq!(2.0f128.gamma(), 1.0f128, TOL_IMPR);
|
||||
assert_approx_eq!(3.0f128.gamma(), 2.0f128, TOL_IMPR);
|
||||
assert_approx_eq!(4.0f128.gamma(), 6.0f128, TOL_IMPR);
|
||||
assert_approx_eq!(5.0f128.gamma(), 24.0f128, TOL_IMPR);
|
||||
assert_approx_eq!(0.5f128.gamma(), consts::PI.sqrt(), TOL_IMPR);
|
||||
assert_approx_eq!((-0.5f128).gamma(), -2.0 * consts::PI.sqrt(), TOL_IMPR);
|
||||
assert_eq!(0.0f128.gamma(), f128::INFINITY);
|
||||
assert_eq!((-0.0f128).gamma(), f128::NEG_INFINITY);
|
||||
assert!((-1.0f128).gamma().is_nan());
|
||||
assert!((-2.0f128).gamma().is_nan());
|
||||
assert!(f128::NAN.gamma().is_nan());
|
||||
assert!(f128::NEG_INFINITY.gamma().is_nan());
|
||||
assert_eq!(f128::INFINITY.gamma(), f128::INFINITY);
|
||||
assert_eq!(1760.9f128.gamma(), f128::INFINITY);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(miri))]
|
||||
#[cfg(target_has_reliable_f128_math)]
|
||||
fn test_ln_gamma() {
|
||||
assert_approx_eq!(1.0f128.ln_gamma().0, 0.0f128, TOL_IMPR);
|
||||
assert_eq!(1.0f128.ln_gamma().1, 1);
|
||||
assert_approx_eq!(2.0f128.ln_gamma().0, 0.0f128, TOL_IMPR);
|
||||
assert_eq!(2.0f128.ln_gamma().1, 1);
|
||||
assert_approx_eq!(3.0f128.ln_gamma().0, 2.0f128.ln(), TOL_IMPR);
|
||||
assert_eq!(3.0f128.ln_gamma().1, 1);
|
||||
assert_approx_eq!((-0.5f128).ln_gamma().0, (2.0 * consts::PI.sqrt()).ln(), TOL_IMPR);
|
||||
assert_eq!((-0.5f128).ln_gamma().1, -1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_real_consts() {
|
||||
let pi: f128 = consts::PI;
|
||||
let frac_pi_2: f128 = consts::FRAC_PI_2;
|
||||
let frac_pi_3: f128 = consts::FRAC_PI_3;
|
||||
let frac_pi_4: f128 = consts::FRAC_PI_4;
|
||||
let frac_pi_6: f128 = consts::FRAC_PI_6;
|
||||
let frac_pi_8: f128 = consts::FRAC_PI_8;
|
||||
let frac_1_pi: f128 = consts::FRAC_1_PI;
|
||||
let frac_2_pi: f128 = consts::FRAC_2_PI;
|
||||
|
||||
assert_approx_eq!(frac_pi_2, pi / 2f128, TOL_PRECISE);
|
||||
assert_approx_eq!(frac_pi_3, pi / 3f128, TOL_PRECISE);
|
||||
assert_approx_eq!(frac_pi_4, pi / 4f128, TOL_PRECISE);
|
||||
assert_approx_eq!(frac_pi_6, pi / 6f128, TOL_PRECISE);
|
||||
assert_approx_eq!(frac_pi_8, pi / 8f128, TOL_PRECISE);
|
||||
assert_approx_eq!(frac_1_pi, 1f128 / pi, TOL_PRECISE);
|
||||
assert_approx_eq!(frac_2_pi, 2f128 / pi, TOL_PRECISE);
|
||||
|
||||
#[cfg(not(miri))]
|
||||
#[cfg(target_has_reliable_f128_math)]
|
||||
{
|
||||
let frac_2_sqrtpi: f128 = consts::FRAC_2_SQRT_PI;
|
||||
let sqrt2: f128 = consts::SQRT_2;
|
||||
let frac_1_sqrt2: f128 = consts::FRAC_1_SQRT_2;
|
||||
let e: f128 = consts::E;
|
||||
let log2_e: f128 = consts::LOG2_E;
|
||||
let log10_e: f128 = consts::LOG10_E;
|
||||
let ln_2: f128 = consts::LN_2;
|
||||
let ln_10: f128 = consts::LN_10;
|
||||
|
||||
assert_approx_eq!(frac_2_sqrtpi, 2f128 / pi.sqrt(), TOL_PRECISE);
|
||||
assert_approx_eq!(sqrt2, 2f128.sqrt(), TOL_PRECISE);
|
||||
assert_approx_eq!(frac_1_sqrt2, 1f128 / 2f128.sqrt(), TOL_PRECISE);
|
||||
assert_approx_eq!(log2_e, e.log2(), TOL_PRECISE);
|
||||
assert_approx_eq!(log10_e, e.log10(), TOL_PRECISE);
|
||||
assert_approx_eq!(ln_2, 2f128.ln(), TOL_PRECISE);
|
||||
assert_approx_eq!(ln_10, 10f128.ln(), TOL_PRECISE);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,297 +0,0 @@
|
|||
#![cfg(target_has_reliable_f16)]
|
||||
|
||||
use std::f16::consts;
|
||||
|
||||
/// Tolerance for results on the order of 10.0e-2
|
||||
#[allow(unused)]
|
||||
const TOL_N2: f16 = 0.0001;
|
||||
|
||||
/// Tolerance for results on the order of 10.0e+0
|
||||
#[allow(unused)]
|
||||
const TOL_0: f16 = 0.01;
|
||||
|
||||
/// Tolerance for results on the order of 10.0e+2
|
||||
#[allow(unused)]
|
||||
const TOL_P2: f16 = 0.5;
|
||||
|
||||
/// Tolerance for results on the order of 10.0e+4
|
||||
#[allow(unused)]
|
||||
const TOL_P4: f16 = 10.0;
|
||||
|
||||
/// Compare by representation
|
||||
#[allow(unused_macros)]
|
||||
macro_rules! assert_f16_biteq {
|
||||
($a:expr, $b:expr) => {
|
||||
let (l, r): (&f16, &f16) = (&$a, &$b);
|
||||
let lb = l.to_bits();
|
||||
let rb = r.to_bits();
|
||||
assert_eq!(lb, rb, "float {l:?} ({lb:#04x}) is not bitequal to {r:?} ({rb:#04x})");
|
||||
};
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(miri))]
|
||||
#[cfg(target_has_reliable_f16_math)]
|
||||
fn test_powf() {
|
||||
let nan: f16 = f16::NAN;
|
||||
let inf: f16 = f16::INFINITY;
|
||||
let neg_inf: f16 = f16::NEG_INFINITY;
|
||||
assert_eq!(1.0f16.powf(1.0), 1.0);
|
||||
assert_approx_eq!(3.4f16.powf(4.5), 246.408183, TOL_P2);
|
||||
assert_approx_eq!(2.7f16.powf(-3.2), 0.041652, TOL_N2);
|
||||
assert_approx_eq!((-3.1f16).powf(2.0), 9.61, TOL_P2);
|
||||
assert_approx_eq!(5.9f16.powf(-2.0), 0.028727, TOL_N2);
|
||||
assert_eq!(8.3f16.powf(0.0), 1.0);
|
||||
assert!(nan.powf(2.0).is_nan());
|
||||
assert_eq!(inf.powf(2.0), inf);
|
||||
assert_eq!(neg_inf.powf(3.0), neg_inf);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(miri))]
|
||||
#[cfg(target_has_reliable_f16_math)]
|
||||
fn test_exp() {
|
||||
assert_eq!(1.0, 0.0f16.exp());
|
||||
assert_approx_eq!(2.718282, 1.0f16.exp(), TOL_0);
|
||||
assert_approx_eq!(148.413159, 5.0f16.exp(), TOL_0);
|
||||
|
||||
let inf: f16 = f16::INFINITY;
|
||||
let neg_inf: f16 = f16::NEG_INFINITY;
|
||||
let nan: f16 = f16::NAN;
|
||||
assert_eq!(inf, inf.exp());
|
||||
assert_eq!(0.0, neg_inf.exp());
|
||||
assert!(nan.exp().is_nan());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(miri))]
|
||||
#[cfg(target_has_reliable_f16_math)]
|
||||
fn test_exp2() {
|
||||
assert_eq!(32.0, 5.0f16.exp2());
|
||||
assert_eq!(1.0, 0.0f16.exp2());
|
||||
|
||||
let inf: f16 = f16::INFINITY;
|
||||
let neg_inf: f16 = f16::NEG_INFINITY;
|
||||
let nan: f16 = f16::NAN;
|
||||
assert_eq!(inf, inf.exp2());
|
||||
assert_eq!(0.0, neg_inf.exp2());
|
||||
assert!(nan.exp2().is_nan());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(miri))]
|
||||
#[cfg(target_has_reliable_f16_math)]
|
||||
fn test_ln() {
|
||||
let nan: f16 = f16::NAN;
|
||||
let inf: f16 = f16::INFINITY;
|
||||
let neg_inf: f16 = f16::NEG_INFINITY;
|
||||
assert_approx_eq!(1.0f16.exp().ln(), 1.0, TOL_0);
|
||||
assert!(nan.ln().is_nan());
|
||||
assert_eq!(inf.ln(), inf);
|
||||
assert!(neg_inf.ln().is_nan());
|
||||
assert!((-2.3f16).ln().is_nan());
|
||||
assert_eq!((-0.0f16).ln(), neg_inf);
|
||||
assert_eq!(0.0f16.ln(), neg_inf);
|
||||
assert_approx_eq!(4.0f16.ln(), 1.386294, TOL_0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(miri))]
|
||||
#[cfg(target_has_reliable_f16_math)]
|
||||
fn test_log() {
|
||||
let nan: f16 = f16::NAN;
|
||||
let inf: f16 = f16::INFINITY;
|
||||
let neg_inf: f16 = f16::NEG_INFINITY;
|
||||
assert_eq!(10.0f16.log(10.0), 1.0);
|
||||
assert_approx_eq!(2.3f16.log(3.5), 0.664858, TOL_0);
|
||||
assert_eq!(1.0f16.exp().log(1.0f16.exp()), 1.0);
|
||||
assert!(1.0f16.log(1.0).is_nan());
|
||||
assert!(1.0f16.log(-13.9).is_nan());
|
||||
assert!(nan.log(2.3).is_nan());
|
||||
assert_eq!(inf.log(10.0), inf);
|
||||
assert!(neg_inf.log(8.8).is_nan());
|
||||
assert!((-2.3f16).log(0.1).is_nan());
|
||||
assert_eq!((-0.0f16).log(2.0), neg_inf);
|
||||
assert_eq!(0.0f16.log(7.0), neg_inf);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(miri))]
|
||||
#[cfg(target_has_reliable_f16_math)]
|
||||
fn test_log2() {
|
||||
let nan: f16 = f16::NAN;
|
||||
let inf: f16 = f16::INFINITY;
|
||||
let neg_inf: f16 = f16::NEG_INFINITY;
|
||||
assert_approx_eq!(10.0f16.log2(), 3.321928, TOL_0);
|
||||
assert_approx_eq!(2.3f16.log2(), 1.201634, TOL_0);
|
||||
assert_approx_eq!(1.0f16.exp().log2(), 1.442695, TOL_0);
|
||||
assert!(nan.log2().is_nan());
|
||||
assert_eq!(inf.log2(), inf);
|
||||
assert!(neg_inf.log2().is_nan());
|
||||
assert!((-2.3f16).log2().is_nan());
|
||||
assert_eq!((-0.0f16).log2(), neg_inf);
|
||||
assert_eq!(0.0f16.log2(), neg_inf);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(miri))]
|
||||
#[cfg(target_has_reliable_f16_math)]
|
||||
fn test_log10() {
|
||||
let nan: f16 = f16::NAN;
|
||||
let inf: f16 = f16::INFINITY;
|
||||
let neg_inf: f16 = f16::NEG_INFINITY;
|
||||
assert_eq!(10.0f16.log10(), 1.0);
|
||||
assert_approx_eq!(2.3f16.log10(), 0.361728, TOL_0);
|
||||
assert_approx_eq!(1.0f16.exp().log10(), 0.434294, TOL_0);
|
||||
assert_eq!(1.0f16.log10(), 0.0);
|
||||
assert!(nan.log10().is_nan());
|
||||
assert_eq!(inf.log10(), inf);
|
||||
assert!(neg_inf.log10().is_nan());
|
||||
assert!((-2.3f16).log10().is_nan());
|
||||
assert_eq!((-0.0f16).log10(), neg_inf);
|
||||
assert_eq!(0.0f16.log10(), neg_inf);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(miri))]
|
||||
#[cfg(target_has_reliable_f16_math)]
|
||||
fn test_asinh() {
|
||||
assert_eq!(0.0f16.asinh(), 0.0f16);
|
||||
assert_eq!((-0.0f16).asinh(), -0.0f16);
|
||||
|
||||
let inf: f16 = f16::INFINITY;
|
||||
let neg_inf: f16 = f16::NEG_INFINITY;
|
||||
let nan: f16 = f16::NAN;
|
||||
assert_eq!(inf.asinh(), inf);
|
||||
assert_eq!(neg_inf.asinh(), neg_inf);
|
||||
assert!(nan.asinh().is_nan());
|
||||
assert!((-0.0f16).asinh().is_sign_negative());
|
||||
// issue 63271
|
||||
assert_approx_eq!(2.0f16.asinh(), 1.443635475178810342493276740273105f16, TOL_0);
|
||||
assert_approx_eq!((-2.0f16).asinh(), -1.443635475178810342493276740273105f16, TOL_0);
|
||||
// regression test for the catastrophic cancellation fixed in 72486
|
||||
assert_approx_eq!((-200.0f16).asinh(), -5.991470797049389, TOL_0);
|
||||
|
||||
// test for low accuracy from issue 104548
|
||||
assert_approx_eq!(10.0f16, 10.0f16.sinh().asinh(), TOL_0);
|
||||
// mul needed for approximate comparison to be meaningful
|
||||
assert_approx_eq!(1.0f16, 1e-3f16.sinh().asinh() * 1e3f16, TOL_0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(miri))]
|
||||
#[cfg(target_has_reliable_f16_math)]
|
||||
fn test_acosh() {
|
||||
assert_eq!(1.0f16.acosh(), 0.0f16);
|
||||
assert!(0.999f16.acosh().is_nan());
|
||||
|
||||
let inf: f16 = f16::INFINITY;
|
||||
let neg_inf: f16 = f16::NEG_INFINITY;
|
||||
let nan: f16 = f16::NAN;
|
||||
assert_eq!(inf.acosh(), inf);
|
||||
assert!(neg_inf.acosh().is_nan());
|
||||
assert!(nan.acosh().is_nan());
|
||||
assert_approx_eq!(2.0f16.acosh(), 1.31695789692481670862504634730796844f16, TOL_0);
|
||||
assert_approx_eq!(3.0f16.acosh(), 1.76274717403908605046521864995958461f16, TOL_0);
|
||||
|
||||
// test for low accuracy from issue 104548
|
||||
assert_approx_eq!(10.0f16, 10.0f16.cosh().acosh(), TOL_P2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(miri))]
|
||||
#[cfg(target_has_reliable_f16_math)]
|
||||
fn test_atanh() {
|
||||
assert_eq!(0.0f16.atanh(), 0.0f16);
|
||||
assert_eq!((-0.0f16).atanh(), -0.0f16);
|
||||
|
||||
let inf: f16 = f16::INFINITY;
|
||||
let neg_inf: f16 = f16::NEG_INFINITY;
|
||||
let nan: f16 = f16::NAN;
|
||||
assert_eq!(1.0f16.atanh(), inf);
|
||||
assert_eq!((-1.0f16).atanh(), neg_inf);
|
||||
assert!(2f16.atanh().atanh().is_nan());
|
||||
assert!((-2f16).atanh().atanh().is_nan());
|
||||
assert!(inf.atanh().is_nan());
|
||||
assert!(neg_inf.atanh().is_nan());
|
||||
assert!(nan.atanh().is_nan());
|
||||
assert_approx_eq!(0.5f16.atanh(), 0.54930614433405484569762261846126285f16, TOL_0);
|
||||
assert_approx_eq!((-0.5f16).atanh(), -0.54930614433405484569762261846126285f16, TOL_0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(miri))]
|
||||
#[cfg(target_has_reliable_f16_math)]
|
||||
fn test_gamma() {
|
||||
// precision can differ among platforms
|
||||
assert_approx_eq!(1.0f16.gamma(), 1.0f16, TOL_0);
|
||||
assert_approx_eq!(2.0f16.gamma(), 1.0f16, TOL_0);
|
||||
assert_approx_eq!(3.0f16.gamma(), 2.0f16, TOL_0);
|
||||
assert_approx_eq!(4.0f16.gamma(), 6.0f16, TOL_0);
|
||||
assert_approx_eq!(5.0f16.gamma(), 24.0f16, TOL_0);
|
||||
assert_approx_eq!(0.5f16.gamma(), consts::PI.sqrt(), TOL_0);
|
||||
assert_approx_eq!((-0.5f16).gamma(), -2.0 * consts::PI.sqrt(), TOL_0);
|
||||
assert_eq!(0.0f16.gamma(), f16::INFINITY);
|
||||
assert_eq!((-0.0f16).gamma(), f16::NEG_INFINITY);
|
||||
assert!((-1.0f16).gamma().is_nan());
|
||||
assert!((-2.0f16).gamma().is_nan());
|
||||
assert!(f16::NAN.gamma().is_nan());
|
||||
assert!(f16::NEG_INFINITY.gamma().is_nan());
|
||||
assert_eq!(f16::INFINITY.gamma(), f16::INFINITY);
|
||||
assert_eq!(171.71f16.gamma(), f16::INFINITY);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(miri))]
|
||||
#[cfg(target_has_reliable_f16_math)]
|
||||
fn test_ln_gamma() {
|
||||
assert_approx_eq!(1.0f16.ln_gamma().0, 0.0f16, TOL_0);
|
||||
assert_eq!(1.0f16.ln_gamma().1, 1);
|
||||
assert_approx_eq!(2.0f16.ln_gamma().0, 0.0f16, TOL_0);
|
||||
assert_eq!(2.0f16.ln_gamma().1, 1);
|
||||
assert_approx_eq!(3.0f16.ln_gamma().0, 2.0f16.ln(), TOL_0);
|
||||
assert_eq!(3.0f16.ln_gamma().1, 1);
|
||||
assert_approx_eq!((-0.5f16).ln_gamma().0, (2.0 * consts::PI.sqrt()).ln(), TOL_0);
|
||||
assert_eq!((-0.5f16).ln_gamma().1, -1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_real_consts() {
|
||||
let pi: f16 = consts::PI;
|
||||
let frac_pi_2: f16 = consts::FRAC_PI_2;
|
||||
let frac_pi_3: f16 = consts::FRAC_PI_3;
|
||||
let frac_pi_4: f16 = consts::FRAC_PI_4;
|
||||
let frac_pi_6: f16 = consts::FRAC_PI_6;
|
||||
let frac_pi_8: f16 = consts::FRAC_PI_8;
|
||||
let frac_1_pi: f16 = consts::FRAC_1_PI;
|
||||
let frac_2_pi: f16 = consts::FRAC_2_PI;
|
||||
|
||||
assert_approx_eq!(frac_pi_2, pi / 2f16, TOL_0);
|
||||
assert_approx_eq!(frac_pi_3, pi / 3f16, TOL_0);
|
||||
assert_approx_eq!(frac_pi_4, pi / 4f16, TOL_0);
|
||||
assert_approx_eq!(frac_pi_6, pi / 6f16, TOL_0);
|
||||
assert_approx_eq!(frac_pi_8, pi / 8f16, TOL_0);
|
||||
assert_approx_eq!(frac_1_pi, 1f16 / pi, TOL_0);
|
||||
assert_approx_eq!(frac_2_pi, 2f16 / pi, TOL_0);
|
||||
|
||||
#[cfg(not(miri))]
|
||||
#[cfg(target_has_reliable_f16_math)]
|
||||
{
|
||||
let frac_2_sqrtpi: f16 = consts::FRAC_2_SQRT_PI;
|
||||
let sqrt2: f16 = consts::SQRT_2;
|
||||
let frac_1_sqrt2: f16 = consts::FRAC_1_SQRT_2;
|
||||
let e: f16 = consts::E;
|
||||
let log2_e: f16 = consts::LOG2_E;
|
||||
let log10_e: f16 = consts::LOG10_E;
|
||||
let ln_2: f16 = consts::LN_2;
|
||||
let ln_10: f16 = consts::LN_10;
|
||||
|
||||
assert_approx_eq!(frac_2_sqrtpi, 2f16 / pi.sqrt(), TOL_0);
|
||||
assert_approx_eq!(sqrt2, 2f16.sqrt(), TOL_0);
|
||||
assert_approx_eq!(frac_1_sqrt2, 1f16 / 2f16.sqrt(), TOL_0);
|
||||
assert_approx_eq!(log2_e, e.log2(), TOL_0);
|
||||
assert_approx_eq!(log10_e, e.log10(), TOL_0);
|
||||
assert_approx_eq!(ln_2, 2f16.ln(), TOL_0);
|
||||
assert_approx_eq!(ln_10, 10f16.ln(), TOL_0);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,258 +0,0 @@
|
|||
use std::f32::consts;
|
||||
|
||||
/// Miri adds some extra errors to float functions; make sure the tests still pass.
|
||||
/// These values are purely used as a canary to test against and are thus not a stable guarantee Rust provides.
|
||||
/// 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-3 } else { 1e-6 };
|
||||
|
||||
#[allow(unused_macros)]
|
||||
macro_rules! assert_f32_biteq {
|
||||
($left : expr, $right : expr) => {
|
||||
let l: &f32 = &$left;
|
||||
let r: &f32 = &$right;
|
||||
let lb = l.to_bits();
|
||||
let rb = r.to_bits();
|
||||
assert_eq!(lb, rb, "float {l} ({lb:#010x}) is not bitequal to {r} ({rb:#010x})");
|
||||
};
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_powf() {
|
||||
let nan: f32 = f32::NAN;
|
||||
let inf: f32 = f32::INFINITY;
|
||||
let neg_inf: f32 = f32::NEG_INFINITY;
|
||||
assert_eq!(1.0f32.powf(1.0), 1.0);
|
||||
assert_approx_eq!(3.4f32.powf(4.5), 246.408218, APPROX_DELTA);
|
||||
assert_approx_eq!(2.7f32.powf(-3.2), 0.041652);
|
||||
assert_approx_eq!((-3.1f32).powf(2.0), 9.61, APPROX_DELTA);
|
||||
assert_approx_eq!(5.9f32.powf(-2.0), 0.028727);
|
||||
assert_eq!(8.3f32.powf(0.0), 1.0);
|
||||
assert!(nan.powf(2.0).is_nan());
|
||||
assert_eq!(inf.powf(2.0), inf);
|
||||
assert_eq!(neg_inf.powf(3.0), neg_inf);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_exp() {
|
||||
assert_eq!(1.0, 0.0f32.exp());
|
||||
assert_approx_eq!(2.718282, 1.0f32.exp(), APPROX_DELTA);
|
||||
assert_approx_eq!(148.413162, 5.0f32.exp(), APPROX_DELTA);
|
||||
|
||||
let inf: f32 = f32::INFINITY;
|
||||
let neg_inf: f32 = f32::NEG_INFINITY;
|
||||
let nan: f32 = f32::NAN;
|
||||
assert_eq!(inf, inf.exp());
|
||||
assert_eq!(0.0, neg_inf.exp());
|
||||
assert!(nan.exp().is_nan());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_exp2() {
|
||||
assert_approx_eq!(32.0, 5.0f32.exp2(), APPROX_DELTA);
|
||||
assert_eq!(1.0, 0.0f32.exp2());
|
||||
|
||||
let inf: f32 = f32::INFINITY;
|
||||
let neg_inf: f32 = f32::NEG_INFINITY;
|
||||
let nan: f32 = f32::NAN;
|
||||
assert_eq!(inf, inf.exp2());
|
||||
assert_eq!(0.0, neg_inf.exp2());
|
||||
assert!(nan.exp2().is_nan());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ln() {
|
||||
let nan: f32 = f32::NAN;
|
||||
let inf: f32 = f32::INFINITY;
|
||||
let neg_inf: f32 = f32::NEG_INFINITY;
|
||||
assert_approx_eq!(1.0f32.exp().ln(), 1.0);
|
||||
assert!(nan.ln().is_nan());
|
||||
assert_eq!(inf.ln(), inf);
|
||||
assert!(neg_inf.ln().is_nan());
|
||||
assert!((-2.3f32).ln().is_nan());
|
||||
assert_eq!((-0.0f32).ln(), neg_inf);
|
||||
assert_eq!(0.0f32.ln(), neg_inf);
|
||||
assert_approx_eq!(4.0f32.ln(), 1.386294, APPROX_DELTA);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_log() {
|
||||
let nan: f32 = f32::NAN;
|
||||
let inf: f32 = f32::INFINITY;
|
||||
let neg_inf: f32 = f32::NEG_INFINITY;
|
||||
assert_approx_eq!(10.0f32.log(10.0), 1.0);
|
||||
assert_approx_eq!(2.3f32.log(3.5), 0.664858);
|
||||
assert_approx_eq!(1.0f32.exp().log(1.0f32.exp()), 1.0, APPROX_DELTA);
|
||||
assert!(1.0f32.log(1.0).is_nan());
|
||||
assert!(1.0f32.log(-13.9).is_nan());
|
||||
assert!(nan.log(2.3).is_nan());
|
||||
assert_eq!(inf.log(10.0), inf);
|
||||
assert!(neg_inf.log(8.8).is_nan());
|
||||
assert!((-2.3f32).log(0.1).is_nan());
|
||||
assert_eq!((-0.0f32).log(2.0), neg_inf);
|
||||
assert_eq!(0.0f32.log(7.0), neg_inf);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_log2() {
|
||||
let nan: f32 = f32::NAN;
|
||||
let inf: f32 = f32::INFINITY;
|
||||
let neg_inf: f32 = f32::NEG_INFINITY;
|
||||
assert_approx_eq!(10.0f32.log2(), 3.321928, APPROX_DELTA);
|
||||
assert_approx_eq!(2.3f32.log2(), 1.201634);
|
||||
assert_approx_eq!(1.0f32.exp().log2(), 1.442695, APPROX_DELTA);
|
||||
assert!(nan.log2().is_nan());
|
||||
assert_eq!(inf.log2(), inf);
|
||||
assert!(neg_inf.log2().is_nan());
|
||||
assert!((-2.3f32).log2().is_nan());
|
||||
assert_eq!((-0.0f32).log2(), neg_inf);
|
||||
assert_eq!(0.0f32.log2(), neg_inf);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_log10() {
|
||||
let nan: f32 = f32::NAN;
|
||||
let inf: f32 = f32::INFINITY;
|
||||
let neg_inf: f32 = f32::NEG_INFINITY;
|
||||
assert_approx_eq!(10.0f32.log10(), 1.0);
|
||||
assert_approx_eq!(2.3f32.log10(), 0.361728);
|
||||
assert_approx_eq!(1.0f32.exp().log10(), 0.434294);
|
||||
assert_eq!(1.0f32.log10(), 0.0);
|
||||
assert!(nan.log10().is_nan());
|
||||
assert_eq!(inf.log10(), inf);
|
||||
assert!(neg_inf.log10().is_nan());
|
||||
assert!((-2.3f32).log10().is_nan());
|
||||
assert_eq!((-0.0f32).log10(), neg_inf);
|
||||
assert_eq!(0.0f32.log10(), neg_inf);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_asinh() {
|
||||
assert_eq!(0.0f32.asinh(), 0.0f32);
|
||||
assert_eq!((-0.0f32).asinh(), -0.0f32);
|
||||
|
||||
let inf: f32 = f32::INFINITY;
|
||||
let neg_inf: f32 = f32::NEG_INFINITY;
|
||||
let nan: f32 = f32::NAN;
|
||||
assert_eq!(inf.asinh(), inf);
|
||||
assert_eq!(neg_inf.asinh(), neg_inf);
|
||||
assert!(nan.asinh().is_nan());
|
||||
assert!((-0.0f32).asinh().is_sign_negative()); // issue 63271
|
||||
assert_approx_eq!(2.0f32.asinh(), 1.443635475178810342493276740273105f32);
|
||||
assert_approx_eq!((-2.0f32).asinh(), -1.443635475178810342493276740273105f32);
|
||||
// regression test for the catastrophic cancellation fixed in 72486
|
||||
assert_approx_eq!((-3000.0f32).asinh(), -8.699514775987968673236893537700647f32, APPROX_DELTA);
|
||||
|
||||
// test for low accuracy from issue 104548
|
||||
assert_approx_eq!(60.0f32, 60.0f32.sinh().asinh(), APPROX_DELTA);
|
||||
// mul needed for approximate comparison to be meaningful
|
||||
assert_approx_eq!(1.0f32, 1e-15f32.sinh().asinh() * 1e15f32);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_acosh() {
|
||||
assert_eq!(1.0f32.acosh(), 0.0f32);
|
||||
assert!(0.999f32.acosh().is_nan());
|
||||
|
||||
let inf: f32 = f32::INFINITY;
|
||||
let neg_inf: f32 = f32::NEG_INFINITY;
|
||||
let nan: f32 = f32::NAN;
|
||||
assert_eq!(inf.acosh(), inf);
|
||||
assert!(neg_inf.acosh().is_nan());
|
||||
assert!(nan.acosh().is_nan());
|
||||
assert_approx_eq!(2.0f32.acosh(), 1.31695789692481670862504634730796844f32);
|
||||
assert_approx_eq!(3.0f32.acosh(), 1.76274717403908605046521864995958461f32);
|
||||
|
||||
// test for low accuracy from issue 104548
|
||||
assert_approx_eq!(60.0f32, 60.0f32.cosh().acosh(), APPROX_DELTA);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_atanh() {
|
||||
assert_eq!(0.0f32.atanh(), 0.0f32);
|
||||
assert_eq!((-0.0f32).atanh(), -0.0f32);
|
||||
|
||||
let inf32: f32 = f32::INFINITY;
|
||||
let neg_inf32: f32 = f32::NEG_INFINITY;
|
||||
assert_eq!(1.0f32.atanh(), inf32);
|
||||
assert_eq!((-1.0f32).atanh(), neg_inf32);
|
||||
|
||||
assert!(2f64.atanh().atanh().is_nan());
|
||||
assert!((-2f64).atanh().atanh().is_nan());
|
||||
|
||||
let inf64: f32 = f32::INFINITY;
|
||||
let neg_inf64: f32 = f32::NEG_INFINITY;
|
||||
let nan32: f32 = f32::NAN;
|
||||
assert!(inf64.atanh().is_nan());
|
||||
assert!(neg_inf64.atanh().is_nan());
|
||||
assert!(nan32.atanh().is_nan());
|
||||
|
||||
assert_approx_eq!(0.5f32.atanh(), 0.54930614433405484569762261846126285f32);
|
||||
assert_approx_eq!((-0.5f32).atanh(), -0.54930614433405484569762261846126285f32);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_gamma() {
|
||||
// precision can differ between platforms
|
||||
assert_approx_eq!(1.0f32.gamma(), 1.0f32, APPROX_DELTA);
|
||||
assert_approx_eq!(2.0f32.gamma(), 1.0f32, APPROX_DELTA);
|
||||
assert_approx_eq!(3.0f32.gamma(), 2.0f32, APPROX_DELTA);
|
||||
assert_approx_eq!(4.0f32.gamma(), 6.0f32, APPROX_DELTA);
|
||||
assert_approx_eq!(5.0f32.gamma(), 24.0f32, APPROX_DELTA);
|
||||
assert_approx_eq!(0.5f32.gamma(), consts::PI.sqrt(), APPROX_DELTA);
|
||||
assert_approx_eq!((-0.5f32).gamma(), -2.0 * consts::PI.sqrt(), APPROX_DELTA);
|
||||
assert_eq!(0.0f32.gamma(), f32::INFINITY);
|
||||
assert_eq!((-0.0f32).gamma(), f32::NEG_INFINITY);
|
||||
assert!((-1.0f32).gamma().is_nan());
|
||||
assert!((-2.0f32).gamma().is_nan());
|
||||
assert!(f32::NAN.gamma().is_nan());
|
||||
assert!(f32::NEG_INFINITY.gamma().is_nan());
|
||||
assert_eq!(f32::INFINITY.gamma(), f32::INFINITY);
|
||||
assert_eq!(171.71f32.gamma(), f32::INFINITY);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ln_gamma() {
|
||||
assert_approx_eq!(1.0f32.ln_gamma().0, 0.0f32);
|
||||
assert_eq!(1.0f32.ln_gamma().1, 1);
|
||||
assert_approx_eq!(2.0f32.ln_gamma().0, 0.0f32);
|
||||
assert_eq!(2.0f32.ln_gamma().1, 1);
|
||||
assert_approx_eq!(3.0f32.ln_gamma().0, 2.0f32.ln());
|
||||
assert_eq!(3.0f32.ln_gamma().1, 1);
|
||||
assert_approx_eq!((-0.5f32).ln_gamma().0, (2.0 * consts::PI.sqrt()).ln(), APPROX_DELTA);
|
||||
assert_eq!((-0.5f32).ln_gamma().1, -1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_real_consts() {
|
||||
let pi: f32 = consts::PI;
|
||||
let frac_pi_2: f32 = consts::FRAC_PI_2;
|
||||
let frac_pi_3: f32 = consts::FRAC_PI_3;
|
||||
let frac_pi_4: f32 = consts::FRAC_PI_4;
|
||||
let frac_pi_6: f32 = consts::FRAC_PI_6;
|
||||
let frac_pi_8: f32 = consts::FRAC_PI_8;
|
||||
let frac_1_pi: f32 = consts::FRAC_1_PI;
|
||||
let frac_2_pi: f32 = consts::FRAC_2_PI;
|
||||
let frac_2_sqrtpi: f32 = consts::FRAC_2_SQRT_PI;
|
||||
let sqrt2: f32 = consts::SQRT_2;
|
||||
let frac_1_sqrt2: f32 = consts::FRAC_1_SQRT_2;
|
||||
let e: f32 = consts::E;
|
||||
let log2_e: f32 = consts::LOG2_E;
|
||||
let log10_e: f32 = consts::LOG10_E;
|
||||
let ln_2: f32 = consts::LN_2;
|
||||
let ln_10: f32 = consts::LN_10;
|
||||
|
||||
assert_approx_eq!(frac_pi_2, pi / 2f32);
|
||||
assert_approx_eq!(frac_pi_3, pi / 3f32, APPROX_DELTA);
|
||||
assert_approx_eq!(frac_pi_4, pi / 4f32);
|
||||
assert_approx_eq!(frac_pi_6, pi / 6f32);
|
||||
assert_approx_eq!(frac_pi_8, pi / 8f32);
|
||||
assert_approx_eq!(frac_1_pi, 1f32 / pi);
|
||||
assert_approx_eq!(frac_2_pi, 2f32 / pi);
|
||||
assert_approx_eq!(frac_2_sqrtpi, 2f32 / pi.sqrt());
|
||||
assert_approx_eq!(sqrt2, 2f32.sqrt());
|
||||
assert_approx_eq!(frac_1_sqrt2, 1f32 / 2f32.sqrt());
|
||||
assert_approx_eq!(log2_e, e.log2());
|
||||
assert_approx_eq!(log10_e, e.log10());
|
||||
assert_approx_eq!(ln_2, 2f32.ln());
|
||||
assert_approx_eq!(ln_10, 10f32.ln(), APPROX_DELTA);
|
||||
}
|
||||
|
|
@ -1,249 +0,0 @@
|
|||
use std::f64::consts;
|
||||
|
||||
#[allow(unused_macros)]
|
||||
macro_rules! assert_f64_biteq {
|
||||
($left : expr, $right : expr) => {
|
||||
let l: &f64 = &$left;
|
||||
let r: &f64 = &$right;
|
||||
let lb = l.to_bits();
|
||||
let rb = r.to_bits();
|
||||
assert_eq!(lb, rb, "float {l} ({lb:#018x}) is not bitequal to {r} ({rb:#018x})");
|
||||
};
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_powf() {
|
||||
let nan: f64 = f64::NAN;
|
||||
let inf: f64 = f64::INFINITY;
|
||||
let neg_inf: f64 = f64::NEG_INFINITY;
|
||||
assert_eq!(1.0f64.powf(1.0), 1.0);
|
||||
assert_approx_eq!(3.4f64.powf(4.5), 246.408183);
|
||||
assert_approx_eq!(2.7f64.powf(-3.2), 0.041652);
|
||||
assert_approx_eq!((-3.1f64).powf(2.0), 9.61);
|
||||
assert_approx_eq!(5.9f64.powf(-2.0), 0.028727);
|
||||
assert_eq!(8.3f64.powf(0.0), 1.0);
|
||||
assert!(nan.powf(2.0).is_nan());
|
||||
assert_eq!(inf.powf(2.0), inf);
|
||||
assert_eq!(neg_inf.powf(3.0), neg_inf);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_exp() {
|
||||
assert_eq!(1.0, 0.0f64.exp());
|
||||
assert_approx_eq!(2.718282, 1.0f64.exp());
|
||||
assert_approx_eq!(148.413159, 5.0f64.exp());
|
||||
|
||||
let inf: f64 = f64::INFINITY;
|
||||
let neg_inf: f64 = f64::NEG_INFINITY;
|
||||
let nan: f64 = f64::NAN;
|
||||
assert_eq!(inf, inf.exp());
|
||||
assert_eq!(0.0, neg_inf.exp());
|
||||
assert!(nan.exp().is_nan());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_exp2() {
|
||||
assert_approx_eq!(32.0, 5.0f64.exp2());
|
||||
assert_eq!(1.0, 0.0f64.exp2());
|
||||
|
||||
let inf: f64 = f64::INFINITY;
|
||||
let neg_inf: f64 = f64::NEG_INFINITY;
|
||||
let nan: f64 = f64::NAN;
|
||||
assert_eq!(inf, inf.exp2());
|
||||
assert_eq!(0.0, neg_inf.exp2());
|
||||
assert!(nan.exp2().is_nan());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ln() {
|
||||
let nan: f64 = f64::NAN;
|
||||
let inf: f64 = f64::INFINITY;
|
||||
let neg_inf: f64 = f64::NEG_INFINITY;
|
||||
assert_approx_eq!(1.0f64.exp().ln(), 1.0);
|
||||
assert!(nan.ln().is_nan());
|
||||
assert_eq!(inf.ln(), inf);
|
||||
assert!(neg_inf.ln().is_nan());
|
||||
assert!((-2.3f64).ln().is_nan());
|
||||
assert_eq!((-0.0f64).ln(), neg_inf);
|
||||
assert_eq!(0.0f64.ln(), neg_inf);
|
||||
assert_approx_eq!(4.0f64.ln(), 1.386294);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_log() {
|
||||
let nan: f64 = f64::NAN;
|
||||
let inf: f64 = f64::INFINITY;
|
||||
let neg_inf: f64 = f64::NEG_INFINITY;
|
||||
assert_approx_eq!(10.0f64.log(10.0), 1.0);
|
||||
assert_approx_eq!(2.3f64.log(3.5), 0.664858);
|
||||
assert_approx_eq!(1.0f64.exp().log(1.0f64.exp()), 1.0);
|
||||
assert!(1.0f64.log(1.0).is_nan());
|
||||
assert!(1.0f64.log(-13.9).is_nan());
|
||||
assert!(nan.log(2.3).is_nan());
|
||||
assert_eq!(inf.log(10.0), inf);
|
||||
assert!(neg_inf.log(8.8).is_nan());
|
||||
assert!((-2.3f64).log(0.1).is_nan());
|
||||
assert_eq!((-0.0f64).log(2.0), neg_inf);
|
||||
assert_eq!(0.0f64.log(7.0), neg_inf);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_log2() {
|
||||
let nan: f64 = f64::NAN;
|
||||
let inf: f64 = f64::INFINITY;
|
||||
let neg_inf: f64 = f64::NEG_INFINITY;
|
||||
assert_approx_eq!(10.0f64.log2(), 3.321928);
|
||||
assert_approx_eq!(2.3f64.log2(), 1.201634);
|
||||
assert_approx_eq!(1.0f64.exp().log2(), 1.442695);
|
||||
assert!(nan.log2().is_nan());
|
||||
assert_eq!(inf.log2(), inf);
|
||||
assert!(neg_inf.log2().is_nan());
|
||||
assert!((-2.3f64).log2().is_nan());
|
||||
assert_eq!((-0.0f64).log2(), neg_inf);
|
||||
assert_eq!(0.0f64.log2(), neg_inf);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_log10() {
|
||||
let nan: f64 = f64::NAN;
|
||||
let inf: f64 = f64::INFINITY;
|
||||
let neg_inf: f64 = f64::NEG_INFINITY;
|
||||
assert_approx_eq!(10.0f64.log10(), 1.0);
|
||||
assert_approx_eq!(2.3f64.log10(), 0.361728);
|
||||
assert_approx_eq!(1.0f64.exp().log10(), 0.434294);
|
||||
assert_eq!(1.0f64.log10(), 0.0);
|
||||
assert!(nan.log10().is_nan());
|
||||
assert_eq!(inf.log10(), inf);
|
||||
assert!(neg_inf.log10().is_nan());
|
||||
assert!((-2.3f64).log10().is_nan());
|
||||
assert_eq!((-0.0f64).log10(), neg_inf);
|
||||
assert_eq!(0.0f64.log10(), neg_inf);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_asinh() {
|
||||
assert_eq!(0.0f64.asinh(), 0.0f64);
|
||||
assert_eq!((-0.0f64).asinh(), -0.0f64);
|
||||
|
||||
let inf: f64 = f64::INFINITY;
|
||||
let neg_inf: f64 = f64::NEG_INFINITY;
|
||||
let nan: f64 = f64::NAN;
|
||||
assert_eq!(inf.asinh(), inf);
|
||||
assert_eq!(neg_inf.asinh(), neg_inf);
|
||||
assert!(nan.asinh().is_nan());
|
||||
assert!((-0.0f64).asinh().is_sign_negative());
|
||||
// issue 63271
|
||||
assert_approx_eq!(2.0f64.asinh(), 1.443635475178810342493276740273105f64);
|
||||
assert_approx_eq!((-2.0f64).asinh(), -1.443635475178810342493276740273105f64);
|
||||
// regression test for the catastrophic cancellation fixed in 72486
|
||||
assert_approx_eq!((-67452098.07139316f64).asinh(), -18.72007542627454439398548429400083);
|
||||
|
||||
// test for low accuracy from issue 104548
|
||||
assert_approx_eq!(60.0f64, 60.0f64.sinh().asinh());
|
||||
// mul needed for approximate comparison to be meaningful
|
||||
assert_approx_eq!(1.0f64, 1e-15f64.sinh().asinh() * 1e15f64);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_acosh() {
|
||||
assert_eq!(1.0f64.acosh(), 0.0f64);
|
||||
assert!(0.999f64.acosh().is_nan());
|
||||
|
||||
let inf: f64 = f64::INFINITY;
|
||||
let neg_inf: f64 = f64::NEG_INFINITY;
|
||||
let nan: f64 = f64::NAN;
|
||||
assert_eq!(inf.acosh(), inf);
|
||||
assert!(neg_inf.acosh().is_nan());
|
||||
assert!(nan.acosh().is_nan());
|
||||
assert_approx_eq!(2.0f64.acosh(), 1.31695789692481670862504634730796844f64);
|
||||
assert_approx_eq!(3.0f64.acosh(), 1.76274717403908605046521864995958461f64);
|
||||
|
||||
// test for low accuracy from issue 104548
|
||||
assert_approx_eq!(60.0f64, 60.0f64.cosh().acosh());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_atanh() {
|
||||
assert_eq!(0.0f64.atanh(), 0.0f64);
|
||||
assert_eq!((-0.0f64).atanh(), -0.0f64);
|
||||
|
||||
let inf: f64 = f64::INFINITY;
|
||||
let neg_inf: f64 = f64::NEG_INFINITY;
|
||||
let nan: f64 = f64::NAN;
|
||||
assert_eq!(1.0f64.atanh(), inf);
|
||||
assert_eq!((-1.0f64).atanh(), neg_inf);
|
||||
assert!(2f64.atanh().atanh().is_nan());
|
||||
assert!((-2f64).atanh().atanh().is_nan());
|
||||
assert!(inf.atanh().is_nan());
|
||||
assert!(neg_inf.atanh().is_nan());
|
||||
assert!(nan.atanh().is_nan());
|
||||
assert_approx_eq!(0.5f64.atanh(), 0.54930614433405484569762261846126285f64);
|
||||
assert_approx_eq!((-0.5f64).atanh(), -0.54930614433405484569762261846126285f64);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_gamma() {
|
||||
// precision can differ between platforms
|
||||
assert_approx_eq!(1.0f64.gamma(), 1.0f64);
|
||||
assert_approx_eq!(2.0f64.gamma(), 1.0f64);
|
||||
assert_approx_eq!(3.0f64.gamma(), 2.0f64);
|
||||
assert_approx_eq!(4.0f64.gamma(), 6.0f64);
|
||||
assert_approx_eq!(5.0f64.gamma(), 24.0f64);
|
||||
assert_approx_eq!(0.5f64.gamma(), consts::PI.sqrt());
|
||||
assert_approx_eq!((-0.5f64).gamma(), -2.0 * consts::PI.sqrt());
|
||||
assert_eq!(0.0f64.gamma(), f64::INFINITY);
|
||||
assert_eq!((-0.0f64).gamma(), f64::NEG_INFINITY);
|
||||
assert!((-1.0f64).gamma().is_nan());
|
||||
assert!((-2.0f64).gamma().is_nan());
|
||||
assert!(f64::NAN.gamma().is_nan());
|
||||
assert!(f64::NEG_INFINITY.gamma().is_nan());
|
||||
assert_eq!(f64::INFINITY.gamma(), f64::INFINITY);
|
||||
assert_eq!(171.71f64.gamma(), f64::INFINITY);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ln_gamma() {
|
||||
assert_approx_eq!(1.0f64.ln_gamma().0, 0.0f64);
|
||||
assert_eq!(1.0f64.ln_gamma().1, 1);
|
||||
assert_approx_eq!(2.0f64.ln_gamma().0, 0.0f64);
|
||||
assert_eq!(2.0f64.ln_gamma().1, 1);
|
||||
assert_approx_eq!(3.0f64.ln_gamma().0, 2.0f64.ln());
|
||||
assert_eq!(3.0f64.ln_gamma().1, 1);
|
||||
assert_approx_eq!((-0.5f64).ln_gamma().0, (2.0 * consts::PI.sqrt()).ln());
|
||||
assert_eq!((-0.5f64).ln_gamma().1, -1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_real_consts() {
|
||||
let pi: f64 = consts::PI;
|
||||
let frac_pi_2: f64 = consts::FRAC_PI_2;
|
||||
let frac_pi_3: f64 = consts::FRAC_PI_3;
|
||||
let frac_pi_4: f64 = consts::FRAC_PI_4;
|
||||
let frac_pi_6: f64 = consts::FRAC_PI_6;
|
||||
let frac_pi_8: f64 = consts::FRAC_PI_8;
|
||||
let frac_1_pi: f64 = consts::FRAC_1_PI;
|
||||
let frac_2_pi: f64 = consts::FRAC_2_PI;
|
||||
let frac_2_sqrtpi: f64 = consts::FRAC_2_SQRT_PI;
|
||||
let sqrt2: f64 = consts::SQRT_2;
|
||||
let frac_1_sqrt2: f64 = consts::FRAC_1_SQRT_2;
|
||||
let e: f64 = consts::E;
|
||||
let log2_e: f64 = consts::LOG2_E;
|
||||
let log10_e: f64 = consts::LOG10_E;
|
||||
let ln_2: f64 = consts::LN_2;
|
||||
let ln_10: f64 = consts::LN_10;
|
||||
|
||||
assert_approx_eq!(frac_pi_2, pi / 2f64);
|
||||
assert_approx_eq!(frac_pi_3, pi / 3f64);
|
||||
assert_approx_eq!(frac_pi_4, pi / 4f64);
|
||||
assert_approx_eq!(frac_pi_6, pi / 6f64);
|
||||
assert_approx_eq!(frac_pi_8, pi / 8f64);
|
||||
assert_approx_eq!(frac_1_pi, 1f64 / pi);
|
||||
assert_approx_eq!(frac_2_pi, 2f64 / pi);
|
||||
assert_approx_eq!(frac_2_sqrtpi, 2f64 / pi.sqrt());
|
||||
assert_approx_eq!(sqrt2, 2f64.sqrt());
|
||||
assert_approx_eq!(frac_1_sqrt2, 1f64 / 2f64.sqrt());
|
||||
assert_approx_eq!(log2_e, e.log2());
|
||||
assert_approx_eq!(log10_e, e.log10());
|
||||
assert_approx_eq!(ln_2, 2f64.ln());
|
||||
assert_approx_eq!(ln_10, 10f64.ln());
|
||||
}
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
#![feature(f16, f128, float_gamma, cfg_target_has_reliable_f16_f128)]
|
||||
#![expect(internal_features)] // for reliable_f16_f128
|
||||
|
||||
use std::fmt;
|
||||
use std::ops::{Add, Div, Mul, Rem, Sub};
|
||||
|
||||
/// Verify that floats are within a tolerance of each other, 1.0e-6 by default.
|
||||
macro_rules! assert_approx_eq {
|
||||
($a:expr, $b:expr) => {{ assert_approx_eq!($a, $b, 1.0e-6) }};
|
||||
($a:expr, $b:expr, $lim:expr) => {{
|
||||
let (a, b) = (&$a, &$b);
|
||||
let diff = (*a - *b).abs();
|
||||
assert!(
|
||||
diff <= $lim,
|
||||
"{a:?} is not approximately equal to {b:?} (threshold {lim:?}, difference {diff:?})",
|
||||
lim = $lim
|
||||
);
|
||||
}};
|
||||
}
|
||||
|
||||
/// 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;
|
||||
Loading…
Add table
Add a link
Reference in a new issue