#![cfg(all(not(feature = "std"), feature = "compact"))]
use core::f64;
use lexical_parse_float::libm;
#[test]
fn fabsf_sanity_test() {
assert_eq!(libm::fabsf(-1.0), 1.0);
assert_eq!(libm::fabsf(2.8), 2.8);
}
#[test]
fn fabsf_spec_test() {
assert!(libm::fabsf(f32::NAN).is_nan());
for f in [0.0, -0.0].iter().copied() {
assert_eq!(libm::fabsf(f), 0.0);
}
for f in [f32::INFINITY, f32::NEG_INFINITY].iter().copied() {
assert_eq!(libm::fabsf(f), f32::INFINITY);
}
}
#[test]
fn sqrtf_sanity_test() {
assert_eq!(libm::sqrtf(100.0), 10.0);
assert_eq!(libm::sqrtf(4.0), 2.0);
}
#[test]
fn sqrtf_spec_test() {
assert!(libm::sqrtf(-1.0).is_nan());
assert!(libm::sqrtf(f32::NAN).is_nan());
for f in [0.0, -0.0, f32::INFINITY].iter().copied() {
assert_eq!(libm::sqrtf(f), f);
}
}
const POS_ZERO: &[f64] = &[0.0];
const NEG_ZERO: &[f64] = &[-0.0];
const POS_ONE: &[f64] = &[1.0];
const NEG_ONE: &[f64] = &[-1.0];
const POS_FLOATS: &[f64] = &[99.0 / 70.0, f64::consts::E, f64::consts::PI];
const NEG_FLOATS: &[f64] = &[-99.0 / 70.0, -f64::consts::E, -f64::consts::PI];
const POS_SMALL_FLOATS: &[f64] = &[(1.0 / 2.0), f64::MIN_POSITIVE, f64::EPSILON];
const NEG_SMALL_FLOATS: &[f64] = &[-(1.0 / 2.0), -f64::MIN_POSITIVE, -f64::EPSILON];
const POS_EVENS: &[f64] = &[2.0, 6.0, 8.0, 10.0, 22.0, 100.0, f64::MAX];
const NEG_EVENS: &[f64] = &[f64::MIN, -100.0, -22.0, -10.0, -8.0, -6.0, -2.0];
const POS_ODDS: &[f64] = &[3.0, 7.0];
const NEG_ODDS: &[f64] = &[-7.0, -3.0];
const NANS: &[f64] = &[f64::NAN];
const POS_INF: &[f64] = &[f64::INFINITY];
const NEG_INF: &[f64] = &[f64::NEG_INFINITY];
const ALL: &[&[f64]] = &[
POS_ZERO,
NEG_ZERO,
NANS,
NEG_SMALL_FLOATS,
POS_SMALL_FLOATS,
NEG_FLOATS,
POS_FLOATS,
NEG_EVENS,
POS_EVENS,
NEG_ODDS,
POS_ODDS,
NEG_INF,
POS_INF,
NEG_ONE,
POS_ONE,
];
const POS: &[&[f64]] = &[POS_ZERO, POS_ODDS, POS_ONE, POS_FLOATS, POS_EVENS, POS_INF];
const NEG: &[&[f64]] = &[NEG_ZERO, NEG_ODDS, NEG_ONE, NEG_FLOATS, NEG_EVENS, NEG_INF];
fn powd(base: f64, exponent: f64, expected: f64) {
let res = libm::powd(base, exponent);
assert!(
if expected.is_nan() {
res.is_nan()
} else {
libm::powd(base, exponent) == expected
},
"{} ** {} was {} instead of {}",
base,
exponent,
res,
expected
);
}
fn powd_test_sets_as_base(sets: &[&[f64]], exponent: f64, expected: f64) {
sets.iter().for_each(|s| s.iter().for_each(|val| powd(*val, exponent, expected)));
}
fn powd_test_sets_as_exponent(base: f64, sets: &[&[f64]], expected: f64) {
sets.iter().for_each(|s| s.iter().for_each(|val| powd(base, *val, expected)));
}
fn powd_test_sets(sets: &[&[f64]], computed: &dyn Fn(f64) -> f64, expected: &dyn Fn(f64) -> f64) {
sets.iter().for_each(|s| {
s.iter().for_each(|val| {
let exp = expected(*val);
let res = computed(*val);
assert!(
if exp.is_nan() {
res.is_nan()
} else {
exp == res
},
"test for {} was {} instead of {}",
val,
res,
exp
);
})
});
}
#[test]
fn powd_zero_as_exponent() {
powd_test_sets_as_base(ALL, 0.0, 1.0);
powd_test_sets_as_base(ALL, -0.0, 1.0);
}
#[test]
fn powd_one_as_base() {
powd_test_sets_as_exponent(1.0, ALL, 1.0);
}
#[test]
fn powd_nan_inputs() {
powd_test_sets_as_exponent(f64::NAN, &ALL[2..], f64::NAN);
powd_test_sets_as_base(&ALL[..(ALL.len() - 2)], f64::NAN, f64::NAN);
}
#[test]
fn powd_infinity_as_base() {
powd_test_sets_as_exponent(f64::INFINITY, &POS[1..], f64::INFINITY);
powd_test_sets_as_exponent(f64::INFINITY, &NEG[1..], 0.0);
powd_test_sets_as_exponent(f64::NEG_INFINITY, &[POS_ODDS], f64::NEG_INFINITY);
powd_test_sets(ALL, &|v: f64| libm::powd(f64::NEG_INFINITY, v), &|v: f64| libm::powd(-0.0, -v));
}
#[test]
fn infinity_as_exponent() {
powd_test_sets_as_base(&ALL[5..(ALL.len() - 2)], f64::INFINITY, f64::INFINITY);
powd_test_sets_as_base(&ALL[5..ALL.len() - 2], f64::NEG_INFINITY, 0.0);
let base_below_one = &[POS_ZERO, NEG_ZERO, NEG_SMALL_FLOATS, POS_SMALL_FLOATS];
powd_test_sets_as_base(base_below_one, f64::INFINITY, 0.0);
powd_test_sets_as_base(base_below_one, f64::NEG_INFINITY, f64::INFINITY);
powd_test_sets_as_base(&[NEG_ONE, POS_ONE], f64::INFINITY, 1.0);
powd_test_sets_as_base(&[NEG_ONE, POS_ONE], f64::NEG_INFINITY, 1.0);
}
#[test]
fn powd_zero_as_base() {
powd_test_sets_as_exponent(0.0, &POS[1..], 0.0);
powd_test_sets_as_exponent(0.0, &NEG[1..], f64::INFINITY);
powd_test_sets_as_exponent(-0.0, &POS[3..], 0.0);
powd_test_sets_as_exponent(-0.0, &NEG[3..], f64::INFINITY);
powd_test_sets_as_exponent(-0.0, &[POS_ODDS], -0.0);
powd_test_sets_as_exponent(-0.0, &[NEG_ODDS], f64::NEG_INFINITY);
}
#[test]
fn special_cases() {
powd_test_sets(ALL, &|v: f64| libm::powd(v, 1.0), &|v: f64| v);
powd_test_sets(ALL, &|v: f64| libm::powd(v, -1.0), &|v: f64| 1.0 / v);
[POS_ZERO, NEG_ZERO, POS_ONE, NEG_ONE, POS_EVENS, NEG_EVENS].iter().for_each(|int_set| {
int_set.iter().for_each(|int| {
powd_test_sets(ALL, &|v: f64| libm::powd(-v, *int), &|v: f64| {
libm::powd(-1.0, *int) * libm::powd(v, *int)
});
})
});
NEG[1..(NEG.len() - 1)].iter().for_each(|set| {
set.iter().for_each(|val| {
powd_test_sets(&ALL[3..7], &|v: f64| libm::powd(*val, v), &|_| f64::NAN);
})
});
}
#[test]
fn normal_cases() {
assert_eq!(libm::powd(2.0, 20.0), (1 << 20) as f64);
assert_eq!(libm::powd(-1.0, 9.0), -1.0);
assert!(libm::powd(-1.0, 2.2).is_nan());
assert!(libm::powd(-1.0, -1.14).is_nan());
}
#[test]
fn fabsd_sanity_test() {
assert_eq!(libm::fabsd(-1.0), 1.0);
assert_eq!(libm::fabsd(2.8), 2.8);
}
#[test]
fn fabsd_spec_test() {
assert!(libm::fabsd(f64::NAN).is_nan());
for f in [0.0, -0.0].iter().copied() {
assert_eq!(libm::fabsd(f), 0.0);
}
for f in [f64::INFINITY, f64::NEG_INFINITY].iter().copied() {
assert_eq!(libm::fabsd(f), f64::INFINITY);
}
}
#[test]
fn sqrtd_sanity_test() {
assert_eq!(libm::sqrtd(100.0), 10.0);
assert_eq!(libm::sqrtd(4.0), 2.0);
}
#[test]
fn sqrtd_spec_test() {
assert!(libm::sqrtd(-1.0).is_nan());
assert!(libm::sqrtd(f64::NAN).is_nan());
for f in [0.0, -0.0, f64::INFINITY].iter().copied() {
assert_eq!(libm::sqrtd(f), f);
}
}