Skip to content
This repository was archived by the owner on Apr 28, 2025. It is now read-only.

Commit 1d77d0a

Browse files
committed
Refactor the Call trait into the test lib
1 parent 8abd2f9 commit 1d77d0a

File tree

2 files changed

+38
-38
lines changed

2 files changed

+38
-38
lines changed

crates/libm-test/src/lib.rs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,3 +51,40 @@ impl WithinUlps for i32 {
5151
ulps <= ulp_tol as _
5252
}
5353
}
54+
55+
/// This implements function dispatch for tuples of arguments used in the tests
56+
/// above, so that we can: (f32, 32).call(fn(f32, f32) -> f32) generically.
57+
///
58+
/// We need the input parameter F to support dispatching, e.g., (f32,f32) with
59+
/// functions that return both f32 or i32. Those are two different types, so we
60+
/// need to be parametric over them.
61+
pub trait Call<F> {
62+
type Ret;
63+
fn call(self, f: F) -> Self::Ret;
64+
}
65+
66+
macro_rules! impl_call {
67+
(($($arg_tys:ty),*) -> $ret_ty:ty: $self_:ident: $($xs:expr),*) => {
68+
// We only care about unsafe extern "C" functions here, safe functions coerce to them:
69+
impl Call<unsafe extern"C" fn($($arg_tys),*) -> $ret_ty> for ($($arg_tys,)+) {
70+
type Ret = $ret_ty;
71+
fn call(self, f: unsafe extern "C" fn($($arg_tys),*) -> $ret_ty) -> Self::Ret {
72+
let $self_ = self;
73+
unsafe { f($($xs),*) }
74+
}
75+
}
76+
};
77+
}
78+
79+
impl_call!((f32) -> f32: x: x.0);
80+
impl_call!((f64) -> f64: x: x.0);
81+
impl_call!((f64) -> i32: x: x.0);
82+
impl_call!((f32) -> i32: x: x.0);
83+
impl_call!((f32, f32) -> f32: x: x.0, x.1);
84+
impl_call!((f64, f64) -> f64: x: x.0, x.1);
85+
impl_call!((f64, i32) -> f64: x: x.0, x.1);
86+
impl_call!((f32, i32) -> f32: x: x.0, x.1);
87+
impl_call!((i32, f64) -> f64: x: x.0, x.1);
88+
impl_call!((i32, f32) -> f32: x: x.0, x.1);
89+
impl_call!((f32, f32, f32) -> f32: x: x.0, x.1, x.2);
90+
impl_call!((f64, f64, f64) -> f64: x: x.0, x.1, x.2);

crates/libm-test/tests/system_libm.rs

Lines changed: 1 addition & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
#![cfg(test)]
33
#![cfg(feature = "system_libm")]
44

5-
use libm_test::WithinUlps;
5+
use libm_test::{Call, WithinUlps};
66

77
// Number of tests to generate for each function
88
const NTESTS: usize = 500;
@@ -114,43 +114,6 @@ macro_rules! system_libm {
114114

115115
libm_analyze::for_each_api!(system_libm);
116116

117-
// This implements function dispatch for tuples of arguments used in the tests
118-
// above, so that we can: (f32, 32).call(fn(f32, f32) -> f32) generically.
119-
//
120-
// We need the input parameter F to support dispatching, e.g., (f32,f32) with
121-
// functions that return both f32 or i32. Those are two different types, so we
122-
// need to be parametric over them.
123-
trait Call<F> {
124-
type Ret;
125-
fn call(self, f: F) -> Self::Ret;
126-
}
127-
128-
macro_rules! impl_call {
129-
(($($arg_tys:ty),*) -> $ret_ty:ty: $self_:ident: $($xs:expr),*) => {
130-
// We only care about unsafe extern "C" functions here, safe functions coerce to them:
131-
impl Call<unsafe extern"C" fn($($arg_tys),*) -> $ret_ty> for ($($arg_tys,)+) {
132-
type Ret = $ret_ty;
133-
fn call(self, f: unsafe extern "C" fn($($arg_tys),*) -> $ret_ty) -> Self::Ret {
134-
let $self_ = self;
135-
unsafe { f($($xs),*) }
136-
}
137-
}
138-
};
139-
}
140-
141-
impl_call!((f32) -> f32: x: x.0);
142-
impl_call!((f64) -> f64: x: x.0);
143-
impl_call!((f64) -> i32: x: x.0);
144-
impl_call!((f32) -> i32: x: x.0);
145-
impl_call!((f32, f32) -> f32: x: x.0, x.1);
146-
impl_call!((f64, f64) -> f64: x: x.0, x.1);
147-
impl_call!((f64, i32) -> f64: x: x.0, x.1);
148-
impl_call!((f32, i32) -> f32: x: x.0, x.1);
149-
impl_call!((i32, f64) -> f64: x: x.0, x.1);
150-
impl_call!((i32, f32) -> f32: x: x.0, x.1);
151-
impl_call!((f32, f32, f32) -> f32: x: x.0, x.1, x.2);
152-
impl_call!((f64, f64, f64) -> f64: x: x.0, x.1, x.2);
153-
154117
// We need to be able to generate random numbers for the types involved.
155118
//
156119
// Rand does this well, but we want to also test some other specific values.

0 commit comments

Comments
 (0)