//! Compare our implementations with the result of musl functions, as provided by `musl-math-sys`. //! //! Currently this only tests randomized inputs. In the future this may be improved to test edge //! cases or run exhaustive tests. //! //! Note that musl functions do not always provide 0.5ULP rounding, so our functions can do better //! than these results. // There are some targets we can't build musl for #![cfg(feature = "build-musl")] use libm_test::generate::{case_list, edge_cases, random, spaced}; use libm_test::{CheckBasis, CheckCtx, CheckOutput, GeneratorKind, MathOp, TupleCall}; const BASIS: CheckBasis = CheckBasis::Musl; fn musl_runner( ctx: &CheckCtx, cases: impl Iterator, musl_fn: Op::CFn, ) { for input in cases { let musl_res = input.call(musl_fn); let crate_res = input.call_intercept_panics(Op::ROUTINE); crate_res.validate(musl_res, input, ctx).unwrap(); } } /// Test against musl with generators from a domain. macro_rules! musl_tests { ( fn_name: $fn_name:ident, attrs: [$($attr:meta),*], ) => { paste::paste! { #[test] $(#[$attr])* fn [< musl_case_list_ $fn_name >]() { type Op = libm_test::op::$fn_name::Routine; let ctx = CheckCtx::new(Op::IDENTIFIER, BASIS, GeneratorKind::List); let cases = case_list::get_test_cases_basis::(&ctx).0; musl_runner::(&ctx, cases, musl_math_sys::$fn_name); } #[test] $(#[$attr])* 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; musl_runner::(&ctx, cases, musl_math_sys::$fn_name); } #[test] $(#[$attr])* 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; musl_runner::(&ctx, cases, musl_math_sys::$fn_name); } #[test] $(#[$attr])* fn [< musl_quickspace_ $fn_name >]() { type Op = libm_test::op::$fn_name::Routine; let ctx = CheckCtx::new(Op::IDENTIFIER, BASIS, GeneratorKind::Spaced); let cases = spaced::get_test_cases::(&ctx).0; musl_runner::(&ctx, cases, musl_math_sys::$fn_name); } } }; } libm_macros::for_each_function! { callback: musl_tests, attributes: [], // Not provided by musl skip_f16_f128: true, skip: [ // TODO integer inputs jn, jnf, ldexp, ldexpf, scalbn, scalbnf, yn, ynf, // Not provided by musl // verify-sorted-start fmaximum, fmaximum_num, fmaximum_numf, fmaximumf, fminimum, fminimum_num, fminimum_numf, fminimumf, roundeven, roundevenf, // // verify-sorted-end ], }