}
#[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,