[][src]Trait float_eq::FloatEqAll

pub trait FloatEqAll<Rhs: ?Sized = Self> {
    type Epsilon;
    type UlpsEpsilon;
    fn eq_abs_all(&self, other: &Rhs, max_diff: &Self::Epsilon) -> bool;
fn eq_rel_all(&self, other: &Rhs, max_diff: &Self::Epsilon) -> bool;
fn eq_ulps_all(&self, other: &Rhs, max_diff: &Self::UlpsEpsilon) -> bool; fn ne_abs_all(&self, other: &Rhs, max_diff: &Self::Epsilon) -> bool { ... }
fn ne_rel_all(&self, other: &Rhs, max_diff: &Self::Epsilon) -> bool { ... }
fn ne_ulps_all(&self, other: &Rhs, max_diff: &Self::UlpsEpsilon) -> bool { ... } }

Compare IEEE floating point values for equality using a uniform threshold.

This trait is used in the implementation of the float_eq! and assert_float_eq! families of macros to provide abs_all, rel_all and ulps_all checks. It may be called directly, but the macros usually provide a friendlier interface. Comparison via this trait may not fit every composite type. For example, it likely ought not to be implemented for (f32, f64), which has a big difference in precision between its fields.

How can I implement FloatEqAll?

You will need some way to represent difference in ULPs for your type, which is likely to be either u32 or u64. Implementation is then usually a matter of calling through to an underlying FloatEqAll method for each field in turn. If not, you will need to take a close look at the descriptions of the algorithms on a method by method basis:

#[derive(Copy, Clone)]
struct MyComplex32 {
    re: f32,
    im: f32,
}

impl FloatEqAll for MyComplex32 {
    type Epsilon = f32;
    type UlpsEpsilon = u32;

    fn eq_abs_all(&self, other: &Self, max_diff: &f32) -> bool {
        self.re.eq_abs_all(&other.re, max_diff) && self.im.eq_abs_all(&other.im, max_diff)
    }

    fn eq_rel_all(&self, other: &Self, max_diff: &f32) -> bool {
        self.re.eq_rel_all(&other.re, max_diff) && self.im.eq_rel_all(&other.im, max_diff)
    }

    fn eq_ulps_all(&self, other: &Self, max_diff: &u32) -> bool {
        self.re.eq_ulps_all(&other.re, max_diff) && self.im.eq_ulps_all(&other.im, max_diff)
    }
}

let a = MyComplex32 { re: 1.0, im: 2.000_003_6, };
let b = MyComplex32 { re: 1.000_000_1, im: 2.0, };

assert!(a.eq_abs_all(&b, &0.000_003_6));
assert!(a.ne_abs_all(&b, &0.000_003_5));

assert!(a.eq_rel_all(&b, &0.000_001_8));
assert!(a.ne_rel_all(&b, &0.000_001_7));

assert!(a.eq_ulps_all(&b, &15));
assert!(a.ne_ulps_all(&b, &14));

How can I compare two different types?

The type to be compared with is controlled by FloatEqAll's parameter. Following on from our previous example, if we wanted to treat f32 as a complex number with an imaginary component of 0.0:

impl FloatEqAll<f32> for MyComplex32 {
    type Epsilon = f32;
    type UlpsEpsilon = u32;

    fn eq_abs_all(&self, other: &f32, max_diff: &f32) -> bool {
        self.re.eq_abs_all(other, max_diff) && self.im.eq_abs_all(&0.0, max_diff)
    }

    fn eq_rel_all(&self, other: &f32, max_diff: &f32) -> bool {
        self.re.eq_rel_all(other, max_diff) && self.im.eq_rel_all(&0.0, max_diff)
    }

    fn eq_ulps_all(&self, other: &f32, max_diff: &u32) -> bool {
        self.re.eq_ulps_all(other, max_diff) && self.im.eq_ulps_all(&0.0, max_diff)
    }
}

let a = MyComplex32 { re: 4.000_000_5, im: 0.0 };
let b = 4.0_f32;

assert!(a.eq_abs_all(&b, &0.000_000_8));
assert!(a.ne_abs_all(&b, &0.000_000_4));

assert!(a.eq_rel_all(&b, &0.000_000_12));
assert!(a.ne_rel_all(&b, &0.000_000_11));

assert!(a.eq_ulps_all(&b, &1));
assert!(a.ne_ulps_all(&b, &0));

Examples

let a = [1.000_000_2f32, -2.0];
let b = [1.0f32, -2.000_002];

assert!(a.eq_abs_all(&b, &0.000_002));
assert!(a.ne_abs_all(&b, &0.000_001));

assert!(a.eq_rel_all(&b, &0.000_001));
assert!(a.ne_rel_all(&b, &0.000_000_5));

assert!(a.eq_ulps_all(&b, &8));
assert!(a.ne_ulps_all(&b, &7));

Associated Types

type Epsilon

Type of the maximum allowed difference between two values for them to be considered equal in terms of their native type.

This is the type of the max_diff parameter passed to abs_all and rel_all checks in methods and via the float_eq! macros. This should be a single floating point value so is often f32 or f64.

type UlpsEpsilon

Type of the maximum allowed difference between two values for them to be considered equal in terms of an ULPs comparison.

This is the type of the max_diff parameter passed to ulps_all checks in methods and via the float_eq! macros. This should be a single value so is often u32 or u64.

Loading content...

Required methods

fn eq_abs_all(&self, other: &Rhs, max_diff: &Self::Epsilon) -> bool

Check whether self is equal to other, using an absolute epsilon comparison.

This must use the same algorithm as FloatEq::eq_abs.

fn eq_rel_all(&self, other: &Rhs, max_diff: &Self::Epsilon) -> bool

Check whether self is equal to other, using a relative epsilon comparison.

This must use the same algorithm as FloatEq::eq_rel.

fn eq_ulps_all(&self, other: &Rhs, max_diff: &Self::UlpsEpsilon) -> bool

Check whether self is equal to other, using an ULPs comparison.

This must use the same algorithm as FloatEq::eq_ulps.

Loading content...

Provided methods

fn ne_abs_all(&self, other: &Rhs, max_diff: &Self::Epsilon) -> bool

Check whether self is not equal to other, using an absolute epsilon comparison.

Equal to !self.eq_abs_all(other, max_diff), there is no need to reimplement this for your own types.

fn ne_rel_all(&self, other: &Rhs, max_diff: &Self::Epsilon) -> bool

Check whether self is not equal to other, using a relative epsilon comparison.

Equal to !self.eq_rel_all(other, max_diff), there is no need to reimplement this for your own types.

fn ne_ulps_all(&self, other: &Rhs, max_diff: &Self::UlpsEpsilon) -> bool

Check whether self is not equal to other, using an ULPs comparison.

Equal to !self.eq_ulps_all(other, max_diff), there is no need to reimplement this for your own types.

Loading content...

Implementations on Foreign Types

impl<T: FloatEqAll> FloatEqAll<[T; 0]> for [T; 0][src]

type Epsilon = T::Epsilon

type UlpsEpsilon = T::UlpsEpsilon

impl<T: FloatEqAll> FloatEqAll<[T; 1]> for [T; 1][src]

type Epsilon = T::Epsilon

type UlpsEpsilon = T::UlpsEpsilon

impl<T: FloatEqAll> FloatEqAll<[T; 2]> for [T; 2][src]

type Epsilon = T::Epsilon

type UlpsEpsilon = T::UlpsEpsilon

impl<T: FloatEqAll> FloatEqAll<[T; 3]> for [T; 3][src]

type Epsilon = T::Epsilon

type UlpsEpsilon = T::UlpsEpsilon

impl<T: FloatEqAll> FloatEqAll<[T; 4]> for [T; 4][src]

type Epsilon = T::Epsilon

type UlpsEpsilon = T::UlpsEpsilon

impl<T: FloatEqAll> FloatEqAll<[T; 5]> for [T; 5][src]

type Epsilon = T::Epsilon

type UlpsEpsilon = T::UlpsEpsilon

impl<T: FloatEqAll> FloatEqAll<[T; 6]> for [T; 6][src]

type Epsilon = T::Epsilon

type UlpsEpsilon = T::UlpsEpsilon

impl<T: FloatEqAll> FloatEqAll<[T; 7]> for [T; 7][src]

type Epsilon = T::Epsilon

type UlpsEpsilon = T::UlpsEpsilon

impl<T: FloatEqAll> FloatEqAll<[T; 8]> for [T; 8][src]

type Epsilon = T::Epsilon

type UlpsEpsilon = T::UlpsEpsilon

impl<T: FloatEqAll> FloatEqAll<[T; 9]> for [T; 9][src]

type Epsilon = T::Epsilon

type UlpsEpsilon = T::UlpsEpsilon

impl<T: FloatEqAll> FloatEqAll<[T; 10]> for [T; 10][src]

type Epsilon = T::Epsilon

type UlpsEpsilon = T::UlpsEpsilon

impl<T: FloatEqAll> FloatEqAll<[T; 11]> for [T; 11][src]

type Epsilon = T::Epsilon

type UlpsEpsilon = T::UlpsEpsilon

impl<T: FloatEqAll> FloatEqAll<[T; 12]> for [T; 12][src]

type Epsilon = T::Epsilon

type UlpsEpsilon = T::UlpsEpsilon

impl<T: FloatEqAll> FloatEqAll<[T; 13]> for [T; 13][src]

type Epsilon = T::Epsilon

type UlpsEpsilon = T::UlpsEpsilon

impl<T: FloatEqAll> FloatEqAll<[T; 14]> for [T; 14][src]

type Epsilon = T::Epsilon

type UlpsEpsilon = T::UlpsEpsilon

impl<T: FloatEqAll> FloatEqAll<[T; 15]> for [T; 15][src]

type Epsilon = T::Epsilon

type UlpsEpsilon = T::UlpsEpsilon

impl<T: FloatEqAll> FloatEqAll<[T; 16]> for [T; 16][src]

type Epsilon = T::Epsilon

type UlpsEpsilon = T::UlpsEpsilon

impl<T: FloatEqAll> FloatEqAll<[T; 17]> for [T; 17][src]

type Epsilon = T::Epsilon

type UlpsEpsilon = T::UlpsEpsilon

impl<T: FloatEqAll> FloatEqAll<[T; 18]> for [T; 18][src]

type Epsilon = T::Epsilon

type UlpsEpsilon = T::UlpsEpsilon

impl<T: FloatEqAll> FloatEqAll<[T; 19]> for [T; 19][src]

type Epsilon = T::Epsilon

type UlpsEpsilon = T::UlpsEpsilon

impl<T: FloatEqAll> FloatEqAll<[T; 20]> for [T; 20][src]

type Epsilon = T::Epsilon

type UlpsEpsilon = T::UlpsEpsilon

impl<T: FloatEqAll> FloatEqAll<[T; 21]> for [T; 21][src]

type Epsilon = T::Epsilon

type UlpsEpsilon = T::UlpsEpsilon

impl<T: FloatEqAll> FloatEqAll<[T; 22]> for [T; 22][src]

type Epsilon = T::Epsilon

type UlpsEpsilon = T::UlpsEpsilon

impl<T: FloatEqAll> FloatEqAll<[T; 23]> for [T; 23][src]

type Epsilon = T::Epsilon

type UlpsEpsilon = T::UlpsEpsilon

impl<T: FloatEqAll> FloatEqAll<[T; 24]> for [T; 24][src]

type Epsilon = T::Epsilon

type UlpsEpsilon = T::UlpsEpsilon

impl<T: FloatEqAll> FloatEqAll<[T; 25]> for [T; 25][src]

type Epsilon = T::Epsilon

type UlpsEpsilon = T::UlpsEpsilon

impl<T: FloatEqAll> FloatEqAll<[T; 26]> for [T; 26][src]

type Epsilon = T::Epsilon

type UlpsEpsilon = T::UlpsEpsilon

impl<T: FloatEqAll> FloatEqAll<[T; 27]> for [T; 27][src]

type Epsilon = T::Epsilon

type UlpsEpsilon = T::UlpsEpsilon

impl<T: FloatEqAll> FloatEqAll<[T; 28]> for [T; 28][src]

type Epsilon = T::Epsilon

type UlpsEpsilon = T::UlpsEpsilon

impl<T: FloatEqAll> FloatEqAll<[T; 29]> for [T; 29][src]

type Epsilon = T::Epsilon

type UlpsEpsilon = T::UlpsEpsilon

impl<T: FloatEqAll> FloatEqAll<[T; 30]> for [T; 30][src]

type Epsilon = T::Epsilon

type UlpsEpsilon = T::UlpsEpsilon

impl<T: FloatEqAll> FloatEqAll<[T; 31]> for [T; 31][src]

type Epsilon = T::Epsilon

type UlpsEpsilon = T::UlpsEpsilon

impl<T: FloatEqAll> FloatEqAll<[T; 32]> for [T; 32][src]

type Epsilon = T::Epsilon

type UlpsEpsilon = T::UlpsEpsilon

impl FloatEqAll<f32> for f32[src]

type Epsilon = <f32 as FloatEq>::Epsilon

type UlpsEpsilon = <f32 as FloatEq>::UlpsEpsilon

impl FloatEqAll<f64> for f64[src]

type Epsilon = <f64 as FloatEq>::Epsilon

type UlpsEpsilon = <f64 as FloatEq>::UlpsEpsilon

impl<T: FloatEqAll> FloatEqAll<Complex<T>> for Complex<T>[src]

type Epsilon = T::Epsilon

type UlpsEpsilon = T::UlpsEpsilon

Loading content...

Implementors

Loading content...