extern crate self as aprox_eq;
pub use aprox_derive::AproxEq;
pub trait AproxEq<T = Self>
where
T: ?Sized,
{
#[must_use]
fn aprox_eq(&self, other: &T) -> bool;
#[inline]
#[must_use]
fn aprox_ne(&self, other: &T) -> bool {
!self.aprox_eq(other)
}
}
#[macro_export]
macro_rules! assert_aprox_eq {
($left:expr, $right:expr) => {
assert!(
aprox_eq::AproxEq::aprox_eq(&$left, &$right),
"assertion failed: `left.aprox_eq(right)`\n left: `{:#?}`,\n right: `{:#?}`",
$left,
$right,
);
};
}
#[macro_export]
macro_rules! assert_aprox_ne {
($left:expr, $right:expr) => {
assert!(
aprox_eq::AproxEq::aprox_ne(&$left, &$right),
"assertion failed: `left.aprox_ne(right)`\n left: `{:#?}`,\n right: `{:#?}`",
$left,
$right,
);
};
}
impl AproxEq for f64 {
fn aprox_eq(&self, other: &Self) -> bool {
(self - other).abs() < 1e-16
}
}
impl AproxEq for f32 {
fn aprox_eq(&self, other: &Self) -> bool {
(self - other).abs() < 1e-8
}
}
#[cfg(test)]
mod tests {
use crate::AproxEq;
#[derive(AproxEq, Debug)]
struct SomeFoats {
pub a: f64,
pub b: f32,
}
#[derive(AproxEq, Debug)]
struct SomeAproxEq {
pub a: SomeFoats,
pub b: SomeFoats,
}
#[test]
fn basic_aprox_eq() {
assert_aprox_eq!(1.0002_f64, 1.0001999999999999_f64);
assert_aprox_ne!(1.002_f32, 1.001_f32);
}
#[test]
fn ownership_retainance() {
let a = 1_f64;
let b = 1_f64;
assert_aprox_eq!(a, b);
let c = a + b;
assert_aprox_ne!(a, c);
}
#[test]
fn derive_test() {
assert_aprox_eq!(
SomeFoats { a: 3f64, b: 2f32 },
SomeFoats { a: 3f64, b: 2f32 }
);
assert_aprox_eq!(
SomeAproxEq {
a: SomeFoats { a: 3f64, b: 2f32 },
b: SomeFoats { a: 5f64, b: 4f32 }
},
SomeAproxEq {
a: SomeFoats { a: 3f64, b: 2f32 },
b: SomeFoats { a: 5f64, b: 4f32 }
}
);
}
}