Skip to content

Commit

Permalink
define FloatMargin trait to solve type inferrence issue #31
Browse files Browse the repository at this point in the history
  • Loading branch information
mikedilger committed Jun 29, 2023
1 parent 418c5d9 commit a2fdd37
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 12 deletions.
43 changes: 34 additions & 9 deletions src/eq.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,31 @@ use core::{f32, f64};
use num_traits::float::FloatCore;
use super::Ulps;

/// A margin specifing a maximum distance two floating point values can be while
/// still being considered equal enough.
pub trait FloatMargin: Copy + Default {
/// A floating-point type used for epsilon values
type F;

/// An integer type used for ulps values
type I;

/// Zero margin
fn zero() -> Self;

/// Set the epsilon value for this margin
fn epsilon(self, epsilon: Self::F) -> Self;

/// Set the ulps value for this margin
fn ulps(self, ulps: Self::I) -> Self;
}

/// A trait for approximate equality comparisons.
pub trait ApproxEq: Sized {
/// This type type defines a margin within which two values are to be
/// considered approximately equal. It must implement `Default` so that
/// `approx_eq()` can be called on unknown types.
type Margin: Copy + Default;
type Margin: FloatMargin;

/// This method tests that the `self` and `other` values are equal within `margin`
/// of each other.
Expand Down Expand Up @@ -56,21 +75,24 @@ impl Default for F32Margin {
}
}
}
impl F32Margin {
impl FloatMargin for F32Margin {
type F = f32;
type I = i32;

#[inline]
pub fn zero() -> F32Margin {
fn zero() -> F32Margin {
F32Margin {
epsilon: 0.0,
ulps: 0
}
}
pub fn epsilon(self, epsilon: f32) -> Self {
fn epsilon(self, epsilon: f32) -> Self {
F32Margin {
epsilon,
..self
}
}
pub fn ulps(self, ulps: i32) -> Self {
fn ulps(self, ulps: i32) -> Self {
F32Margin {
ulps,
..self
Expand Down Expand Up @@ -182,21 +204,24 @@ impl Default for F64Margin {
}
}
}
impl F64Margin {
impl FloatMargin for F64Margin {
type F = f64;
type I = i64;

#[inline]
pub fn zero() -> F64Margin {
fn zero() -> F64Margin {
F64Margin {
epsilon: 0.0,
ulps: 0
}
}
pub fn epsilon(self, epsilon: f64) -> Self {
fn epsilon(self, epsilon: f64) -> Self {
F64Margin {
epsilon,
..self
}
}
pub fn ulps(self, ulps: i64) -> Self {
fn ulps(self, ulps: i64) -> Self {
F64Margin {
ulps,
..self
Expand Down
6 changes: 3 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,14 +142,14 @@
//! it for references to your type as shown.
//!
//! ```
//! use float_cmp::ApproxEq;
//! use float_cmp::{ApproxEq, FloatMargin};
//!
//! pub struct Vec2<F> {
//! pub x: F,
//! pub y: F,
//! }
//!
//! impl<'a, M: Copy + Default, F: Copy + ApproxEq<Margin=M>> ApproxEq for &'a Vec2<F> {
//! impl<'a, M: FloatMargin, F: Copy + ApproxEq<Margin=M>> ApproxEq for &'a Vec2<F> {
//! type Margin = M;
//!
//! fn approx_eq<T: Into<Self::Margin>>(self, other: Self, margin: T) -> bool {
Expand Down Expand Up @@ -187,7 +187,7 @@ mod ulps_eq;
pub use self::ulps_eq::ApproxEqUlps;

mod eq;
pub use self::eq::{ApproxEq, F32Margin, F64Margin};
pub use self::eq::{ApproxEq, F32Margin, F64Margin, FloatMargin};

#[cfg(feature="ratio")]
mod ratio;
Expand Down
1 change: 1 addition & 0 deletions src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ macro_rules! approx_eq {
};
($typ:ty, $lhs:expr, $rhs:expr $(, $set:ident = $val:expr)*) => {
{
use $crate::FloatMargin;
let m = <$typ as $crate::ApproxEq>::Margin::zero()$(.$set($val))*;
<$typ as $crate::ApproxEq>::approx_eq($lhs, $rhs, m)
}
Expand Down

0 comments on commit a2fdd37

Please sign in to comment.