make ulp testing code more generic
authorJacob Lifshay <programmerjake@gmail.com>
Mon, 10 May 2021 01:08:37 +0000 (18:08 -0700)
committerJacob Lifshay <programmerjake@gmail.com>
Mon, 10 May 2021 01:08:37 +0000 (18:08 -0700)
src/algorithms/trig_pi.rs
src/prim.rs

index 5e6659cbecc730b4b5e5c655ff7dab1e7d0f0d6d..a9b275c5b6c94f6ee8e961a7b6e510c730409108 100644 (file)
@@ -170,15 +170,15 @@ mod tests {
     }
 
     #[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;
@@ -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<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 {
@@ -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,
index b2d2ebb5c5dbadc29f31f2b34af57c96bb37c943..08ede9e643616a73a8fe15fb189cfdf4a32e741b 100644 (file)
@@ -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()
+            }
         }
     };
 }