}
#[track_caller]
- fn check_ulp_f16(
- x: F16,
- is_ok: impl Fn(CheckUlpCallbackArg<F16, u32>) -> bool,
- fn_f16: impl Fn(F16) -> F16,
- fn_f64: impl Fn(f64) -> f64,
+ fn check_ulp<T: PrimFloat>(
+ x: T,
+ is_ok: impl Fn(CheckUlpCallbackArg<T, u64>) -> bool,
+ fn_f16: impl Fn(T) -> T,
+ fn_reference: impl Fn(f64) -> f64,
) {
let x_f64: f64 = x.to();
- let expected_f64 = fn_f64(x_f64);
- let expected: F16 = expected_f64.to();
+ let expected_f64 = fn_reference(x_f64);
+ let expected: T = expected_f64.to();
let result = fn_f16(x);
if result == expected {
return;
if result.is_nan() && expected.is_nan() {
return;
}
- let distance_in_ulp = (expected.to_bits() as i32 - result.to_bits() as i32).unsigned_abs();
+ let expected_bits: i64 = expected.to_bits().to();
+ let result_bits: i64 = result.to_bits().to();
+ let distance_in_ulp = (expected_bits - result_bits).unsigned_abs();
if !result.is_nan()
&& !expected.is_nan()
&& is_ok(CheckUlpCallbackArg {
)]
fn test_sin_pi_kernel_f16() {
let check = |x| {
- check_ulp_f16(
+ check_ulp(
x,
|arg| arg.distance_in_ulp <= if arg.expected == 0.to() { 0 } else { 2 },
|x| sin_pi_kernel_f16(Scalar, Value(x)).0,
)]
fn test_cos_pi_kernel_f16() {
let check = |x| {
- check_ulp_f16(
+ check_ulp(
x,
|arg| arg.distance_in_ulp <= 2 && arg.result <= 1.to(),
|x| cos_pi_kernel_f16(Scalar, Value(x)).0,
}
}
- fn sin_cos_pi_check_ulp_callback_f16(arg: CheckUlpCallbackArg<F16, u32>) -> bool {
+ fn sin_cos_pi_check_ulp_callback_f16(arg: CheckUlpCallbackArg<F16, u64>) -> bool {
if f32::cvt_from(arg.x) % 0.5 == 0.0 {
arg.distance_in_ulp == 0
} else {
)]
fn test_sin_pi_f16() {
for bits in 0..=u16::MAX {
- check_ulp_f16(
+ check_ulp(
F16::from_bits(bits),
sin_cos_pi_check_ulp_callback_f16,
|x| sin_pi_f16(Scalar, Value(x)).0,
)]
fn test_cos_pi_f16() {
for bits in 0..=u16::MAX {
- check_ulp_f16(
+ check_ulp(
F16::from_bits(bits),
sin_cos_pi_check_ulp_callback_f16,
|x| cos_pi_f16(Scalar, Value(x)).0,
const NAN_INFINITY_EXPONENT: Self::BitsType;
const INFINITY_BITS: Self::BitsType;
const NAN_BITS: Self::BitsType;
+ fn is_nan(self) -> bool;
+ fn from_bits(bits: Self::BitsType) -> Self;
+ fn to_bits(self) -> Self::BitsType;
}
macro_rules! impl_float {
Self::NAN_INFINITY_EXPONENT << Self::EXPONENT_FIELD_SHIFT;
const NAN_BITS: Self::BitsType =
Self::INFINITY_BITS | (1 << (Self::MANTISSA_FIELD_WIDTH - 1));
+ fn is_nan(self) -> bool {
+ $float::is_nan(self)
+ }
+ fn from_bits(bits: Self::BitsType) -> Self {
+ $float::from_bits(bits)
+ }
+ fn to_bits(self) -> Self::BitsType {
+ self.to_bits()
+ }
}
};
}