2024-10-16 22:59:17 -05:00
|
|
|
//! 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")]
|
|
|
|
|
|
2025-02-06 04:03:11 +00:00
|
|
|
use libm_test::gen::{case_list, edge_cases, random, spaced};
|
2025-01-07 06:28:04 +00:00
|
|
|
use libm_test::{CheckBasis, CheckCtx, CheckOutput, GeneratorKind, MathOp, TupleCall};
|
2024-10-16 22:59:17 -05:00
|
|
|
|
2025-01-07 06:28:04 +00:00
|
|
|
const BASIS: CheckBasis = CheckBasis::Musl;
|
2024-10-31 02:46:21 -05:00
|
|
|
|
2025-01-07 06:28:04 +00:00
|
|
|
fn musl_runner<Op: MathOp>(
|
|
|
|
|
ctx: &CheckCtx,
|
|
|
|
|
cases: impl Iterator<Item = Op::RustArgs>,
|
|
|
|
|
musl_fn: Op::CFn,
|
|
|
|
|
) {
|
2024-10-31 02:46:21 -05:00
|
|
|
for input in cases {
|
|
|
|
|
let musl_res = input.call(musl_fn);
|
|
|
|
|
let crate_res = input.call(Op::ROUTINE);
|
|
|
|
|
|
2025-01-07 06:28:04 +00:00
|
|
|
crate_res.validate(musl_res, input, ctx).unwrap();
|
2024-10-31 02:46:21 -05:00
|
|
|
}
|
2024-10-16 22:59:17 -05:00
|
|
|
}
|
|
|
|
|
|
2024-12-28 09:52:19 +00:00
|
|
|
/// Test against musl with generators from a domain.
|
2025-01-07 06:28:04 +00:00
|
|
|
macro_rules! musl_tests {
|
2024-12-28 09:52:19 +00:00
|
|
|
(
|
|
|
|
|
fn_name: $fn_name:ident,
|
|
|
|
|
attrs: [$($attr:meta),*],
|
|
|
|
|
) => {
|
|
|
|
|
paste::paste! {
|
2025-01-07 06:28:04 +00:00
|
|
|
#[test]
|
|
|
|
|
$(#[$attr])*
|
2025-02-06 04:03:11 +00:00
|
|
|
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::<Op>(&ctx).0;
|
|
|
|
|
musl_runner::<Op>(&ctx, cases, musl_math_sys::$fn_name);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
$(#[$attr])*
|
2025-01-07 06:28:04 +00:00
|
|
|
fn [< musl_random_ $fn_name >]() {
|
|
|
|
|
type Op = libm_test::op::$fn_name::Routine;
|
|
|
|
|
let ctx = CheckCtx::new(Op::IDENTIFIER, BASIS, GeneratorKind::Random);
|
2025-02-05 21:18:33 +00:00
|
|
|
let cases = random::get_test_cases::<<Op as MathOp>::RustArgs>(&ctx).0;
|
2025-01-07 06:28:04 +00:00
|
|
|
musl_runner::<Op>(&ctx, cases, musl_math_sys::$fn_name);
|
|
|
|
|
}
|
|
|
|
|
|
2024-12-28 09:52:19 +00:00
|
|
|
#[test]
|
|
|
|
|
$(#[$attr])*
|
|
|
|
|
fn [< musl_edge_case_ $fn_name >]() {
|
|
|
|
|
type Op = libm_test::op::$fn_name::Routine;
|
2025-01-07 06:28:04 +00:00
|
|
|
let ctx = CheckCtx::new(Op::IDENTIFIER, BASIS, GeneratorKind::EdgeCases);
|
2025-02-05 21:18:33 +00:00
|
|
|
let cases = edge_cases::get_test_cases::<Op>(&ctx).0;
|
2025-01-07 06:28:04 +00:00
|
|
|
musl_runner::<Op>(&ctx, cases, musl_math_sys::$fn_name);
|
2024-12-28 09:52:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
$(#[$attr])*
|
2025-01-07 06:28:04 +00:00
|
|
|
fn [< musl_quickspace_ $fn_name >]() {
|
2024-12-28 09:52:19 +00:00
|
|
|
type Op = libm_test::op::$fn_name::Routine;
|
2025-01-07 06:28:04 +00:00
|
|
|
let ctx = CheckCtx::new(Op::IDENTIFIER, BASIS, GeneratorKind::QuickSpaced);
|
|
|
|
|
let cases = spaced::get_test_cases::<Op>(&ctx).0;
|
|
|
|
|
musl_runner::<Op>(&ctx, cases, musl_math_sys::$fn_name);
|
2024-12-28 09:52:19 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
libm_macros::for_each_function! {
|
2025-01-07 06:28:04 +00:00
|
|
|
callback: musl_tests,
|
2024-12-28 09:52:19 +00:00
|
|
|
attributes: [],
|
|
|
|
|
skip: [
|
2025-01-07 06:28:04 +00:00
|
|
|
// TODO integer inputs
|
2024-12-28 09:52:19 +00:00
|
|
|
jn,
|
|
|
|
|
jnf,
|
|
|
|
|
ldexp,
|
|
|
|
|
ldexpf,
|
|
|
|
|
scalbn,
|
|
|
|
|
scalbnf,
|
|
|
|
|
yn,
|
|
|
|
|
ynf,
|
|
|
|
|
|
|
|
|
|
// Not provided by musl
|
2025-02-05 15:03:34 +00:00
|
|
|
// verify-sorted-start
|
2025-01-13 11:17:17 +00:00
|
|
|
ceilf128,
|
|
|
|
|
ceilf16,
|
2025-01-07 06:28:04 +00:00
|
|
|
copysignf128,
|
|
|
|
|
copysignf16,
|
2024-12-28 09:52:19 +00:00
|
|
|
fabsf128,
|
2025-01-13 13:58:40 +00:00
|
|
|
fabsf16,
|
|
|
|
|
fdimf128,
|
|
|
|
|
fdimf16,
|
2025-01-13 13:33:24 +00:00
|
|
|
floorf128,
|
|
|
|
|
floorf16,
|
2025-02-05 23:45:14 +00:00
|
|
|
fmaf128,
|
2025-01-24 02:57:35 +00:00
|
|
|
fmaxf128,
|
|
|
|
|
fmaxf16,
|
2025-02-10 19:43:49 +00:00
|
|
|
fmaximum,
|
|
|
|
|
fmaximum_num,
|
|
|
|
|
fmaximum_numf,
|
|
|
|
|
fmaximum_numf128,
|
|
|
|
|
fmaximum_numf16,
|
|
|
|
|
fmaximumf,
|
|
|
|
|
fmaximumf128,
|
|
|
|
|
fmaximumf16,
|
2025-01-24 02:57:35 +00:00
|
|
|
fminf128,
|
|
|
|
|
fminf16,
|
2025-02-10 19:43:49 +00:00
|
|
|
fminimum,
|
|
|
|
|
fminimum_num,
|
|
|
|
|
fminimum_numf,
|
|
|
|
|
fminimum_numf128,
|
|
|
|
|
fminimum_numf16,
|
|
|
|
|
fminimumf,
|
|
|
|
|
fminimumf128,
|
|
|
|
|
fminimumf16,
|
2025-01-24 05:58:08 +00:00
|
|
|
fmodf128,
|
2025-01-24 05:09:08 +00:00
|
|
|
fmodf16,
|
2025-01-03 04:34:21 +00:00
|
|
|
ldexpf128,
|
|
|
|
|
ldexpf16,
|
2025-01-22 10:58:29 +00:00
|
|
|
rintf128,
|
|
|
|
|
rintf16,
|
Add `roundeven{,f,f16,f128}`
C23 specifies a new set of `roundeven` functions that round to the
nearest integral, with ties to even. It does not raise any floating
point exceptions.
This behavior is similar to two other functions:
1. `rint`, which rounds to the nearest integer respecting rounding mode
and possibly raising exceptions.
2. `nearbyint`, which is identical to `rint` except it may not raise
exceptions.
Technically `rint`, `nearbyint`, and `roundeven` all behave the same in
Rust because we assume default floating point environment. The backends
are allowed to lower to `roundeven`, however, so we should provide it in
case the fallback is needed.
Add the `roundeven` family here and convert `rint` to a function that
takes a rounding mode. This currently has no effect.
2025-02-11 00:17:32 +00:00
|
|
|
roundeven,
|
|
|
|
|
roundevenf,
|
|
|
|
|
roundevenf128,
|
|
|
|
|
roundevenf16,
|
2025-01-24 01:57:12 +00:00
|
|
|
roundf128,
|
|
|
|
|
roundf16,
|
2025-01-03 04:34:21 +00:00
|
|
|
scalbnf128,
|
|
|
|
|
scalbnf16,
|
2025-01-22 10:58:29 +00:00
|
|
|
sqrtf128,
|
|
|
|
|
sqrtf16,
|
2025-01-12 04:12:56 +00:00
|
|
|
truncf128,
|
2025-01-13 13:58:40 +00:00
|
|
|
truncf16,
|
2025-02-05 15:03:34 +00:00
|
|
|
// verify-sorted-end
|
2024-12-28 09:52:19 +00:00
|
|
|
],
|
|
|
|
|
}
|