Skip to content

Commit a6fe05b

Browse files
authored
Merge pull request rust-lang#378 from tgross35/run-cfg
Use `CheckCtx` in more places
2 parents 5c5df51 + c0d9cc3 commit a6fe05b

File tree

7 files changed

+72
-52
lines changed

7 files changed

+72
-52
lines changed

crates/libm-test/examples/plot_domains.rs

+8-6
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use std::{env, fs};
1414

1515
use libm_test::domain::HasDomain;
1616
use libm_test::gen::{domain_logspace, edge_cases};
17-
use libm_test::{MathOp, op};
17+
use libm_test::{CheckBasis, CheckCtx, MathOp, op};
1818

1919
const JL_PLOT: &str = "examples/plot_file.jl";
2020

@@ -54,30 +54,32 @@ fn plot_one_operator<Op>(out_dir: &Path, config: &mut String)
5454
where
5555
Op: MathOp<FTy = f32> + HasDomain<f32>,
5656
{
57+
let ctx = CheckCtx::new(Op::IDENTIFIER, CheckBasis::Mpfr);
5758
plot_one_generator(
5859
out_dir,
59-
Op::BASE_NAME.as_str(),
60+
&ctx,
6061
"logspace",
6162
config,
62-
domain_logspace::get_test_cases::<Op>(),
63+
domain_logspace::get_test_cases::<Op>(&ctx),
6364
);
6465
plot_one_generator(
6566
out_dir,
66-
Op::BASE_NAME.as_str(),
67+
&ctx,
6768
"edge_cases",
6869
config,
69-
edge_cases::get_test_cases::<Op, _>(),
70+
edge_cases::get_test_cases::<Op, _>(&ctx),
7071
);
7172
}
7273

7374
/// Plot the output of a single generator.
7475
fn plot_one_generator(
7576
out_dir: &Path,
76-
fn_name: &str,
77+
ctx: &CheckCtx,
7778
gen_name: &str,
7879
config: &mut String,
7980
gen: impl Iterator<Item = (f32,)>,
8081
) {
82+
let fn_name = ctx.base_name_str;
8183
let text_file = out_dir.join(format!("input-{fn_name}-{gen_name}.txt"));
8284

8385
let f = fs::File::create(&text_file).unwrap();

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

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use libm::support::{IntTy, MinInt};
44

55
use crate::domain::HasDomain;
66
use crate::op::OpITy;
7-
use crate::{MathOp, logspace};
7+
use crate::{CheckCtx, MathOp, logspace};
88

99
/// Number of tests to run.
1010
// FIXME(ntests): replace this with a more logical algorithm
@@ -30,7 +30,7 @@ const NTESTS: usize = {
3030
///
3131
/// This allows us to get reasonably thorough coverage without wasting time on values that are
3232
/// NaN or out of range. Random tests will still cover values that are excluded here.
33-
pub fn get_test_cases<Op>() -> impl Iterator<Item = (Op::FTy,)>
33+
pub fn get_test_cases<Op>(_ctx: &CheckCtx) -> impl Iterator<Item = (Op::FTy,)>
3434
where
3535
Op: MathOp + HasDomain<Op::FTy>,
3636
IntTy<Op::FTy>: TryFrom<usize>,

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

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
use libm::support::Float;
44

55
use crate::domain::HasDomain;
6-
use crate::{FloatExt, MathOp};
6+
use crate::{CheckCtx, FloatExt, MathOp};
77

88
/// Number of values near an interesting point to check.
99
// FIXME(ntests): replace this with a more logical algorithm
@@ -14,7 +14,7 @@ const AROUND: usize = 100;
1414
const MAX_CHECK_POINTS: usize = 10;
1515

1616
/// Create a list of values around interesting points (infinities, zeroes, NaNs).
17-
pub fn get_test_cases<Op, F>() -> impl Iterator<Item = (F,)>
17+
pub fn get_test_cases<Op, F>(_ctx: &CheckCtx) -> impl Iterator<Item = (F,)>
1818
where
1919
Op: MathOp<FTy = F> + HasDomain<F>,
2020
F: Float,

crates/libm-test/src/lib.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,16 @@ pub mod mpfloat;
88
mod num;
99
pub mod op;
1010
mod precision;
11+
mod run_cfg;
1112
mod test_traits;
1213

1314
pub use f8_impl::f8;
1415
pub use libm::support::{Float, Int, IntTy, MinInt};
1516
pub use num::{FloatExt, logspace};
1617
pub use op::{BaseName, FloatTy, Identifier, MathOp, OpCFn, OpFTy, OpRustFn, OpRustRet, Ty};
1718
pub use precision::{MaybeOverride, SpecialCase, default_ulp};
18-
pub use test_traits::{CheckBasis, CheckCtx, CheckOutput, GenerateInput, Hex, TupleCall};
19+
pub use run_cfg::{CheckBasis, CheckCtx};
20+
pub use test_traits::{CheckOutput, GenerateInput, Hex, TupleCall};
1921

2022
/// Result type for tests is usually from `anyhow`. Most times there is no success value to
2123
/// propagate.

crates/libm-test/src/run_cfg.rs

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
//! Configuration for how tests get run.
2+
3+
#![allow(unused)]
4+
5+
use std::collections::BTreeMap;
6+
use std::env;
7+
use std::sync::LazyLock;
8+
9+
use crate::{BaseName, FloatTy, Identifier, op};
10+
11+
pub const EXTENSIVE_ENV: &str = "LIBM_EXTENSIVE_TESTS";
12+
13+
/// Context passed to [`CheckOutput`].
14+
#[derive(Clone, Debug, PartialEq, Eq)]
15+
pub struct CheckCtx {
16+
/// Allowed ULP deviation
17+
pub ulp: u32,
18+
pub fn_ident: Identifier,
19+
pub base_name: BaseName,
20+
/// Function name.
21+
pub fn_name: &'static str,
22+
/// Return the unsuffixed version of the function name.
23+
pub base_name_str: &'static str,
24+
/// Source of truth for tests.
25+
pub basis: CheckBasis,
26+
}
27+
28+
impl CheckCtx {
29+
/// Create a new check context, using the default ULP for the function.
30+
pub fn new(fn_ident: Identifier, basis: CheckBasis) -> Self {
31+
let mut ret = Self {
32+
ulp: 0,
33+
fn_ident,
34+
fn_name: fn_ident.as_str(),
35+
base_name: fn_ident.base_name(),
36+
base_name_str: fn_ident.base_name().as_str(),
37+
basis,
38+
};
39+
ret.ulp = crate::default_ulp(&ret);
40+
ret
41+
}
42+
}
43+
44+
/// Possible items to test against
45+
#[derive(Clone, Debug, PartialEq, Eq)]
46+
pub enum CheckBasis {
47+
/// Check against Musl's math sources.
48+
Musl,
49+
/// Check against infinite precision (MPFR).
50+
Mpfr,
51+
}

crates/libm-test/src/test_traits.rs

+1-38
Original file line numberDiff line numberDiff line change
@@ -11,44 +11,7 @@ use std::fmt;
1111

1212
use anyhow::{Context, bail, ensure};
1313

14-
use crate::{BaseName, Float, Identifier, Int, MaybeOverride, SpecialCase, TestResult};
15-
16-
/// Context passed to [`CheckOutput`].
17-
#[derive(Clone, Debug, PartialEq, Eq)]
18-
pub struct CheckCtx {
19-
/// Allowed ULP deviation
20-
pub ulp: u32,
21-
pub fn_ident: Identifier,
22-
pub base_name: BaseName,
23-
/// Function name.
24-
pub fn_name: &'static str,
25-
/// Source of truth for tests.
26-
pub basis: CheckBasis,
27-
}
28-
29-
impl CheckCtx {
30-
/// Create a new check context, using the default ULP for the function.
31-
pub fn new(fn_ident: Identifier, basis: CheckBasis) -> Self {
32-
let mut ret = Self {
33-
ulp: 0,
34-
fn_ident,
35-
fn_name: fn_ident.as_str(),
36-
base_name: fn_ident.base_name(),
37-
basis,
38-
};
39-
ret.ulp = crate::default_ulp(&ret);
40-
ret
41-
}
42-
}
43-
44-
/// Possible items to test against
45-
#[derive(Clone, Debug, PartialEq, Eq)]
46-
pub enum CheckBasis {
47-
/// Check against Musl's math sources.
48-
Musl,
49-
/// Check against infinite precision (MPFR).
50-
Mpfr,
51-
}
14+
use crate::{CheckCtx, Float, Int, MaybeOverride, SpecialCase, TestResult};
5215

5316
/// Implement this on types that can generate a sequence of tuples for test input.
5417
pub trait GenerateInput<TupleArgs> {

crates/libm-test/tests/multiprecision.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -83,21 +83,21 @@ macro_rules! mp_domain_tests {
8383
$(#[$meta])*
8484
fn [< mp_edge_case_ $fn_name >]() {
8585
type Op = libm_test::op::$fn_name::Routine;
86-
domain_test_runner::<Op>(edge_cases::get_test_cases::<Op, _>());
86+
domain_test_runner::<Op, _>(edge_cases::get_test_cases::<Op, _>);
8787
}
8888

8989
#[test]
9090
$(#[$meta])*
9191
fn [< mp_logspace_ $fn_name >]() {
9292
type Op = libm_test::op::$fn_name::Routine;
93-
domain_test_runner::<Op>(domain_logspace::get_test_cases::<Op>());
93+
domain_test_runner::<Op, _>(domain_logspace::get_test_cases::<Op>);
9494
}
9595
}
9696
};
9797
}
9898

9999
/// Test a single routine against domaine-aware inputs.
100-
fn domain_test_runner<Op>(cases: impl Iterator<Item = (Op::FTy,)>)
100+
fn domain_test_runner<Op, I>(gen: impl FnOnce(&CheckCtx) -> I)
101101
where
102102
// Complicated generics...
103103
// The operation must take a single float argument (unary only)
@@ -108,9 +108,11 @@ where
108108
Op: HasDomain<Op::FTy>,
109109
// The single float argument tuple must be able to call the `RustFn` and return `RustRet`
110110
(OpFTy<Op>,): TupleCall<OpRustFn<Op>, Output = OpRustRet<Op>>,
111+
I: Iterator<Item = (Op::FTy,)>,
111112
{
112113
let mut mp_vals = Op::new_mp();
113114
let ctx = CheckCtx::new(Op::IDENTIFIER, CheckBasis::Mpfr);
115+
let cases = gen(&ctx);
114116

115117
for input in cases {
116118
let mp_res = Op::run(&mut mp_vals, input);

0 commit comments

Comments
 (0)