#![doc = include_str!("../README.md")]
#![no_std]
mod sealed {
pub trait Sealed {}
impl Sealed for f32 {}
impl Sealed for f64 {}
}
pub trait ApproxEq: sealed::Sealed {
fn approx_eq(self, other: Self) -> bool;
}
impl ApproxEq for f32 {
fn approx_eq(self, other: Self) -> bool {
let diff = (self - other).abs();
let a = self.abs();
let b = other.abs();
let largest = f32::max(a, b);
diff <= largest * f32::EPSILON
}
}
impl ApproxEq for f64 {
fn approx_eq(self, other: Self) -> bool {
let diff = (self - other).abs();
let a = self.abs();
let b = other.abs();
let largest = f64::max(a, b);
diff <= largest * f64::EPSILON
}
}
#[macro_export]
macro_rules! assert_approx_eq {
($a:expr, $b:expr) => {{
let a = $a;
let b = $b;
assert!(
$crate::ApproxEq::approx_eq(a, b),
"assertion `{a}.approx_eq({b})` failed"
)
}};
}
#[macro_export]
macro_rules! assert_approx_eq_slice {
($a:expr, $b:expr) => {{
let a = $a;
let b = $b;
let a: &[_] = ::core::convert::AsRef::as_ref(&a);
let b: &[_] = ::core::convert::AsRef::as_ref(&b);
assert_eq!(
a.len(),
b.len(),
"assertion `{a:?}.len() == {b:?}.len()` failed"
);
for (&a, &b) in a.iter().zip(b) {
$crate::assert_approx_eq!(a, b);
}
}};
}