From 1827d567c05f64aa96d93bd62741e5aabfd88f76 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Sun, 22 Dec 2024 12:38:58 +0000 Subject: [PATCH] switch from Identifier to CheckCtx --- crates/libm-test/examples/plot_domains.rs | 14 ++++--- crates/libm-test/src/gen/domain_logspace.rs | 8 ++-- crates/libm-test/src/gen/edge_cases.rs | 4 +- crates/libm-test/src/gen/extensive.rs | 10 ++--- crates/libm-test/src/lib.rs | 5 ++- crates/libm-test/src/test_traits.rs | 42 +-------------------- crates/libm-test/tests/multiprecision.rs | 8 ++-- crates/libm-test/tests/z_extensive/run.rs | 9 +++-- 8 files changed, 34 insertions(+), 66 deletions(-) diff --git a/crates/libm-test/examples/plot_domains.rs b/crates/libm-test/examples/plot_domains.rs index b8362ce4..ae07251b 100644 --- a/crates/libm-test/examples/plot_domains.rs +++ b/crates/libm-test/examples/plot_domains.rs @@ -14,7 +14,7 @@ use std::{env, fs}; use libm_test::domain::HasDomain; use libm_test::gen::{domain_logspace, edge_cases}; -use libm_test::{MathOp, op}; +use libm_test::{CheckBasis, CheckCtx, MathOp, op}; const JL_PLOT: &str = "examples/plot_file.jl"; @@ -54,29 +54,31 @@ fn plot_one_operator(out_dir: &Path, config: &mut String) where Op: MathOp + HasDomain, { + let ctx = CheckCtx::new(Op::IDENTIFIER, CheckBasis::Mpfr); plot_one_generator( out_dir, - Op::BASE_NAME.as_str(), + &ctx, "logspace", config, - domain_logspace::get_test_cases::(), + domain_logspace::get_test_cases::(&ctx), ); plot_one_generator( out_dir, - Op::BASE_NAME.as_str(), + &ctx, "edge_cases", config, - edge_cases::get_test_cases::(), + edge_cases::get_test_cases::(&ctx), ); } /// Plot the output of a single generator. fn plot_one_generator( out_dir: &Path, - fn_name: &str, + ctx: &CheckCtx, gen_name: &str, config: &mut String, gen: impl Iterator, ) { + let fn_name = ctx.base_name_str; let text_file = out_dir.join(format!("input-{fn_name}-{gen_name}.txt")); let f = fs::File::create(&text_file).unwrap(); diff --git a/crates/libm-test/src/gen/domain_logspace.rs b/crates/libm-test/src/gen/domain_logspace.rs index 3e302ad2..1cf51513 100644 --- a/crates/libm-test/src/gen/domain_logspace.rs +++ b/crates/libm-test/src/gen/domain_logspace.rs @@ -4,20 +4,20 @@ use libm::support::{IntTy, MinInt}; use crate::domain::HasDomain; use crate::op::OpITy; -use crate::run_cfg::{TestAction, TestTy}; -use crate::{MathOp, logspace}; +use crate::run_cfg::{GeneratorKind, TestAction}; +use crate::{CheckCtx, MathOp, logspace}; /// Create a range of logarithmically spaced inputs within a function's domain. /// /// This allows us to get reasonably thorough coverage without wasting time on values that are /// NaN or out of range. Random tests will still cover values that are excluded here. -pub fn get_test_cases() -> impl Iterator +pub fn get_test_cases(ctx: &CheckCtx) -> impl Iterator where Op: MathOp + HasDomain, IntTy: TryFrom, { let domain = Op::DOMAIN; - let action = crate::run_cfg::get_iterations(Op::IDENTIFIER, TestTy::Logspace, 0); + let action = crate::run_cfg::get_iterations(ctx, GeneratorKind::Logspace, 0); let ntests = match action { TestAction::Iterations(n) => n, TestAction::Run => unimplemented!(), diff --git a/crates/libm-test/src/gen/edge_cases.rs b/crates/libm-test/src/gen/edge_cases.rs index feda8128..303cb5d0 100644 --- a/crates/libm-test/src/gen/edge_cases.rs +++ b/crates/libm-test/src/gen/edge_cases.rs @@ -3,7 +3,7 @@ use libm::support::Float; use crate::domain::HasDomain; -use crate::{FloatExt, MathOp}; +use crate::{CheckCtx, FloatExt, MathOp}; /// Number of values near an interesting point to check. // FIXME(ntests): replace this with a more logical algorithm @@ -14,7 +14,7 @@ const AROUND: usize = 100; const MAX_CHECK_POINTS: usize = 10; /// Create a list of values around interesting points (infinities, zeroes, NaNs). -pub fn get_test_cases() -> impl Iterator +pub fn get_test_cases(_ctx: &CheckCtx) -> impl Iterator where Op: MathOp + HasDomain, F: Float, diff --git a/crates/libm-test/src/gen/extensive.rs b/crates/libm-test/src/gen/extensive.rs index 1f7a788c..8dc57496 100644 --- a/crates/libm-test/src/gen/extensive.rs +++ b/crates/libm-test/src/gen/extensive.rs @@ -31,8 +31,8 @@ where Op: HasDomain, { fn gen() -> impl Iterator { - let mut start = Op::D.range_start(); - let end = Op::D.range_end(); + let mut start = Op::DOMAIN.range_start(); + let end = Op::DOMAIN.range_end(); iter::from_fn(move || { if start > end || start >= Op::FTy::INFINITY { return None; @@ -44,7 +44,7 @@ where } fn count() -> u64 { - u64::from(ulp_between(Op::D.range_start(), Op::D.range_end()).unwrap()) + 1 + u64::from(ulp_between(Op::DOMAIN.range_start(), Op::DOMAIN.range_end()).unwrap()) + 1 } } @@ -54,8 +54,8 @@ where Op: HasDomain, { fn gen() -> impl Iterator { - let start = Op::D.range_start(); - let end = Op::D.range_end(); + let start = Op::DOMAIN.range_start(); + let end = Op::DOMAIN.range_end(); let steps = ::Int::try_from(MAX_ITERATIONS) .unwrap_or(::Int::MAX); logspace(start, end, steps).map(|v| (v,)) diff --git a/crates/libm-test/src/lib.rs b/crates/libm-test/src/lib.rs index b4a86d35..c631f5a3 100644 --- a/crates/libm-test/src/lib.rs +++ b/crates/libm-test/src/lib.rs @@ -8,7 +8,7 @@ pub mod mpfloat; mod num; pub mod op; mod precision; -pub mod run_cfg; +mod run_cfg; mod test_traits; pub use f8_impl::f8; @@ -16,7 +16,8 @@ pub use libm::support::{Float, Int, IntTy, MinInt}; pub use num::{FloatExt, logspace}; pub use op::{BaseName, FloatTy, Identifier, MathOp, OpCFn, OpFTy, OpRustFn, OpRustRet, Ty}; pub use precision::{MaybeOverride, SpecialCase, default_ulp}; -pub use test_traits::{CheckBasis, CheckCtx, CheckOutput, GenerateInput, Hex, TupleCall}; +pub use run_cfg::{CheckBasis, CheckCtx, EXTENSIVE_ENV, GeneratorKind, TestAction, get_iterations}; +pub use test_traits::{CheckOutput, GenerateInput, Hex, TupleCall}; /// Result type for tests is usually from `anyhow`. Most times there is no success value to /// propagate. diff --git a/crates/libm-test/src/test_traits.rs b/crates/libm-test/src/test_traits.rs index b8e0aa10..6b833dfb 100644 --- a/crates/libm-test/src/test_traits.rs +++ b/crates/libm-test/src/test_traits.rs @@ -11,47 +11,7 @@ use std::fmt; use anyhow::{Context, bail, ensure}; -use crate::{BaseName, Float, Identifier, Int, MaybeOverride, SpecialCase, TestResult}; - -/// Context passed to [`CheckOutput`]. -#[derive(Clone, Debug, PartialEq, Eq)] -pub struct CheckCtx { - /// Allowed ULP deviation - pub ulp: u32, - pub fn_ident: Identifier, - pub base_name: BaseName, - /// Function name. - pub fn_name: &'static str, - /// Return the unsuffixed version of the function name. - pub base_name_str: &'static str, - /// Source of truth for tests. - pub basis: CheckBasis, -} - -impl CheckCtx { - /// Create a new check context, using the default ULP for the function. - pub fn new(fn_ident: Identifier, basis: CheckBasis) -> Self { - let mut ret = Self { - ulp: 0, - fn_ident, - fn_name: fn_ident.as_str(), - base_name: fn_ident.base_name(), - base_name_str: fn_ident.base_name().as_str(), - basis, - }; - ret.ulp = crate::default_ulp(&ret); - ret - } -} - -/// Possible items to test against -#[derive(Clone, Debug, PartialEq, Eq)] -pub enum CheckBasis { - /// Check against Musl's math sources. - Musl, - /// Check against infinite precision (MPFR). - Mpfr, -} +use crate::{CheckCtx, Float, Int, MaybeOverride, SpecialCase, TestResult}; /// Implement this on types that can generate a sequence of tuples for test input. pub trait GenerateInput { diff --git a/crates/libm-test/tests/multiprecision.rs b/crates/libm-test/tests/multiprecision.rs index 5255dc1c..2675ca01 100644 --- a/crates/libm-test/tests/multiprecision.rs +++ b/crates/libm-test/tests/multiprecision.rs @@ -83,21 +83,21 @@ macro_rules! mp_domain_tests { $(#[$meta])* fn [< mp_edge_case_ $fn_name >]() { type Op = libm_test::op::$fn_name::Routine; - domain_test_runner::(edge_cases::get_test_cases::()); + domain_test_runner::(edge_cases::get_test_cases::); } #[test] $(#[$meta])* fn [< mp_logspace_ $fn_name >]() { type Op = libm_test::op::$fn_name::Routine; - domain_test_runner::(domain_logspace::get_test_cases::()); + domain_test_runner::(domain_logspace::get_test_cases::); } } }; } /// Test a single routine against domaine-aware inputs. -fn domain_test_runner(cases: impl Iterator) +fn domain_test_runner(gen: impl FnOnce(&CheckCtx) -> I) where // Complicated generics... // The operation must take a single float argument (unary only) @@ -108,9 +108,11 @@ where Op: HasDomain, // The single float argument tuple must be able to call the `RustFn` and return `RustRet` (OpFTy,): TupleCall, Output = OpRustRet>, + I: Iterator, { let mut mp_vals = Op::new_mp(); let ctx = CheckCtx::new(Op::IDENTIFIER, CheckBasis::Mpfr); + let cases = gen(&ctx); for input in cases { let mp_res = Op::run(&mut mp_vals, input); diff --git a/crates/libm-test/tests/z_extensive/run.rs b/crates/libm-test/tests/z_extensive/run.rs index 5c1865f8..ba4fe923 100644 --- a/crates/libm-test/tests/z_extensive/run.rs +++ b/crates/libm-test/tests/z_extensive/run.rs @@ -6,8 +6,10 @@ use std::time::Duration; use indicatif::{ProgressBar, ProgressStyle}; use libm_test::gen::extensive::{self, ExtensiveInput}; use libm_test::mpfloat::MpOp; -use libm_test::run_cfg::{EXTENSIVE_ENV, TestAction, TestTy, get_iterations}; -use libm_test::{CheckBasis, CheckCtx, CheckOutput, MathOp, TestResult, TupleCall}; +use libm_test::{ + CheckBasis, CheckCtx, CheckOutput, EXTENSIVE_ENV, GeneratorKind, MathOp, TestAction, + TestResult, TupleCall, get_iterations, +}; use libtest_mimic::{Arguments, Completion, Trial}; use rayon::prelude::*; @@ -46,7 +48,8 @@ where { let test_name = format!("mp_extensive_{name}"); all.push(Trial::skippable_test(test_name, move || { - let action = get_iterations(Op::IDENTIFIER, TestTy::Extensive, 0); + let ctx = CheckCtx::new(Op::IDENTIFIER, CheckBasis::Mpfr); + let action = get_iterations(&ctx, GeneratorKind::Extensive, 0); match action { TestAction::Run => (), TestAction::Iterations(_) => panic!("extensive tests disregard iteration counts"),