diff --git a/crates/libm-test/benches/icount.rs b/crates/libm-test/benches/icount.rs index 53ecb5a37..33c290c0b 100644 --- a/crates/libm-test/benches/icount.rs +++ b/crates/libm-test/benches/icount.rs @@ -20,7 +20,7 @@ macro_rules! icount_benches { let mut ctx = CheckCtx::new( Op::IDENTIFIER, CheckBasis::None, - GeneratorKind::QuickSpaced + GeneratorKind::Spaced ); ctx.override_iterations(BENCH_ITER_ITEMS); let ret = spaced::get_test_cases::(&ctx).0.collect::>(); diff --git a/crates/libm-test/benches/random.rs b/crates/libm-test/benches/random.rs index 66486a56a..820e7d73c 100644 --- a/crates/libm-test/benches/random.rs +++ b/crates/libm-test/benches/random.rs @@ -54,7 +54,7 @@ where let ctx = CheckCtx::new(Op::IDENTIFIER, CheckBasis::Musl, GeneratorKind::Random); let benchvec: Vec<_> = - random::get_test_cases::(&ctx).0.take(BENCH_ITER_ITEMS).collect(); + random::get_test_cases::(ctx.clone()).0.take(BENCH_ITER_ITEMS).collect(); // Perform a sanity check that we are benchmarking the same thing // Don't test against musl if it is not available diff --git a/crates/libm-test/examples/plot_domains.rs b/crates/libm-test/examples/plot_domains.rs index 441889c69..c076a30f3 100644 --- a/crates/libm-test/examples/plot_domains.rs +++ b/crates/libm-test/examples/plot_domains.rs @@ -55,15 +55,21 @@ where Op: MathOp, Op::RustArgs: SpacedInput, { - let mut ctx = CheckCtx::new(Op::IDENTIFIER, CheckBasis::Mpfr, GeneratorKind::QuickSpaced); - plot_one_generator(out_dir, &ctx, "logspace", config, spaced::get_test_cases::(&ctx).0); + let mut ctx = CheckCtx::new(Op::IDENTIFIER, CheckBasis::Mpfr, GeneratorKind::Spaced); + plot_one_generator( + out_dir, + &ctx, + "logspace", + config, + spaced::get_test_cases::(ctx.clone()).0, + ); ctx.gen_kind = GeneratorKind::EdgeCases; plot_one_generator( out_dir, &ctx, "edge_cases", config, - edge_cases::get_test_cases::(&ctx).0, + edge_cases::get_test_cases::(ctx.clone()).0, ); } diff --git a/crates/libm-test/src/gen/edge_cases.rs b/crates/libm-test/src/gen/edge_cases.rs index 8de954ae3..8771df135 100644 --- a/crates/libm-test/src/gen/edge_cases.rs +++ b/crates/libm-test/src/gen/edge_cases.rs @@ -5,11 +5,11 @@ use libm::support::{Float, Int}; use crate::domain::get_domain; use crate::gen::KnownSize; use crate::run_cfg::{check_near_count, check_point_count}; -use crate::{CheckCtx, FloatExt, MathOp, test_log}; +use crate::{CheckCtx, FloatExt, GeneratorKind, MathOp, test_log}; /// Generate a sequence of edge cases, e.g. numbers near zeroes and infiniteis. pub trait EdgeCaseInput { - fn get_cases(ctx: &CheckCtx) -> (impl Iterator + Send, u64); + fn get_cases(ctx: CheckCtx) -> (impl Iterator + Send, u64); } /// Create a list of values around interesting points (infinities, zeroes, NaNs). @@ -140,7 +140,8 @@ macro_rules! impl_edge_case_input { where Op: MathOp, { - fn get_cases(ctx: &CheckCtx) -> (impl Iterator, u64) { + fn get_cases(ctx: CheckCtx) -> (impl Iterator, u64) { + let ctx = &ctx; let (iter0, steps0) = float_edge_cases::(ctx, 0); let iter0 = iter0.map(|v| (v,)); (iter0, steps0) @@ -151,7 +152,8 @@ macro_rules! impl_edge_case_input { where Op: MathOp, { - fn get_cases(ctx: &CheckCtx) -> (impl Iterator, u64) { + fn get_cases(ctx: CheckCtx) -> (impl Iterator, u64) { + let ctx = &ctx; let (iter0, steps0) = float_edge_cases::(ctx, 0); let (iter1, steps1) = float_edge_cases::(ctx, 1); let iter = @@ -165,7 +167,8 @@ macro_rules! impl_edge_case_input { where Op: MathOp, { - fn get_cases(ctx: &CheckCtx) -> (impl Iterator, u64) { + fn get_cases(ctx: CheckCtx) -> (impl Iterator, u64) { + let ctx = &ctx; let (iter0, steps0) = float_edge_cases::(ctx, 0); let (iter1, steps1) = float_edge_cases::(ctx, 1); let (iter2, steps2) = float_edge_cases::(ctx, 2); @@ -185,7 +188,8 @@ macro_rules! impl_edge_case_input { where Op: MathOp, { - fn get_cases(ctx: &CheckCtx) -> (impl Iterator, u64) { + fn get_cases(ctx: CheckCtx) -> (impl Iterator, u64) { + let ctx = &ctx; let (iter0, steps0) = int_edge_cases(ctx, 0); let (iter1, steps1) = float_edge_cases::(ctx, 1); @@ -201,7 +205,8 @@ macro_rules! impl_edge_case_input { where Op: MathOp, { - fn get_cases(ctx: &CheckCtx) -> (impl Iterator, u64) { + fn get_cases(ctx: CheckCtx) -> (impl Iterator, u64) { + let ctx = &ctx; let (iter0, steps0) = float_edge_cases::(ctx, 0); let (iter1, steps1) = int_edge_cases(ctx, 1); @@ -222,13 +227,12 @@ impl_edge_case_input!(f64); #[cfg(f128_enabled)] impl_edge_case_input!(f128); -pub fn get_test_cases( - ctx: &CheckCtx, -) -> (impl Iterator + Send + use<'_, Op>, u64) +pub fn get_test_cases(ctx: CheckCtx) -> (impl Iterator + Send, u64) where Op: MathOp, Op::RustArgs: EdgeCaseInput, { + assert_eq!(ctx.gen_kind, GeneratorKind::EdgeCases); let (iter, count) = Op::RustArgs::get_cases(ctx); // Wrap in `KnownSize` so we get an assertion if the cuunt is wrong. diff --git a/crates/libm-test/src/gen/random.rs b/crates/libm-test/src/gen/random.rs index 5b127f38d..3eb9a15f5 100644 --- a/crates/libm-test/src/gen/random.rs +++ b/crates/libm-test/src/gen/random.rs @@ -9,8 +9,8 @@ use rand::{Rng, SeedableRng}; use rand_chacha::ChaCha8Rng; use super::KnownSize; -use crate::CheckCtx; use crate::run_cfg::{int_range, iteration_count}; +use crate::{CheckCtx, GeneratorKind, MathOp}; pub(crate) const SEED_ENV: &str = "LIBM_SEED"; @@ -27,7 +27,7 @@ pub(crate) static SEED: LazyLock<[u8; 32]> = LazyLock::new(|| { /// Generate a sequence of random values of this type. pub trait RandomInput: Sized { - fn get_cases(ctx: &CheckCtx) -> (impl Iterator + Send, u64); + fn get_cases(ctx: CheckCtx) -> (impl Iterator + Send, u64); } /// Generate a sequence of deterministically random floats. @@ -51,7 +51,8 @@ fn random_ints(count: u64, range: RangeInclusive) -> impl Iterator { impl RandomInput for ($fty,) { - fn get_cases(ctx: &CheckCtx) -> (impl Iterator, u64) { + fn get_cases(ctx: CheckCtx) -> (impl Iterator, u64) { + let ctx = &ctx; let count = iteration_count(ctx, 0); let iter = random_floats(count).map(|f: $fty| (f,)); (iter, count) @@ -59,7 +60,8 @@ macro_rules! impl_random_input { } impl RandomInput for ($fty, $fty) { - fn get_cases(ctx: &CheckCtx) -> (impl Iterator, u64) { + fn get_cases(ctx: CheckCtx) -> (impl Iterator, u64) { + let ctx = &ctx; let count0 = iteration_count(ctx, 0); let count1 = iteration_count(ctx, 1); let iter = random_floats(count0) @@ -69,7 +71,8 @@ macro_rules! impl_random_input { } impl RandomInput for ($fty, $fty, $fty) { - fn get_cases(ctx: &CheckCtx) -> (impl Iterator, u64) { + fn get_cases(ctx: CheckCtx) -> (impl Iterator, u64) { + let ctx = &ctx; let count0 = iteration_count(ctx, 0); let count1 = iteration_count(ctx, 1); let count2 = iteration_count(ctx, 2); @@ -83,7 +86,8 @@ macro_rules! impl_random_input { } impl RandomInput for (i32, $fty) { - fn get_cases(ctx: &CheckCtx) -> (impl Iterator, u64) { + fn get_cases(ctx: CheckCtx) -> (impl Iterator, u64) { + let ctx = &ctx; let count0 = iteration_count(ctx, 0); let count1 = iteration_count(ctx, 1); let range0 = int_range(ctx, 0); @@ -94,7 +98,8 @@ macro_rules! impl_random_input { } impl RandomInput for ($fty, i32) { - fn get_cases(ctx: &CheckCtx) -> (impl Iterator, u64) { + fn get_cases(ctx: CheckCtx) -> (impl Iterator, u64) { + let ctx = &ctx; let count0 = iteration_count(ctx, 0); let count1 = iteration_count(ctx, 1); let range1 = int_range(ctx, 1); @@ -115,10 +120,13 @@ impl_random_input!(f64); impl_random_input!(f128); /// Create a test case iterator. -pub fn get_test_cases( - ctx: &CheckCtx, -) -> (impl Iterator + Send + use<'_, RustArgs>, u64) { - let (iter, count) = RustArgs::get_cases(ctx); +pub fn get_test_cases(ctx: CheckCtx) -> (impl Iterator + Send, u64) +where + Op: MathOp, + Op::RustArgs: RandomInput, +{ + assert_eq!(ctx.gen_kind, GeneratorKind::Random); + let (iter, count) = Op::RustArgs::get_cases(ctx); // Wrap in `KnownSize` so we get an assertion if the cuunt is wrong. (KnownSize::new(iter, count), count) diff --git a/crates/libm-test/src/gen/spaced.rs b/crates/libm-test/src/gen/spaced.rs index bea3f4c7e..74e35d8a6 100644 --- a/crates/libm-test/src/gen/spaced.rs +++ b/crates/libm-test/src/gen/spaced.rs @@ -6,13 +6,13 @@ use libm::support::{Float, MinInt}; use crate::domain::get_domain; use crate::op::OpITy; use crate::run_cfg::{int_range, iteration_count}; -use crate::{CheckCtx, MathOp, linear_ints, logspace}; +use crate::{CheckCtx, GeneratorKind, MathOp, linear_ints, logspace}; /// Generate a sequence of inputs that eiher cover the domain in completeness (for smaller float /// types and single argument functions) or provide evenly spaced inputs across the domain with /// approximately `u32::MAX` total iterations. pub trait SpacedInput { - fn get_cases(ctx: &CheckCtx) -> (impl Iterator + Send, u64); + fn get_cases(ctx: CheckCtx) -> (impl Iterator + Send, u64); } /// Construct an iterator from `logspace` and also calculate the total number of steps expected @@ -87,8 +87,8 @@ macro_rules! impl_spaced_input { where Op: MathOp, { - fn get_cases(ctx: &CheckCtx) -> (impl Iterator, u64) { - let max_steps0 = iteration_count(ctx, 0); + fn get_cases(ctx: CheckCtx) -> (impl Iterator, u64) { + let max_steps0 = iteration_count(&ctx, 0); // `f16` and `f32` can have exhaustive tests. match value_count::() { Some(steps0) if steps0 <= max_steps0 => { @@ -97,7 +97,7 @@ macro_rules! impl_spaced_input { (EitherIter::A(iter0), steps0) } _ => { - let (iter0, steps0) = logspace_steps::(ctx, 0, max_steps0); + let (iter0, steps0) = logspace_steps::(&ctx, 0, max_steps0); let iter0 = iter0.map(|v| (v,)); (EitherIter::B(iter0), steps0) } @@ -109,9 +109,9 @@ macro_rules! impl_spaced_input { where Op: MathOp, { - fn get_cases(ctx: &CheckCtx) -> (impl Iterator, u64) { - let max_steps0 = iteration_count(ctx, 0); - let max_steps1 = iteration_count(ctx, 1); + fn get_cases(ctx: CheckCtx) -> (impl Iterator, u64) { + let max_steps0 = iteration_count(&ctx, 0); + let max_steps1 = iteration_count(&ctx, 1); // `f16` can have exhaustive tests. match value_count::() { Some(count) if count <= max_steps0 && count <= max_steps1 => { @@ -120,8 +120,8 @@ macro_rules! impl_spaced_input { (EitherIter::A(iter), count.checked_mul(count).unwrap()) } _ => { - let (iter0, steps0) = logspace_steps::(ctx, 0, max_steps0); - let (iter1, steps1) = logspace_steps::(ctx, 1, max_steps1); + let (iter0, steps0) = logspace_steps::(&ctx, 0, max_steps0); + let (iter1, steps1) = logspace_steps::(&ctx, 1, max_steps1); let iter = iter0.flat_map(move |first| { iter1.clone().map(move |second| (first, second)) }); @@ -136,10 +136,10 @@ macro_rules! impl_spaced_input { where Op: MathOp, { - fn get_cases(ctx: &CheckCtx) -> (impl Iterator, u64) { - let max_steps0 = iteration_count(ctx, 0); - let max_steps1 = iteration_count(ctx, 1); - let max_steps2 = iteration_count(ctx, 2); + fn get_cases(ctx: CheckCtx) -> (impl Iterator, u64) { + let max_steps0 = iteration_count(&ctx, 0); + let max_steps1 = iteration_count(&ctx, 1); + let max_steps2 = iteration_count(&ctx, 2); // `f16` can be exhaustive tested if `LIBM_EXTENSIVE_TESTS` is incresed. match value_count::() { Some(count) @@ -153,9 +153,9 @@ macro_rules! impl_spaced_input { (EitherIter::A(iter), count.checked_pow(3).unwrap()) } _ => { - let (iter0, steps0) = logspace_steps::(ctx, 0, max_steps0); - let (iter1, steps1) = logspace_steps::(ctx, 1, max_steps1); - let (iter2, steps2) = logspace_steps::(ctx, 2, max_steps2); + let (iter0, steps0) = logspace_steps::(&ctx, 0, max_steps0); + let (iter1, steps1) = logspace_steps::(&ctx, 1, max_steps1); + let (iter2, steps2) = logspace_steps::(&ctx, 2, max_steps2); let iter = iter0 .flat_map(move |first| iter1.clone().map(move |second| (first, second))) @@ -175,10 +175,10 @@ macro_rules! impl_spaced_input { where Op: MathOp, { - fn get_cases(ctx: &CheckCtx) -> (impl Iterator, u64) { - let range0 = int_range(ctx, 0); - let max_steps0 = iteration_count(ctx, 0); - let max_steps1 = iteration_count(ctx, 1); + fn get_cases(ctx: CheckCtx) -> (impl Iterator, u64) { + let range0 = int_range(&ctx, 0); + let max_steps0 = iteration_count(&ctx, 0); + let max_steps1 = iteration_count(&ctx, 1); match value_count::() { Some(count1) if count1 <= max_steps1 => { let (iter0, steps0) = linear_ints(range0, max_steps0); @@ -188,7 +188,7 @@ macro_rules! impl_spaced_input { } _ => { let (iter0, steps0) = linear_ints(range0, max_steps0); - let (iter1, steps1) = logspace_steps::(ctx, 1, max_steps1); + let (iter1, steps1) = logspace_steps::(&ctx, 1, max_steps1); let iter = iter0.flat_map(move |first| { iter1.clone().map(move |second| (first, second)) @@ -205,10 +205,10 @@ macro_rules! impl_spaced_input { where Op: MathOp, { - fn get_cases(ctx: &CheckCtx) -> (impl Iterator, u64) { - let max_steps0 = iteration_count(ctx, 0); - let range1 = int_range(ctx, 1); - let max_steps1 = iteration_count(ctx, 1); + fn get_cases(ctx: CheckCtx) -> (impl Iterator, u64) { + let max_steps0 = iteration_count(&ctx, 0); + let range1 = int_range(&ctx, 1); + let max_steps1 = iteration_count(&ctx, 1); match value_count::() { Some(count0) if count0 <= max_steps0 => { let (iter1, steps1) = linear_ints(range1, max_steps1); @@ -218,7 +218,7 @@ macro_rules! impl_spaced_input { (EitherIter::A(iter), count0.checked_mul(steps1).unwrap()) } _ => { - let (iter0, steps0) = logspace_steps::(ctx, 0, max_steps0); + let (iter0, steps0) = logspace_steps::(&ctx, 0, max_steps0); let (iter1, steps1) = linear_ints(range1, max_steps1); let iter = iter0.flat_map(move |first| { @@ -242,12 +242,11 @@ impl_spaced_input!(f64); impl_spaced_input!(f128); /// Create a test case iterator for extensive inputs. Also returns the total test case count. -pub fn get_test_cases( - ctx: &CheckCtx, -) -> (impl Iterator + Send + use<'_, Op>, u64) +pub fn get_test_cases(ctx: CheckCtx) -> (impl Iterator + Send, u64) where Op: MathOp, Op::RustArgs: SpacedInput, { + assert_eq!(ctx.gen_kind, GeneratorKind::Spaced); Op::RustArgs::get_cases(ctx) } diff --git a/crates/libm-test/src/run_cfg.rs b/crates/libm-test/src/run_cfg.rs index 783142e37..f660a0af5 100644 --- a/crates/libm-test/src/run_cfg.rs +++ b/crates/libm-test/src/run_cfg.rs @@ -21,10 +21,10 @@ static EXTENSIVE_ITER_OVERRIDE: LazyLock> = LazyLock::new(|| { /// Specific tests that need to have a reduced amount of iterations to complete in a reasonable /// amount of time. /// -/// Contains the itentifier+generator combo to match on, plus the factor to reduce by. -const EXTEMELY_SLOW_TESTS: &[(Identifier, GeneratorKind, u64)] = &[ - (Identifier::Fmodf128, GeneratorKind::QuickSpaced, 40), - (Identifier::Fmodf128, GeneratorKind::Extensive, 40), +/// Contains the itentifier+generator+exhaustive combo to match on, plus the factor to reduce by. +const EXTEMELY_SLOW_TESTS: &[(Identifier, GeneratorKind, bool, u64)] = &[ + (Identifier::Fmodf128, GeneratorKind::Spaced, false, 40), + (Identifier::Fmodf128, GeneratorKind::Spaced, true, 40), ]; /// Maximum number of iterations to run for a single routine. @@ -52,6 +52,7 @@ pub struct CheckCtx { /// Source of truth for tests. pub basis: CheckBasis, pub gen_kind: GeneratorKind, + pub extensive: bool, /// If specified, this value will override the value returned by [`iteration_count`]. pub override_iterations: Option, } @@ -67,12 +68,19 @@ impl CheckCtx { base_name_str: fn_ident.base_name().as_str(), basis, gen_kind, + extensive: false, override_iterations: None, }; ret.ulp = crate::default_ulp(&ret); ret } + /// Configure that this is an extensive test. + pub fn extensive(mut self, extensive: bool) -> Self { + self.extensive = extensive; + self + } + /// The number of input arguments for this function. pub fn input_count(&self) -> usize { self.fn_ident.math_op().rust_sig.args.len() @@ -99,8 +107,7 @@ pub enum CheckBasis { #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum GeneratorKind { EdgeCases, - Extensive, - QuickSpaced, + Spaced, Random, } @@ -216,21 +223,22 @@ pub fn iteration_count(ctx: &CheckCtx, argnum: usize) -> u64 { let random_iter_count = domain_iter_count / 100; let mut total_iterations = match ctx.gen_kind { - GeneratorKind::QuickSpaced => domain_iter_count, + GeneratorKind::Spaced if ctx.extensive => extensive_max_iterations(), + GeneratorKind::Spaced => domain_iter_count, GeneratorKind::Random => random_iter_count, - GeneratorKind::Extensive => extensive_max_iterations(), GeneratorKind::EdgeCases => { unimplemented!("edge case tests shoudn't need `iteration_count`") } }; // Some tests are significantly slower than others and need to be further reduced. - if let Some((_id, _gen, scale)) = EXTEMELY_SLOW_TESTS - .iter() - .find(|(id, gen, _scale)| *id == ctx.fn_ident && *gen == ctx.gen_kind) + if let Some((_id, _gen, _extensive, scale)) = + EXTEMELY_SLOW_TESTS.iter().find(|(id, gen, extensive, _scale)| { + *id == ctx.fn_ident && *gen == ctx.gen_kind && *extensive == ctx.extensive + }) { // However, do not override if the extensive iteration count has been manually set. - if !(ctx.gen_kind == GeneratorKind::Extensive && EXTENSIVE_ITER_OVERRIDE.is_some()) { + if !(ctx.extensive && EXTENSIVE_ITER_OVERRIDE.is_some()) { total_iterations /= scale; } } @@ -265,7 +273,7 @@ pub fn iteration_count(ctx: &CheckCtx, argnum: usize) -> u64 { let total = ntests.pow(t_env.input_count.try_into().unwrap()); let seed_msg = match ctx.gen_kind { - GeneratorKind::QuickSpaced | GeneratorKind::Extensive => String::new(), + GeneratorKind::Spaced => String::new(), GeneratorKind::Random => { format!(" using `{SEED_ENV}={}`", str::from_utf8(SEED.as_slice()).unwrap()) } @@ -307,8 +315,8 @@ pub fn int_range(ctx: &CheckCtx, argnum: usize) -> RangeInclusive { let extensive_range = (-0xfff)..=0xfffff; match ctx.gen_kind { - GeneratorKind::Extensive => extensive_range, - GeneratorKind::QuickSpaced | GeneratorKind::Random => non_extensive_range, + _ if ctx.extensive => extensive_range, + GeneratorKind::Spaced | GeneratorKind::Random => non_extensive_range, GeneratorKind::EdgeCases => extensive_range, } } diff --git a/crates/libm-test/tests/compare_built_musl.rs b/crates/libm-test/tests/compare_built_musl.rs index c8beaffc3..3fc48b5b3 100644 --- a/crates/libm-test/tests/compare_built_musl.rs +++ b/crates/libm-test/tests/compare_built_musl.rs @@ -39,7 +39,7 @@ macro_rules! musl_tests { fn [< musl_random_ $fn_name >]() { type Op = libm_test::op::$fn_name::Routine; let ctx = CheckCtx::new(Op::IDENTIFIER, BASIS, GeneratorKind::Random); - let cases = random::get_test_cases::<::RustArgs>(&ctx).0; + let cases = random::get_test_cases::(ctx.clone()).0; musl_runner::(&ctx, cases, musl_math_sys::$fn_name); } @@ -48,16 +48,16 @@ macro_rules! musl_tests { fn [< musl_edge_case_ $fn_name >]() { type Op = libm_test::op::$fn_name::Routine; let ctx = CheckCtx::new(Op::IDENTIFIER, BASIS, GeneratorKind::EdgeCases); - let cases = edge_cases::get_test_cases::(&ctx).0; + let cases = edge_cases::get_test_cases::(ctx.clone()).0; musl_runner::(&ctx, cases, musl_math_sys::$fn_name); } #[test] $(#[$attr])* - fn [< musl_quickspace_ $fn_name >]() { + fn [< musl_logspace_ $fn_name >]() { type Op = libm_test::op::$fn_name::Routine; - let ctx = CheckCtx::new(Op::IDENTIFIER, BASIS, GeneratorKind::QuickSpaced); - let cases = spaced::get_test_cases::(&ctx).0; + let ctx = CheckCtx::new(Op::IDENTIFIER, BASIS, GeneratorKind::Spaced); + let cases = spaced::get_test_cases::(ctx.clone()).0; musl_runner::(&ctx, cases, musl_math_sys::$fn_name); } } diff --git a/crates/libm-test/tests/multiprecision.rs b/crates/libm-test/tests/multiprecision.rs index 0d5c5e60c..72854e49e 100644 --- a/crates/libm-test/tests/multiprecision.rs +++ b/crates/libm-test/tests/multiprecision.rs @@ -29,7 +29,7 @@ macro_rules! mp_tests { fn [< mp_random_ $fn_name >]() { type Op = libm_test::op::$fn_name::Routine; let ctx = CheckCtx::new(Op::IDENTIFIER, BASIS, GeneratorKind::Random); - let cases = random::get_test_cases::<::RustArgs>(&ctx).0; + let cases = random::get_test_cases::(ctx.clone()).0; mp_runner::(&ctx, cases); } @@ -38,16 +38,16 @@ macro_rules! mp_tests { fn [< mp_edge_case_ $fn_name >]() { type Op = libm_test::op::$fn_name::Routine; let ctx = CheckCtx::new(Op::IDENTIFIER, BASIS, GeneratorKind::EdgeCases); - let cases = edge_cases::get_test_cases::(&ctx).0; + let cases = edge_cases::get_test_cases::(ctx.clone()).0; mp_runner::(&ctx, cases); } #[test] $(#[$attr])* - fn [< mp_quickspace_ $fn_name >]() { + fn [< mp_logspace_ $fn_name >]() { type Op = libm_test::op::$fn_name::Routine; - let ctx = CheckCtx::new(Op::IDENTIFIER, BASIS, GeneratorKind::QuickSpaced); - let cases = spaced::get_test_cases::(&ctx).0; + let ctx = CheckCtx::new(Op::IDENTIFIER, BASIS, GeneratorKind::Spaced); + let cases = spaced::get_test_cases::(ctx.clone()).0; mp_runner::(&ctx, cases); } } diff --git a/crates/libm-test/tests/z_extensive/run.rs b/crates/libm-test/tests/z_extensive/run.rs index a323c9110..20721d6be 100644 --- a/crates/libm-test/tests/z_extensive/run.rs +++ b/crates/libm-test/tests/z_extensive/run.rs @@ -6,7 +6,9 @@ use std::sync::atomic::{AtomicU64, Ordering}; use std::time::Duration; use indicatif::{ProgressBar, ProgressStyle}; -use libm_test::gen::spaced; +use libm_test::gen::edge_cases::EdgeCaseInput; +use libm_test::gen::random::RandomInput; +use libm_test::gen::{edge_cases, random, spaced}; use libm_test::mpfloat::MpOp; use libm_test::{ CheckBasis, CheckCtx, CheckOutput, GeneratorKind, MathOp, TestResult, TupleCall, @@ -17,7 +19,6 @@ use rayon::prelude::*; use spaced::SpacedInput; const BASIS: CheckBasis = CheckBasis::Mpfr; -const GEN_KIND: GeneratorKind = GeneratorKind::Extensive; /// Run the extensive test suite. pub fn run() { @@ -41,7 +42,7 @@ macro_rules! mp_extensive_tests { extra: [$push_to:ident], ) => { $(#[$attr])* - register_single_test::(&mut $push_to); + register_single_op::(&mut $push_to); }; } @@ -64,13 +65,43 @@ fn register_all_tests() -> Vec { } /// Add a single test to the list. -fn register_single_test(all: &mut Vec) +fn register_single_op(all: &mut Vec) where + Op: MathOp + MpOp + 'static, + Op::RustArgs: SpacedInput + RandomInput + EdgeCaseInput + Send, +{ + // All generators need to take `ctx` by value to avoid + // https://github.com/rust-lang/rust/issues/42940 + + let ctx = CheckCtx::new(Op::IDENTIFIER, BASIS, GeneratorKind::EdgeCases).extensive(true); + let (cases, total) = edge_cases::get_test_cases::(ctx.clone()); + register_single_test::(all, ctx, cases, total); + + let ctx = CheckCtx::new(Op::IDENTIFIER, BASIS, GeneratorKind::Spaced).extensive(true); + let (cases, total) = spaced::get_test_cases::(ctx.clone()); + register_single_test::(all, ctx, cases, total); + + let ctx = CheckCtx::new(Op::IDENTIFIER, BASIS, GeneratorKind::Random).extensive(true); + let (cases, total) = random::get_test_cases::(ctx.clone()); + register_single_test::(all, ctx, cases, total); +} + +fn register_single_test( + all: &mut Vec, + ctx: CheckCtx, + cases: impl Iterator + Send + 'static, + total: u64, +) where Op: MathOp + MpOp, - Op::RustArgs: SpacedInput + Send, + Op::RustArgs: SpacedInput + RandomInput + EdgeCaseInput + Send, { - let test_name = format!("mp_extensive_{}", Op::NAME); - let ctx = CheckCtx::new(Op::IDENTIFIER, BASIS, GEN_KIND); + let x = match ctx.gen_kind { + GeneratorKind::EdgeCases => "edge_cases", + GeneratorKind::Spaced => "logspace", + GeneratorKind::Random => "random", + }; + + let test_name = format!("mp_extensive_{x}_{}", Op::NAME); let skip = skip_extensive_test(&ctx); let runner = move || { @@ -78,7 +109,7 @@ where panic!("extensive tests should be run with --release"); } - let res = run_single_test::(&ctx); + let res = run_single_test::(&ctx, cases, total); let e = match res { Ok(()) => return Ok(()), Err(e) => e, @@ -96,7 +127,11 @@ where } /// Test runner for a signle routine. -fn run_single_test(ctx: &CheckCtx) -> TestResult +fn run_single_test( + ctx: &CheckCtx, + mut cases: impl Iterator + Send, + total: u64, +) -> TestResult where Op: MathOp + MpOp, Op::RustArgs: SpacedInput + Send, @@ -106,7 +141,8 @@ where eprintln!(); let completed = AtomicU64::new(0); - let (ref mut cases, total) = spaced::get_test_cases::(ctx); + // let ref mut cases = cases; + // let (ref mut cases, total) = spaced::get_test_cases::(ctx); let pb = Progress::new(Op::NAME, total); let test_single_chunk = |mp_vals: &mut Op::MpTy, input_vec: Vec| -> TestResult { @@ -129,7 +165,7 @@ where let chunk_size = 50_000; let chunks = std::iter::from_fn(move || { let mut v = Vec::with_capacity(chunk_size); - v.extend(cases.take(chunk_size)); + v.extend((&mut cases).take(chunk_size)); (!v.is_empty()).then_some(v) });