mod macros;
pub trait ApproxEq: Sized {
type Epsilon;
fn default_epsilon() -> Self::Epsilon;
fn default_max_relative() -> Self::Epsilon;
fn default_max_ulps() -> u32;
fn relative_eq(&self, other: &Self, epsilon: Self::Epsilon, max_relative: Self::Epsilon) -> bool;
fn relative_ne(&self, other: &Self, epsilon: Self::Epsilon, max_relative: Self::Epsilon) -> bool {
!Self::relative_eq(self, other, epsilon, max_relative)
}
fn ulps_eq(&self, other: &Self, epsilon: Self::Epsilon, max_ulps: u32) -> bool;
fn ulps_ne(&self, other: &Self, epsilon: Self::Epsilon, max_ulps: u32) -> bool {
!Self::ulps_eq(self, other, epsilon, max_ulps)
}
}
macro_rules! impl_float_relative_eq {
($T:ident, $U:ident) => {
impl ApproxEq for $T {
type Epsilon = $T;
#[inline]
fn default_epsilon() -> $T { std::$T::EPSILON }
#[inline]
fn default_max_relative() -> $T { std::$T::EPSILON }
#[inline]
fn default_max_ulps() -> u32 { 4 }
fn relative_eq(&self, other: &$T, epsilon: $T, max_relative: $T) -> bool {
if self == other { return true; }
let abs_diff = $T::abs(self - other);
if abs_diff <= epsilon { return true };
let abs_self = $T::abs(*self);
let abs_other = $T::abs(*other);
let largest = if abs_other > abs_self { abs_other } else { abs_self };
abs_diff <= largest * max_relative
}
fn ulps_eq(&self, other: &$T, epsilon: $T, max_ulps: u32) -> bool {
if $T::abs(self - other) <= epsilon { return true }
if self.signum() != other.signum() {
return self == other;
}
let int_self: $U = unsafe { std::mem::transmute(*self) };
let int_other: $U = unsafe { std::mem::transmute(*other) };
$U::abs(int_self - int_other) < max_ulps as $U
}
}
}
}
impl_float_relative_eq!(f32, i32);
impl_float_relative_eq!(f64, i64);
impl<'a, T: ApproxEq> ApproxEq for &'a T {
type Epsilon = T::Epsilon;
#[inline]
fn default_epsilon() -> Self::Epsilon {
T::default_epsilon()
}
#[inline]
fn default_max_relative() -> Self::Epsilon {
T::default_max_relative()
}
#[inline]
fn default_max_ulps() -> u32 {
T::default_max_ulps()
}
#[inline]
fn relative_eq(&self, other: &&'a T, epsilon: T::Epsilon, max_relative: T::Epsilon) -> bool {
T::relative_eq(*self, *other, epsilon, max_relative)
}
#[inline]
fn ulps_eq(&self, other: &&'a T, epsilon: T::Epsilon, max_ulps: u32) -> bool {
T::ulps_eq(*self, *other, epsilon, max_ulps)
}
}
impl<'a, T: ApproxEq> ApproxEq for &'a mut T {
type Epsilon = T::Epsilon;
#[inline]
fn default_epsilon() -> Self::Epsilon {
T::default_epsilon()
}
#[inline]
fn default_max_relative() -> Self::Epsilon {
T::default_max_relative()
}
#[inline]
fn default_max_ulps() -> u32 {
T::default_max_ulps()
}
#[inline]
fn relative_eq(&self, other: &&'a mut T, epsilon: T::Epsilon, max_relative: T::Epsilon) -> bool {
T::relative_eq(*self, *other, epsilon, max_relative)
}
#[inline]
fn ulps_eq(&self, other: &&'a mut T, epsilon: T::Epsilon, max_ulps: u32) -> bool {
T::ulps_eq(*self, *other, epsilon, max_ulps)
}
}
pub struct Relative<'a, T: 'a + ApproxEq> {
pub lhs: &'a T,
pub rhs: &'a T,
pub epsilon: T::Epsilon,
pub max_relative: T::Epsilon,
}
impl<'a, T> Relative<'a, T> where T: ApproxEq {
#[inline]
pub fn new(lhs: &'a T, rhs: &'a T) -> Relative<'a, T> {
Relative {
lhs: lhs,
rhs: rhs,
epsilon: T::default_epsilon(),
max_relative: T::default_max_relative(),
}
}
#[inline]
pub fn epsilon(self, epsilon: T::Epsilon) -> Relative<'a, T> {
Relative { epsilon: epsilon, ..self }
}
#[inline]
pub fn max_relative(self, max_relative: T::Epsilon) -> Relative<'a, T> {
Relative { max_relative: max_relative, ..self }
}
#[inline]
pub fn eq(self) -> bool {
let Relative { lhs, rhs, epsilon, max_relative } = self;
T::relative_eq(lhs, rhs, epsilon, max_relative)
}
#[inline]
pub fn ne(self) -> bool {
let Relative { lhs, rhs, epsilon, max_relative } = self;
T::relative_ne(lhs, rhs, epsilon, max_relative)
}
}
pub struct Ulps<'a, T: 'a + ApproxEq> {
pub lhs: &'a T,
pub rhs: &'a T,
pub epsilon: T::Epsilon,
pub max_ulps: u32,
}
impl<'a, T> Ulps<'a, T> where T: ApproxEq {
#[inline]
pub fn new(lhs: &'a T, rhs: &'a T) -> Ulps<'a, T> {
Ulps {
lhs: lhs,
rhs: rhs,
epsilon: T::default_epsilon(),
max_ulps: T::default_max_ulps(),
}
}
#[inline]
pub fn epsilon(self, epsilon: T::Epsilon) -> Ulps<'a, T> {
Ulps { epsilon: epsilon, ..self }
}
#[inline]
pub fn max_ulps(self, max_ulps:u32) -> Ulps<'a, T> {
Ulps { max_ulps: max_ulps, ..self }
}
#[inline]
pub fn eq(self) -> bool {
let Ulps { lhs, rhs, epsilon, max_ulps } = self;
T::ulps_eq(lhs, rhs, epsilon, max_ulps)
}
#[inline]
pub fn ne(self) -> bool {
let Ulps { lhs, rhs, epsilon, max_ulps } = self;
T::ulps_ne(lhs, rhs, epsilon, max_ulps)
}
}