Merge pull request rust-lang/libm#359 from tgross35/update-check-ctx
Change the `CheckCtx` constructor to take a `Name` enum
This commit is contained in:
commit
0f76ef074f
8 changed files with 32 additions and 45 deletions
|
|
@ -628,9 +628,9 @@ impl VisitMut for MacroReplace {
|
|||
}
|
||||
}
|
||||
|
||||
/// Return the unsuffixed name of a function.
|
||||
/// Return the unsuffixed version of a function name; e.g. `abs` and `absf` both return `abs`,
|
||||
/// `lgamma_r` and `lgammaf_r` both return `lgamma_r`.
|
||||
fn base_name(name: &str) -> &str {
|
||||
// Keep this in sync with `libm_test::base_name`
|
||||
let known_mappings = &[
|
||||
("erff", "erf"),
|
||||
("erf", "erf"),
|
||||
|
|
|
|||
|
|
@ -47,10 +47,10 @@ where
|
|||
Op: MathOp,
|
||||
CachedInput: GenerateInput<Op::RustArgs>,
|
||||
{
|
||||
let name = Op::NAME_STR;
|
||||
let name = Op::NAME;
|
||||
|
||||
let ulp = libm_test::musl_allowed_ulp(name);
|
||||
let ctx = CheckCtx::new(ulp, name, CheckBasis::Musl);
|
||||
let ctx = CheckCtx::new(ulp, Op::IDENTIFIER, CheckBasis::Musl);
|
||||
let benchvec: Vec<_> =
|
||||
random::get_test_cases::<Op::RustArgs>(&ctx).take(BENCH_ITER_ITEMS).collect();
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ mod precision;
|
|||
mod test_traits;
|
||||
|
||||
pub use libm::support::{Float, Int};
|
||||
pub use op::{BaseName, MathOp, Name};
|
||||
pub use op::{BaseName, Identifier, MathOp};
|
||||
pub use precision::{MaybeOverride, SpecialCase, multiprec_allowed_ulp, musl_allowed_ulp};
|
||||
pub use test_traits::{CheckBasis, CheckCtx, CheckOutput, GenerateInput, Hex, TupleCall};
|
||||
|
||||
|
|
@ -17,27 +17,6 @@ pub type TestResult<T = (), E = anyhow::Error> = Result<T, E>;
|
|||
// List of all files present in libm's source
|
||||
include!(concat!(env!("OUT_DIR"), "/all_files.rs"));
|
||||
|
||||
/// Return the unsuffixed version of a function name; e.g. `abs` and `absf` both return `abs`,
|
||||
/// `lgamma_r` and `lgammaf_r` both return `lgamma_r`.
|
||||
pub fn base_name(name: &str) -> &str {
|
||||
let known_mappings = &[
|
||||
("erff", "erf"),
|
||||
("erf", "erf"),
|
||||
("lgammaf_r", "lgamma_r"),
|
||||
("modff", "modf"),
|
||||
("modf", "modf"),
|
||||
];
|
||||
|
||||
match known_mappings.iter().find(|known| known.0 == name) {
|
||||
Some(found) => found.1,
|
||||
None => name
|
||||
.strip_suffix("f")
|
||||
.or_else(|| name.strip_suffix("f16"))
|
||||
.or_else(|| name.strip_suffix("f128"))
|
||||
.unwrap_or(name),
|
||||
}
|
||||
}
|
||||
|
||||
/// True if `EMULATED` is set and nonempty. Used to determine how many iterations to run.
|
||||
pub const fn emulated() -> bool {
|
||||
match option_env!("EMULATED") {
|
||||
|
|
|
|||
|
|
@ -15,10 +15,10 @@
|
|||
|
||||
use crate::{CheckOutput, Float, TupleCall};
|
||||
|
||||
/// An enum representing each possible routine name.
|
||||
/// An enum representing each possible symbol name (`sin`, `sinf`, `sinl`, etc).
|
||||
#[libm_macros::function_enum(BaseName)]
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||
pub enum Name {}
|
||||
pub enum Identifier {}
|
||||
|
||||
/// The name without any type specifier, e.g. `sin` and `sinf` both become `sin`.
|
||||
#[libm_macros::base_name_enum]
|
||||
|
|
@ -58,13 +58,13 @@ pub trait MathOp {
|
|||
type RustRet: CheckOutput<Self::RustArgs>;
|
||||
|
||||
/// The name of this function, including suffix (e.g. `sin`, `sinf`).
|
||||
const NAME: Name;
|
||||
const IDENTIFIER: Identifier;
|
||||
|
||||
/// The name as a string.
|
||||
const NAME_STR: &'static str = Self::NAME.as_str();
|
||||
const NAME: &'static str = Self::IDENTIFIER.as_str();
|
||||
|
||||
/// The name of the function excluding the type suffix, e.g. `sin` and `sinf` are both `sin`.
|
||||
const BASE_NAME: BaseName = Self::NAME.base_name();
|
||||
const BASE_NAME: BaseName = Self::IDENTIFIER.base_name();
|
||||
|
||||
/// The function in `libm` which can be called.
|
||||
const ROUTINE: Self::RustFn;
|
||||
|
|
@ -96,7 +96,7 @@ macro_rules! do_thing {
|
|||
type RustArgs = $RustArgs;
|
||||
type RustRet = $RustRet;
|
||||
|
||||
const NAME: Name = Name::[< $fn_name:camel >];
|
||||
const IDENTIFIER: Identifier = Identifier::[< $fn_name:camel >];
|
||||
const ROUTINE: Self::RustFn = libm::$fn_name;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -219,7 +219,7 @@ impl MaybeOverride<(f64,)> for SpecialCase {
|
|||
|
||||
/// Check NaN bits if the function requires it
|
||||
fn maybe_check_nan_bits<F: Float>(actual: F, expected: F, ctx: &CheckCtx) -> Option<TestResult> {
|
||||
if !(ctx.base_name == "fabs" || ctx.base_name == "copysign") {
|
||||
if !(ctx.base_name_str == "fabs" || ctx.base_name_str == "copysign") {
|
||||
return None;
|
||||
}
|
||||
|
||||
|
|
@ -277,7 +277,7 @@ fn maybe_skip_binop_nan<F1: Float, F2: Float>(
|
|||
) -> Option<TestResult> {
|
||||
match ctx.basis {
|
||||
CheckBasis::Musl => {
|
||||
if (ctx.base_name == "fmax" || ctx.base_name == "fmin")
|
||||
if (ctx.base_name_str == "fmax" || ctx.base_name_str == "fmin")
|
||||
&& (input.0.is_nan() || input.1.is_nan())
|
||||
&& expected.is_nan()
|
||||
{
|
||||
|
|
@ -287,7 +287,7 @@ fn maybe_skip_binop_nan<F1: Float, F2: Float>(
|
|||
}
|
||||
}
|
||||
CheckBasis::Mpfr => {
|
||||
if ctx.base_name == "copysign" && input.1.is_nan() {
|
||||
if ctx.base_name_str == "copysign" && input.1.is_nan() {
|
||||
SKIP
|
||||
} else {
|
||||
None
|
||||
|
|
@ -353,7 +353,7 @@ fn bessel_prec_dropoff<F: Float>(
|
|||
ulp: &mut u32,
|
||||
ctx: &CheckCtx,
|
||||
) -> Option<TestResult> {
|
||||
if ctx.base_name == "jn" {
|
||||
if ctx.base_name_str == "jn" {
|
||||
if input.0 > 4000 {
|
||||
return XFAIL;
|
||||
} else if input.0 > 2000 {
|
||||
|
|
|
|||
|
|
@ -11,25 +11,33 @@ use std::fmt;
|
|||
|
||||
use anyhow::{Context, bail, ensure};
|
||||
|
||||
use crate::{Float, Int, MaybeOverride, SpecialCase, TestResult};
|
||||
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: &'static str,
|
||||
pub base_name_str: &'static str,
|
||||
/// Source of truth for tests.
|
||||
pub basis: CheckBasis,
|
||||
}
|
||||
|
||||
impl CheckCtx {
|
||||
pub fn new(ulp: u32, fname: &'static str, basis: CheckBasis) -> Self {
|
||||
let base_name = crate::base_name(fname);
|
||||
Self { ulp, fn_name: fname, base_name, basis }
|
||||
pub fn new(ulp: u32, fn_ident: Identifier, basis: CheckBasis) -> Self {
|
||||
Self {
|
||||
ulp,
|
||||
fn_ident,
|
||||
fn_name: fn_ident.as_str(),
|
||||
base_name: fn_ident.base_name(),
|
||||
base_name_str: fn_ident.base_name().as_str(),
|
||||
basis,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -34,9 +34,9 @@ where
|
|||
Op: MathOp,
|
||||
CachedInput: GenerateInput<Op::RustArgs>,
|
||||
{
|
||||
let name = Op::NAME_STR;
|
||||
let name = Op::NAME;
|
||||
let ulp = musl_allowed_ulp(name);
|
||||
let ctx = CheckCtx::new(ulp, name, CheckBasis::Musl);
|
||||
let ctx = CheckCtx::new(ulp, Op::IDENTIFIER, CheckBasis::Musl);
|
||||
let cases = random::get_test_cases::<Op::RustArgs>(&ctx);
|
||||
|
||||
for input in cases {
|
||||
|
|
|
|||
|
|
@ -29,11 +29,11 @@ where
|
|||
Op: MathOp + MpOp,
|
||||
CachedInput: GenerateInput<Op::RustArgs>,
|
||||
{
|
||||
let name = Op::NAME_STR;
|
||||
let name = Op::NAME;
|
||||
|
||||
let ulp = multiprec_allowed_ulp(name);
|
||||
let mut mp_vals = Op::new_mp();
|
||||
let ctx = CheckCtx::new(ulp, name, CheckBasis::Mpfr);
|
||||
let ctx = CheckCtx::new(ulp, Op::IDENTIFIER, CheckBasis::Mpfr);
|
||||
let cases = random::get_test_cases::<Op::RustArgs>(&ctx);
|
||||
|
||||
for input in cases {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue