Skip to content

Commit 654569a

Browse files
committed
Add more extensive tests
1 parent 9feb949 commit 654569a

File tree

8 files changed

+124
-71
lines changed

8 files changed

+124
-71
lines changed

crates/libm-test/benches/random.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ where
5454

5555
let ctx = CheckCtx::new(Op::IDENTIFIER, CheckBasis::Musl, GeneratorKind::Random);
5656
let benchvec: Vec<_> =
57-
random::get_test_cases::<Op::RustArgs>(&ctx).0.take(BENCH_ITER_ITEMS).collect();
57+
random::get_test_cases::<Op>(ctx.clone()).0.take(BENCH_ITER_ITEMS).collect();
5858

5959
// Perform a sanity check that we are benchmarking the same thing
6060
// Don't test against musl if it is not available

crates/libm-test/examples/plot_domains.rs

+8-2
Original file line numberDiff line numberDiff line change
@@ -56,14 +56,20 @@ where
5656
Op::RustArgs: SpacedInput<Op>,
5757
{
5858
let mut ctx = CheckCtx::new(Op::IDENTIFIER, CheckBasis::Mpfr, GeneratorKind::Spaced);
59-
plot_one_generator(out_dir, &ctx, "logspace", config, spaced::get_test_cases::<Op>(&ctx).0);
59+
plot_one_generator(
60+
out_dir,
61+
&ctx,
62+
"logspace",
63+
config,
64+
spaced::get_test_cases::<Op>(ctx.clone()).0,
65+
);
6066
ctx.gen_kind = GeneratorKind::EdgeCases;
6167
plot_one_generator(
6268
out_dir,
6369
&ctx,
6470
"edge_cases",
6571
config,
66-
edge_cases::get_test_cases::<Op>(&ctx).0,
72+
edge_cases::get_test_cases::<Op>(ctx.clone()).0,
6773
);
6874
}
6975

crates/libm-test/src/gen/edge_cases.rs

+14-10
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@ use libm::support::{Float, Int};
55
use crate::domain::get_domain;
66
use crate::gen::KnownSize;
77
use crate::run_cfg::{check_near_count, check_point_count};
8-
use crate::{CheckCtx, FloatExt, MathOp, test_log};
8+
use crate::{CheckCtx, FloatExt, GeneratorKind, MathOp, test_log};
99

1010
/// Generate a sequence of edge cases, e.g. numbers near zeroes and infiniteis.
1111
pub trait EdgeCaseInput<Op> {
12-
fn get_cases(ctx: &CheckCtx) -> (impl Iterator<Item = Self> + Send, u64);
12+
fn get_cases(ctx: CheckCtx) -> (impl Iterator<Item = Self> + Send, u64);
1313
}
1414

1515
/// Create a list of values around interesting points (infinities, zeroes, NaNs).
@@ -140,7 +140,8 @@ macro_rules! impl_edge_case_input {
140140
where
141141
Op: MathOp<RustArgs = Self, FTy = $fty>,
142142
{
143-
fn get_cases(ctx: &CheckCtx) -> (impl Iterator<Item = Self>, u64) {
143+
fn get_cases(ctx: CheckCtx) -> (impl Iterator<Item = Self>, u64) {
144+
let ctx = &ctx;
144145
let (iter0, steps0) = float_edge_cases::<Op>(ctx, 0);
145146
let iter0 = iter0.map(|v| (v,));
146147
(iter0, steps0)
@@ -151,7 +152,8 @@ macro_rules! impl_edge_case_input {
151152
where
152153
Op: MathOp<RustArgs = Self, FTy = $fty>,
153154
{
154-
fn get_cases(ctx: &CheckCtx) -> (impl Iterator<Item = Self>, u64) {
155+
fn get_cases(ctx: CheckCtx) -> (impl Iterator<Item = Self>, u64) {
156+
let ctx = &ctx;
155157
let (iter0, steps0) = float_edge_cases::<Op>(ctx, 0);
156158
let (iter1, steps1) = float_edge_cases::<Op>(ctx, 1);
157159
let iter =
@@ -165,7 +167,8 @@ macro_rules! impl_edge_case_input {
165167
where
166168
Op: MathOp<RustArgs = Self, FTy = $fty>,
167169
{
168-
fn get_cases(ctx: &CheckCtx) -> (impl Iterator<Item = Self>, u64) {
170+
fn get_cases(ctx: CheckCtx) -> (impl Iterator<Item = Self>, u64) {
171+
let ctx = &ctx;
169172
let (iter0, steps0) = float_edge_cases::<Op>(ctx, 0);
170173
let (iter1, steps1) = float_edge_cases::<Op>(ctx, 1);
171174
let (iter2, steps2) = float_edge_cases::<Op>(ctx, 2);
@@ -185,7 +188,8 @@ macro_rules! impl_edge_case_input {
185188
where
186189
Op: MathOp<RustArgs = Self, FTy = $fty>,
187190
{
188-
fn get_cases(ctx: &CheckCtx) -> (impl Iterator<Item = Self>, u64) {
191+
fn get_cases(ctx: CheckCtx) -> (impl Iterator<Item = Self>, u64) {
192+
let ctx = &ctx;
189193
let (iter0, steps0) = int_edge_cases(ctx, 0);
190194
let (iter1, steps1) = float_edge_cases::<Op>(ctx, 1);
191195

@@ -201,7 +205,8 @@ macro_rules! impl_edge_case_input {
201205
where
202206
Op: MathOp<RustArgs = Self, FTy = $fty>,
203207
{
204-
fn get_cases(ctx: &CheckCtx) -> (impl Iterator<Item = Self>, u64) {
208+
fn get_cases(ctx: CheckCtx) -> (impl Iterator<Item = Self>, u64) {
209+
let ctx = &ctx;
205210
let (iter0, steps0) = float_edge_cases::<Op>(ctx, 0);
206211
let (iter1, steps1) = int_edge_cases(ctx, 1);
207212

@@ -222,13 +227,12 @@ impl_edge_case_input!(f64);
222227
#[cfg(f128_enabled)]
223228
impl_edge_case_input!(f128);
224229

225-
pub fn get_test_cases<Op>(
226-
ctx: &CheckCtx,
227-
) -> (impl Iterator<Item = Op::RustArgs> + Send + use<'_, Op>, u64)
230+
pub fn get_test_cases<Op>(ctx: CheckCtx) -> (impl Iterator<Item = Op::RustArgs> + Send, u64)
228231
where
229232
Op: MathOp,
230233
Op::RustArgs: EdgeCaseInput<Op>,
231234
{
235+
assert_eq!(ctx.gen_kind, GeneratorKind::EdgeCases);
232236
let (iter, count) = Op::RustArgs::get_cases(ctx);
233237

234238
// Wrap in `KnownSize` so we get an assertion if the cuunt is wrong.

crates/libm-test/src/gen/random.rs

+19-11
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ use rand::{Rng, SeedableRng};
99
use rand_chacha::ChaCha8Rng;
1010

1111
use super::KnownSize;
12-
use crate::CheckCtx;
1312
use crate::run_cfg::{int_range, iteration_count};
13+
use crate::{CheckCtx, GeneratorKind, MathOp};
1414

1515
pub(crate) const SEED_ENV: &str = "LIBM_SEED";
1616

@@ -27,7 +27,7 @@ pub(crate) static SEED: LazyLock<[u8; 32]> = LazyLock::new(|| {
2727

2828
/// Generate a sequence of random values of this type.
2929
pub trait RandomInput: Sized {
30-
fn get_cases(ctx: &CheckCtx) -> (impl Iterator<Item = Self> + Send, u64);
30+
fn get_cases(ctx: CheckCtx) -> (impl Iterator<Item = Self> + Send, u64);
3131
}
3232

3333
/// Generate a sequence of deterministically random floats.
@@ -51,15 +51,17 @@ fn random_ints(count: u64, range: RangeInclusive<i32>) -> impl Iterator<Item = i
5151
macro_rules! impl_random_input {
5252
($fty:ty) => {
5353
impl RandomInput for ($fty,) {
54-
fn get_cases(ctx: &CheckCtx) -> (impl Iterator<Item = Self>, u64) {
54+
fn get_cases(ctx: CheckCtx) -> (impl Iterator<Item = Self>, u64) {
55+
let ctx = &ctx;
5556
let count = iteration_count(ctx, 0);
5657
let iter = random_floats(count).map(|f: $fty| (f,));
5758
(iter, count)
5859
}
5960
}
6061

6162
impl RandomInput for ($fty, $fty) {
62-
fn get_cases(ctx: &CheckCtx) -> (impl Iterator<Item = Self>, u64) {
63+
fn get_cases(ctx: CheckCtx) -> (impl Iterator<Item = Self>, u64) {
64+
let ctx = &ctx;
6365
let count0 = iteration_count(ctx, 0);
6466
let count1 = iteration_count(ctx, 1);
6567
let iter = random_floats(count0)
@@ -69,7 +71,8 @@ macro_rules! impl_random_input {
6971
}
7072

7173
impl RandomInput for ($fty, $fty, $fty) {
72-
fn get_cases(ctx: &CheckCtx) -> (impl Iterator<Item = Self>, u64) {
74+
fn get_cases(ctx: CheckCtx) -> (impl Iterator<Item = Self>, u64) {
75+
let ctx = &ctx;
7376
let count0 = iteration_count(ctx, 0);
7477
let count1 = iteration_count(ctx, 1);
7578
let count2 = iteration_count(ctx, 2);
@@ -83,7 +86,8 @@ macro_rules! impl_random_input {
8386
}
8487

8588
impl RandomInput for (i32, $fty) {
86-
fn get_cases(ctx: &CheckCtx) -> (impl Iterator<Item = Self>, u64) {
89+
fn get_cases(ctx: CheckCtx) -> (impl Iterator<Item = Self>, u64) {
90+
let ctx = &ctx;
8791
let count0 = iteration_count(ctx, 0);
8892
let count1 = iteration_count(ctx, 1);
8993
let range0 = int_range(ctx, 0);
@@ -94,7 +98,8 @@ macro_rules! impl_random_input {
9498
}
9599

96100
impl RandomInput for ($fty, i32) {
97-
fn get_cases(ctx: &CheckCtx) -> (impl Iterator<Item = Self>, u64) {
101+
fn get_cases(ctx: CheckCtx) -> (impl Iterator<Item = Self>, u64) {
102+
let ctx = &ctx;
98103
let count0 = iteration_count(ctx, 0);
99104
let count1 = iteration_count(ctx, 1);
100105
let range1 = int_range(ctx, 1);
@@ -115,10 +120,13 @@ impl_random_input!(f64);
115120
impl_random_input!(f128);
116121

117122
/// Create a test case iterator.
118-
pub fn get_test_cases<RustArgs: RandomInput>(
119-
ctx: &CheckCtx,
120-
) -> (impl Iterator<Item = RustArgs> + Send + use<'_, RustArgs>, u64) {
121-
let (iter, count) = RustArgs::get_cases(ctx);
123+
pub fn get_test_cases<Op>(ctx: CheckCtx) -> (impl Iterator<Item = Op::RustArgs> + Send, u64)
124+
where
125+
Op: MathOp,
126+
Op::RustArgs: RandomInput,
127+
{
128+
assert_eq!(ctx.gen_kind, GeneratorKind::Random);
129+
let (iter, count) = Op::RustArgs::get_cases(ctx);
122130

123131
// Wrap in `KnownSize` so we get an assertion if the cuunt is wrong.
124132
(KnownSize::new(iter, count), count)

crates/libm-test/src/gen/spaced.rs

+29-30
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@ use libm::support::{Float, MinInt};
66
use crate::domain::get_domain;
77
use crate::op::OpITy;
88
use crate::run_cfg::{int_range, iteration_count};
9-
use crate::{CheckCtx, MathOp, linear_ints, logspace};
9+
use crate::{CheckCtx, GeneratorKind, MathOp, linear_ints, logspace};
1010

1111
/// Generate a sequence of inputs that eiher cover the domain in completeness (for smaller float
1212
/// types and single argument functions) or provide evenly spaced inputs across the domain with
1313
/// approximately `u32::MAX` total iterations.
1414
pub trait SpacedInput<Op> {
15-
fn get_cases(ctx: &CheckCtx) -> (impl Iterator<Item = Self> + Send, u64);
15+
fn get_cases(ctx: CheckCtx) -> (impl Iterator<Item = Self> + Send, u64);
1616
}
1717

1818
/// Construct an iterator from `logspace` and also calculate the total number of steps expected
@@ -87,8 +87,8 @@ macro_rules! impl_spaced_input {
8787
where
8888
Op: MathOp<RustArgs = Self, FTy = $fty>,
8989
{
90-
fn get_cases(ctx: &CheckCtx) -> (impl Iterator<Item = Self>, u64) {
91-
let max_steps0 = iteration_count(ctx, 0);
90+
fn get_cases(ctx: CheckCtx) -> (impl Iterator<Item = Self>, u64) {
91+
let max_steps0 = iteration_count(&ctx, 0);
9292
// `f16` and `f32` can have exhaustive tests.
9393
match value_count::<Op::FTy>() {
9494
Some(steps0) if steps0 <= max_steps0 => {
@@ -97,7 +97,7 @@ macro_rules! impl_spaced_input {
9797
(EitherIter::A(iter0), steps0)
9898
}
9999
_ => {
100-
let (iter0, steps0) = logspace_steps::<Op>(ctx, 0, max_steps0);
100+
let (iter0, steps0) = logspace_steps::<Op>(&ctx, 0, max_steps0);
101101
let iter0 = iter0.map(|v| (v,));
102102
(EitherIter::B(iter0), steps0)
103103
}
@@ -109,9 +109,9 @@ macro_rules! impl_spaced_input {
109109
where
110110
Op: MathOp<RustArgs = Self, FTy = $fty>,
111111
{
112-
fn get_cases(ctx: &CheckCtx) -> (impl Iterator<Item = Self>, u64) {
113-
let max_steps0 = iteration_count(ctx, 0);
114-
let max_steps1 = iteration_count(ctx, 1);
112+
fn get_cases(ctx: CheckCtx) -> (impl Iterator<Item = Self>, u64) {
113+
let max_steps0 = iteration_count(&ctx, 0);
114+
let max_steps1 = iteration_count(&ctx, 1);
115115
// `f16` can have exhaustive tests.
116116
match value_count::<Op::FTy>() {
117117
Some(count) if count <= max_steps0 && count <= max_steps1 => {
@@ -120,8 +120,8 @@ macro_rules! impl_spaced_input {
120120
(EitherIter::A(iter), count.checked_mul(count).unwrap())
121121
}
122122
_ => {
123-
let (iter0, steps0) = logspace_steps::<Op>(ctx, 0, max_steps0);
124-
let (iter1, steps1) = logspace_steps::<Op>(ctx, 1, max_steps1);
123+
let (iter0, steps0) = logspace_steps::<Op>(&ctx, 0, max_steps0);
124+
let (iter1, steps1) = logspace_steps::<Op>(&ctx, 1, max_steps1);
125125
let iter = iter0.flat_map(move |first| {
126126
iter1.clone().map(move |second| (first, second))
127127
});
@@ -136,10 +136,10 @@ macro_rules! impl_spaced_input {
136136
where
137137
Op: MathOp<RustArgs = Self, FTy = $fty>,
138138
{
139-
fn get_cases(ctx: &CheckCtx) -> (impl Iterator<Item = Self>, u64) {
140-
let max_steps0 = iteration_count(ctx, 0);
141-
let max_steps1 = iteration_count(ctx, 1);
142-
let max_steps2 = iteration_count(ctx, 2);
139+
fn get_cases(ctx: CheckCtx) -> (impl Iterator<Item = Self>, u64) {
140+
let max_steps0 = iteration_count(&ctx, 0);
141+
let max_steps1 = iteration_count(&ctx, 1);
142+
let max_steps2 = iteration_count(&ctx, 2);
143143
// `f16` can be exhaustive tested if `LIBM_EXTENSIVE_TESTS` is incresed.
144144
match value_count::<Op::FTy>() {
145145
Some(count)
@@ -153,9 +153,9 @@ macro_rules! impl_spaced_input {
153153
(EitherIter::A(iter), count.checked_pow(3).unwrap())
154154
}
155155
_ => {
156-
let (iter0, steps0) = logspace_steps::<Op>(ctx, 0, max_steps0);
157-
let (iter1, steps1) = logspace_steps::<Op>(ctx, 1, max_steps1);
158-
let (iter2, steps2) = logspace_steps::<Op>(ctx, 2, max_steps2);
156+
let (iter0, steps0) = logspace_steps::<Op>(&ctx, 0, max_steps0);
157+
let (iter1, steps1) = logspace_steps::<Op>(&ctx, 1, max_steps1);
158+
let (iter2, steps2) = logspace_steps::<Op>(&ctx, 2, max_steps2);
159159

160160
let iter = iter0
161161
.flat_map(move |first| iter1.clone().map(move |second| (first, second)))
@@ -175,10 +175,10 @@ macro_rules! impl_spaced_input {
175175
where
176176
Op: MathOp<RustArgs = Self, FTy = $fty>,
177177
{
178-
fn get_cases(ctx: &CheckCtx) -> (impl Iterator<Item = Self>, u64) {
179-
let range0 = int_range(ctx, 0);
180-
let max_steps0 = iteration_count(ctx, 0);
181-
let max_steps1 = iteration_count(ctx, 1);
178+
fn get_cases(ctx: CheckCtx) -> (impl Iterator<Item = Self>, u64) {
179+
let range0 = int_range(&ctx, 0);
180+
let max_steps0 = iteration_count(&ctx, 0);
181+
let max_steps1 = iteration_count(&ctx, 1);
182182
match value_count::<Op::FTy>() {
183183
Some(count1) if count1 <= max_steps1 => {
184184
let (iter0, steps0) = linear_ints(range0, max_steps0);
@@ -188,7 +188,7 @@ macro_rules! impl_spaced_input {
188188
}
189189
_ => {
190190
let (iter0, steps0) = linear_ints(range0, max_steps0);
191-
let (iter1, steps1) = logspace_steps::<Op>(ctx, 1, max_steps1);
191+
let (iter1, steps1) = logspace_steps::<Op>(&ctx, 1, max_steps1);
192192

193193
let iter = iter0.flat_map(move |first| {
194194
iter1.clone().map(move |second| (first, second))
@@ -205,10 +205,10 @@ macro_rules! impl_spaced_input {
205205
where
206206
Op: MathOp<RustArgs = Self, FTy = $fty>,
207207
{
208-
fn get_cases(ctx: &CheckCtx) -> (impl Iterator<Item = Self>, u64) {
209-
let max_steps0 = iteration_count(ctx, 0);
210-
let range1 = int_range(ctx, 1);
211-
let max_steps1 = iteration_count(ctx, 1);
208+
fn get_cases(ctx: CheckCtx) -> (impl Iterator<Item = Self>, u64) {
209+
let max_steps0 = iteration_count(&ctx, 0);
210+
let range1 = int_range(&ctx, 1);
211+
let max_steps1 = iteration_count(&ctx, 1);
212212
match value_count::<Op::FTy>() {
213213
Some(count0) if count0 <= max_steps0 => {
214214
let (iter1, steps1) = linear_ints(range1, max_steps1);
@@ -218,7 +218,7 @@ macro_rules! impl_spaced_input {
218218
(EitherIter::A(iter), count0.checked_mul(steps1).unwrap())
219219
}
220220
_ => {
221-
let (iter0, steps0) = logspace_steps::<Op>(ctx, 0, max_steps0);
221+
let (iter0, steps0) = logspace_steps::<Op>(&ctx, 0, max_steps0);
222222
let (iter1, steps1) = linear_ints(range1, max_steps1);
223223

224224
let iter = iter0.flat_map(move |first| {
@@ -242,12 +242,11 @@ impl_spaced_input!(f64);
242242
impl_spaced_input!(f128);
243243

244244
/// Create a test case iterator for extensive inputs. Also returns the total test case count.
245-
pub fn get_test_cases<Op>(
246-
ctx: &CheckCtx,
247-
) -> (impl Iterator<Item = Op::RustArgs> + Send + use<'_, Op>, u64)
245+
pub fn get_test_cases<Op>(ctx: CheckCtx) -> (impl Iterator<Item = Op::RustArgs> + Send, u64)
248246
where
249247
Op: MathOp,
250248
Op::RustArgs: SpacedInput<Op>,
251249
{
250+
assert_eq!(ctx.gen_kind, GeneratorKind::Spaced);
252251
Op::RustArgs::get_cases(ctx)
253252
}

crates/libm-test/tests/compare_built_musl.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ macro_rules! musl_tests {
3939
fn [< musl_random_ $fn_name >]() {
4040
type Op = libm_test::op::$fn_name::Routine;
4141
let ctx = CheckCtx::new(Op::IDENTIFIER, BASIS, GeneratorKind::Random);
42-
let cases = random::get_test_cases::<<Op as MathOp>::RustArgs>(&ctx).0;
42+
let cases = random::get_test_cases::<Op>(ctx.clone()).0;
4343
musl_runner::<Op>(&ctx, cases, musl_math_sys::$fn_name);
4444
}
4545

@@ -48,7 +48,7 @@ macro_rules! musl_tests {
4848
fn [< musl_edge_case_ $fn_name >]() {
4949
type Op = libm_test::op::$fn_name::Routine;
5050
let ctx = CheckCtx::new(Op::IDENTIFIER, BASIS, GeneratorKind::EdgeCases);
51-
let cases = edge_cases::get_test_cases::<Op>(&ctx).0;
51+
let cases = edge_cases::get_test_cases::<Op>(ctx.clone()).0;
5252
musl_runner::<Op>(&ctx, cases, musl_math_sys::$fn_name);
5353
}
5454

@@ -57,7 +57,7 @@ macro_rules! musl_tests {
5757
fn [< musl_logspace_ $fn_name >]() {
5858
type Op = libm_test::op::$fn_name::Routine;
5959
let ctx = CheckCtx::new(Op::IDENTIFIER, BASIS, GeneratorKind::Spaced);
60-
let cases = spaced::get_test_cases::<Op>(&ctx).0;
60+
let cases = spaced::get_test_cases::<Op>(ctx.clone()).0;
6161
musl_runner::<Op>(&ctx, cases, musl_math_sys::$fn_name);
6262
}
6363
}

0 commit comments

Comments
 (0)