diff --git a/src/abs_diff_eq.rs b/src/abs_diff_eq.rs index cf13ec3..67f59c7 100644 --- a/src/abs_diff_eq.rs +++ b/src/abs_diff_eq.rs @@ -5,7 +5,10 @@ use num_traits::float::FloatCore; use std::{cell, f32, f64}; /// Equality that is defined using the absolute difference of two numbers. -pub trait AbsDiffEq: PartialEq { +pub trait AbsDiffEq: PartialEq +where + Rhs: ?Sized, +{ /// Used for specifying relative comparisons. type Epsilon; @@ -17,10 +20,10 @@ pub trait AbsDiffEq: PartialEq { /// A test for equality that uses the absolute difference to compute the approximate /// equality of two numbers. - fn abs_diff_eq(&self, other: &Self, epsilon: Self::Epsilon) -> bool; + fn abs_diff_eq(&self, other: &Rhs, epsilon: Self::Epsilon) -> bool; /// The inverse of `ApproxEq::abs_diff_eq`. - fn abs_diff_ne(&self, other: &Self, epsilon: Self::Epsilon) -> bool { + fn abs_diff_ne(&self, other: &Rhs, epsilon: Self::Epsilon) -> bool { !Self::abs_diff_eq(self, other, epsilon) } } @@ -143,21 +146,22 @@ impl AbsDiffEq for cell::RefCell { } } -impl AbsDiffEq for [T] +impl AbsDiffEq<[B]> for [A] where - T::Epsilon: Clone, + A: AbsDiffEq, + A::Epsilon: Clone, { - type Epsilon = T::Epsilon; + type Epsilon = A::Epsilon; #[inline] - fn default_epsilon() -> T::Epsilon { - T::default_epsilon() + fn default_epsilon() -> A::Epsilon { + A::default_epsilon() } #[inline] - fn abs_diff_eq(&self, other: &[T], epsilon: T::Epsilon) -> bool { + fn abs_diff_eq(&self, other: &[B], epsilon: A::Epsilon) -> bool { self.len() == other.len() - && Iterator::zip(self.iter(), other).all(|(x, y)| T::abs_diff_eq(x, y, epsilon.clone())) + && Iterator::zip(self.iter(), other).all(|(x, y)| A::abs_diff_eq(x, y, epsilon.clone())) } } diff --git a/src/lib.rs b/src/lib.rs index 6e45373..a857f47 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -188,40 +188,49 @@ pub use ulps_eq::UlpsEq; /// AbsDiff::default().eq(&1.0, &1.0); /// AbsDiff::default().epsilon(f64::EPSILON).eq(&1.0, &1.0); /// ``` -pub struct AbsDiff { +pub struct AbsDiff +where + A: AbsDiffEq + ?Sized, + B: ?Sized, +{ /// The tolerance to use when testing values that are close together. - pub epsilon: T::Epsilon, + pub epsilon: A::Epsilon, } -impl Default for AbsDiff { +impl Default for AbsDiff +where + A: AbsDiffEq + ?Sized, + B: ?Sized, +{ #[inline] - fn default() -> AbsDiff { + fn default() -> AbsDiff { AbsDiff { - epsilon: T::default_epsilon(), + epsilon: A::default_epsilon(), } } } -impl AbsDiff +impl AbsDiff where - T: AbsDiffEq + ?Sized, + A: AbsDiffEq + ?Sized, + B: ?Sized, { /// Replace the epsilon value with the one specified. #[inline] - pub fn epsilon(self, epsilon: T::Epsilon) -> AbsDiff { + pub fn epsilon(self, epsilon: A::Epsilon) -> AbsDiff { AbsDiff { epsilon, ..self } } /// Peform the equality comparison #[inline] - pub fn eq(self, lhs: &T, rhs: &T) -> bool { - T::abs_diff_eq(lhs, rhs, self.epsilon) + pub fn eq(self, lhs: &A, rhs: &B) -> bool { + A::abs_diff_eq(lhs, rhs, self.epsilon) } /// Peform the inequality comparison #[inline] - pub fn ne(self, lhs: &T, rhs: &T) -> bool { - T::abs_diff_ne(lhs, rhs, self.epsilon) + pub fn ne(self, lhs: &A, rhs: &B) -> bool { + A::abs_diff_ne(lhs, rhs, self.epsilon) } } @@ -243,33 +252,45 @@ where /// Relative::default().epsilon(f64::EPSILON).max_relative(1.0).eq(&1.0, &1.0); /// Relative::default().max_relative(1.0).epsilon(f64::EPSILON).eq(&1.0, &1.0); /// ``` -pub struct Relative { +pub struct Relative +where + A: RelativeEq + ?Sized, + B: ?Sized, +{ /// The tolerance to use when testing values that are close together. - pub epsilon: T::Epsilon, + pub epsilon: A::Epsilon, /// The relative tolerance for testing values that are far-apart. - pub max_relative: T::Epsilon, + pub max_relative: A::Epsilon, } -impl Default for Relative { +impl Default for Relative +where + A: RelativeEq + ?Sized, + B: ?Sized, +{ #[inline] - fn default() -> Relative { + fn default() -> Relative { Relative { - epsilon: T::default_epsilon(), - max_relative: T::default_max_relative(), + epsilon: A::default_epsilon(), + max_relative: A::default_max_relative(), } } } -impl Relative { +impl Relative +where + A: RelativeEq + ?Sized, + B: ?Sized, +{ /// Replace the epsilon value with the one specified. #[inline] - pub fn epsilon(self, epsilon: T::Epsilon) -> Relative { + pub fn epsilon(self, epsilon: A::Epsilon) -> Relative { Relative { epsilon, ..self } } /// Replace the maximum relative value with the one specified. #[inline] - pub fn max_relative(self, max_relative: T::Epsilon) -> Relative { + pub fn max_relative(self, max_relative: A::Epsilon) -> Relative { Relative { max_relative, ..self @@ -278,14 +299,14 @@ impl Relative { /// Peform the equality comparison #[inline] - pub fn eq(self, lhs: &T, rhs: &T) -> bool { - T::relative_eq(lhs, rhs, self.epsilon, self.max_relative) + pub fn eq(self, lhs: &A, rhs: &B) -> bool { + A::relative_eq(lhs, rhs, self.epsilon, self.max_relative) } /// Peform the inequality comparison #[inline] - pub fn ne(self, lhs: &T, rhs: &T) -> bool { - T::relative_ne(lhs, rhs, self.epsilon, self.max_relative) + pub fn ne(self, lhs: &A, rhs: &B) -> bool { + A::relative_ne(lhs, rhs, self.epsilon, self.max_relative) } } @@ -307,48 +328,57 @@ impl Relative { /// Ulps::default().epsilon(f64::EPSILON).max_ulps(4).eq(&1.0, &1.0); /// Ulps::default().max_ulps(4).epsilon(f64::EPSILON).eq(&1.0, &1.0); /// ``` -pub struct Ulps { +pub struct Ulps +where + A: UlpsEq + ?Sized, + B: ?Sized, +{ /// The tolerance to use when testing values that are close together. - pub epsilon: T::Epsilon, + pub epsilon: A::Epsilon, /// The ULPs to tolerate when testing values that are far-apart. pub max_ulps: u32, } -impl Default for Ulps +impl Default for Ulps where - T: UlpsEq, + A: UlpsEq + ?Sized, + B: ?Sized, { #[inline] - fn default() -> Ulps { + fn default() -> Ulps { Ulps { - epsilon: T::default_epsilon(), - max_ulps: T::default_max_ulps(), + epsilon: A::default_epsilon(), + max_ulps: A::default_max_ulps(), } } } -impl Ulps { +impl Ulps +where + A: UlpsEq + ?Sized, + B: ?Sized, +{ /// Replace the epsilon value with the one specified. #[inline] - pub fn epsilon(self, epsilon: T::Epsilon) -> Ulps { + pub fn epsilon(self, epsilon: A::Epsilon) -> Ulps { Ulps { epsilon, ..self } } /// Replace the max ulps value with the one specified. #[inline] - pub fn max_ulps(self, max_ulps: u32) -> Ulps { + pub fn max_ulps(self, max_ulps: u32) -> Ulps { Ulps { max_ulps, ..self } } /// Peform the equality comparison #[inline] - pub fn eq(self, lhs: &T, rhs: &T) -> bool { - T::ulps_eq(lhs, rhs, self.epsilon, self.max_ulps) + pub fn eq(self, lhs: &A, rhs: &B) -> bool { + A::ulps_eq(lhs, rhs, self.epsilon, self.max_ulps) } /// Peform the inequality comparison #[inline] - pub fn ne(self, lhs: &T, rhs: &T) -> bool { - T::ulps_ne(lhs, rhs, self.epsilon, self.max_ulps) + pub fn ne(self, lhs: &A, rhs: &B) -> bool { + A::ulps_ne(lhs, rhs, self.epsilon, self.max_ulps) } } diff --git a/src/relative_eq.rs b/src/relative_eq.rs index 52c1333..5498825 100644 --- a/src/relative_eq.rs +++ b/src/relative_eq.rs @@ -8,7 +8,10 @@ use AbsDiffEq; /// Equality comparisons between two numbers using both the absolute difference and /// relative based comparisons. -pub trait RelativeEq: AbsDiffEq { +pub trait RelativeEq: AbsDiffEq +where + Rhs: ?Sized, +{ /// The default relative tolerance for testing values that are far-apart. /// /// This is used when no `max_relative` value is supplied to the `relative_eq` macro. @@ -17,7 +20,7 @@ pub trait RelativeEq: AbsDiffEq { /// A test for equality that uses a relative comparison if the values are far apart. fn relative_eq( &self, - other: &Self, + other: &Rhs, epsilon: Self::Epsilon, max_relative: Self::Epsilon, ) -> bool; @@ -25,7 +28,7 @@ pub trait RelativeEq: AbsDiffEq { /// The inverse of `ApproxEq::relative_eq`. fn relative_ne( &self, - other: &Self, + other: &Rhs, epsilon: Self::Epsilon, max_relative: Self::Epsilon, ) -> bool { @@ -152,20 +155,21 @@ impl RelativeEq for cell::RefCell { } } -impl RelativeEq for [T] +impl RelativeEq<[B]> for [A] where - T::Epsilon: Clone, + A: RelativeEq, + A::Epsilon: Clone, { #[inline] - fn default_max_relative() -> T::Epsilon { - T::default_max_relative() + fn default_max_relative() -> A::Epsilon { + A::default_max_relative() } #[inline] - fn relative_eq(&self, other: &[T], epsilon: T::Epsilon, max_relative: T::Epsilon) -> bool { + fn relative_eq(&self, other: &[B], epsilon: A::Epsilon, max_relative: A::Epsilon) -> bool { self.len() == other.len() && Iterator::zip(self.iter(), other) - .all(|(x, y)| T::relative_eq(x, y, epsilon.clone(), max_relative.clone())) + .all(|(x, y)| A::relative_eq(x, y, epsilon.clone(), max_relative.clone())) } } diff --git a/src/ulps_eq.rs b/src/ulps_eq.rs index 132abff..b177aaa 100644 --- a/src/ulps_eq.rs +++ b/src/ulps_eq.rs @@ -8,17 +8,20 @@ use AbsDiffEq; /// Equality comparisons between two numbers using both the absolute difference and ULPs /// (Units in Last Place) based comparisons. -pub trait UlpsEq: AbsDiffEq { +pub trait UlpsEq: AbsDiffEq +where + Rhs: ?Sized, +{ /// The default ULPs to tolerate when testing values that are far-apart. /// /// This is used when no `max_ulps` value is supplied to the `ulps_eq` macro. fn default_max_ulps() -> u32; /// A test for equality that uses units in the last place (ULP) if the values are far apart. - fn ulps_eq(&self, other: &Self, epsilon: Self::Epsilon, max_ulps: u32) -> bool; + fn ulps_eq(&self, other: &Rhs, epsilon: Self::Epsilon, max_ulps: u32) -> bool; /// The inverse of `ApproxEq::ulps_eq`. - fn ulps_ne(&self, other: &Self, epsilon: Self::Epsilon, max_ulps: u32) -> bool { + fn ulps_ne(&self, other: &Rhs, epsilon: Self::Epsilon, max_ulps: u32) -> bool { !Self::ulps_eq(self, other, epsilon, max_ulps) } } @@ -114,20 +117,21 @@ impl UlpsEq for cell::RefCell { } } -impl UlpsEq for [T] +impl UlpsEq<[B]> for [A] where - T::Epsilon: Clone, + A: UlpsEq, + A::Epsilon: Clone, { #[inline] fn default_max_ulps() -> u32 { - T::default_max_ulps() + A::default_max_ulps() } #[inline] - fn ulps_eq(&self, other: &[T], epsilon: T::Epsilon, max_ulps: u32) -> bool { + fn ulps_eq(&self, other: &[B], epsilon: A::Epsilon, max_ulps: u32) -> bool { self.len() == other.len() && Iterator::zip(self.iter(), other) - .all(|(x, y)| T::ulps_eq(x, y, epsilon.clone(), max_ulps.clone())) + .all(|(x, y)| A::ulps_eq(x, y, epsilon.clone(), max_ulps.clone())) } }