From 03da364a0b4473f51cce6377fc4299524a41852f Mon Sep 17 00:00:00 2001 From: Jacob Lifshay Date: Sun, 9 May 2021 18:08:37 -0700 Subject: [PATCH] make ulp testing code more generic --- src/algorithms/trig_pi.rs | 28 +++++++++++++++------------- src/prim.rs | 12 ++++++++++++ 2 files changed, 27 insertions(+), 13 deletions(-) diff --git a/src/algorithms/trig_pi.rs b/src/algorithms/trig_pi.rs index 5e6659c..a9b275c 100644 --- a/src/algorithms/trig_pi.rs +++ b/src/algorithms/trig_pi.rs @@ -170,15 +170,15 @@ mod tests { } #[track_caller] - fn check_ulp_f16( - x: F16, - is_ok: impl Fn(CheckUlpCallbackArg) -> bool, - fn_f16: impl Fn(F16) -> F16, - fn_f64: impl Fn(f64) -> f64, + fn check_ulp( + x: T, + is_ok: impl Fn(CheckUlpCallbackArg) -> 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; @@ -186,7 +186,9 @@ mod tests { 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 { @@ -221,7 +223,7 @@ mod tests { )] 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, @@ -242,7 +244,7 @@ mod tests { )] 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, @@ -256,7 +258,7 @@ mod tests { } } - fn sin_cos_pi_check_ulp_callback_f16(arg: CheckUlpCallbackArg) -> bool { + fn sin_cos_pi_check_ulp_callback_f16(arg: CheckUlpCallbackArg) -> bool { if f32::cvt_from(arg.x) % 0.5 == 0.0 { arg.distance_in_ulp == 0 } else { @@ -271,7 +273,7 @@ mod tests { )] 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, @@ -287,7 +289,7 @@ mod tests { )] 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, diff --git a/src/prim.rs b/src/prim.rs index b2d2ebb..08ede9e 100644 --- a/src/prim.rs +++ b/src/prim.rs @@ -136,6 +136,9 @@ pub trait PrimFloat: 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 { @@ -173,6 +176,15 @@ 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() + } } }; } -- 2.30.2