[][src]Trait float_eq::FloatDiff

pub trait FloatDiff<Rhs: ?Sized = Self> {
    type AbsDiff;
    type UlpsDiff;
    fn abs_diff(&self, other: &Rhs) -> Self::AbsDiff;
fn ulps_diff(&self, other: &Rhs) -> Option<Self::UlpsDiff>; }

Compute the difference between IEEE floating point values.

This trait is used by the family of assert_float_eq! macros to provide debug context information when they fail, but may also be called directly. Types are displayed to the user with fmt::Debug.

Note: the definition of this trait is very much tailored to float_eq's debug context requirements, and may not be ideal for general use.

How can I implement FloatDiff?

You will need some way to represent difference in ULPs for your type, following the same structure as the type itself. Implementation is then usually a matter of calling through to an underlying FloatDiff 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(Debug, Clone, Copy, PartialEq)]
struct MyComplex32 {
    re: f32,
    im: f32,
}

#[derive(Debug, Clone, Copy, PartialEq)]
struct MyComplex32Ulps {
    re: <f32 as FloatDiff>::UlpsDiff,
    im: <f32 as FloatDiff>::UlpsDiff,
}

impl FloatDiff for MyComplex32 {
    type AbsDiff = Self;
    type UlpsDiff = MyComplex32Ulps;

    fn abs_diff(&self, other: &Self) -> Self::AbsDiff {
        MyComplex32 {
            re: self.re.abs_diff(&other.re),
            im: self.im.abs_diff(&other.im),
        }
    }

    fn ulps_diff(&self, other: &Self) -> Option<Self::UlpsDiff> {
        Some(MyComplex32Ulps {
            re: self.re.ulps_diff(&other.re)?,
            im: self.im.ulps_diff(&other.im)?,
        })
    }
}

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

assert_eq!(
    a.abs_diff(&b),
    MyComplex32 {
        re: 0.000_000_119_209_29,
        im: 0.000_003_576_278_7,
    }
);

assert_eq!(a.ulps_diff(&b), Some(MyComplex32Ulps { re: 1, im: 15 }));

How can I compare two different types?

The type you can diff with is controlled by FloatDiff'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 FloatDiff<f32> for MyComplex32 {
    type AbsDiff = MyComplex32;
    type UlpsDiff = MyComplex32Ulps;

    fn abs_diff(&self, other: &f32) -> Self::AbsDiff {
        MyComplex32 {
            re: self.re.abs_diff(other),
            im: self.im.abs_diff(&0.0),
        }
    }

    fn ulps_diff(&self, other: &f32) -> Option<Self::UlpsDiff> {
        Some(MyComplex32Ulps {
            re: self.re.ulps_diff(other)?,
            im: self.im.ulps_diff(&0.0)?,
        })
    }
}

impl FloatDiff<MyComplex32> for f32 {
    type AbsDiff = <MyComplex32 as FloatDiff<f32>>::AbsDiff;
    type UlpsDiff = <MyComplex32 as FloatDiff<f32>>::UlpsDiff;

    fn abs_diff(&self, other: &MyComplex32) -> Self::AbsDiff {
        other.abs_diff(self)
    }

    fn ulps_diff(&self, other: &MyComplex32) -> Option<Self::UlpsDiff> {
        other.ulps_diff(self)
    }
}

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

assert_eq!(
    a.abs_diff(&b),
    MyComplex32 {
        re: 0.000_000_119_209_29,
        im: 2.000_003_6,
    }
);

assert_eq!(a.ulps_diff(&b), Some(MyComplex32Ulps { re: 1, im: 1_073_741_839 }));

Examples

assert_eq!(1.0f32.abs_diff(&-1.0), 2.0);
assert_eq!(1.0f64.abs_diff(&-1.0), 2.0);

assert_eq!(1.0f32.ulps_diff(&1.000_000_1), Some(1));
assert_eq!(1.0f64.ulps_diff(&1.000_000_000_000_000_2), Some(1));

assert_eq!(1.0f32.ulps_diff(&-1.0), None);
assert_eq!(1.0f64.ulps_diff(&-1.0), None);

let a = [0.0_f32, 2.0, -2.0];
let b = [0.0_f32, -1.0, 2.0];
assert_eq!(a.abs_diff(&b), [0.0, 3.0, 4.0]);
assert_eq!(a.ulps_diff(&b), None);

let c = [1.000_000_1f32, -2.0];
let d = [1.0f32, -2.000_000_5];
assert_eq!(c.ulps_diff(&d), Some([1, 2]));

Associated Types

type AbsDiff

Type of the absolute difference between two values.

This is often Self, unless comparing two different types. Composite types should probably use a type that follows the same structure as the inputs, to make error messages more legible.

type UlpsDiff

Type of the absolute difference between two values in terms of ULPs.

This should be an unsigned integer of the same size as the underlying floating point type, for example f32 uses u32. Composite types should probably use a type that follows the same structure as the inputs, to make error messages more legible.

Loading content...

Required methods

fn abs_diff(&self, other: &Rhs) -> Self::AbsDiff

Always positive absolute difference between two values.

Implementations should be the equivalent of:

(self - other).abs()

fn ulps_diff(&self, other: &Rhs) -> Option<Self::UlpsDiff>

Always positive absolute difference between two values in terms of ULPs.

A partial function that returns:

  • Some(0) if either argument is 0.0 or -0.0
  • None if either argument is NaN
  • None if the arguments have differing signs
  • Some(bitwise-difference) otherwise

Implementations on composite types should return None if any of their parts is an ulps_diff of None.

Implementations should be the equivalent of (using f32 as an example):

if self == other {
    Some(0)
} else if self.is_nan() || other.is_nan() {
    None
} else if self.is_sign_positive() != other.is_sign_positive() {
    None
} else {
    let a = self.to_bits();
    let b = other.to_bits();
    let max = a.max(b);
    let min = a.min(b);
    Some(max - min)
}
Loading content...

Implementations on Foreign Types

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

type AbsDiff = [<T as FloatDiff>::AbsDiff; 0]

type UlpsDiff = [<T as FloatDiff>::UlpsDiff; 0]

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

type AbsDiff = [<T as FloatDiff>::AbsDiff; 1]

type UlpsDiff = [<T as FloatDiff>::UlpsDiff; 1]

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

type AbsDiff = [<T as FloatDiff>::AbsDiff; 2]

type UlpsDiff = [<T as FloatDiff>::UlpsDiff; 2]

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

type AbsDiff = [<T as FloatDiff>::AbsDiff; 3]

type UlpsDiff = [<T as FloatDiff>::UlpsDiff; 3]

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

type AbsDiff = [<T as FloatDiff>::AbsDiff; 4]

type UlpsDiff = [<T as FloatDiff>::UlpsDiff; 4]

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

type AbsDiff = [<T as FloatDiff>::AbsDiff; 5]

type UlpsDiff = [<T as FloatDiff>::UlpsDiff; 5]

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

type AbsDiff = [<T as FloatDiff>::AbsDiff; 6]

type UlpsDiff = [<T as FloatDiff>::UlpsDiff; 6]

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

type AbsDiff = [<T as FloatDiff>::AbsDiff; 7]

type UlpsDiff = [<T as FloatDiff>::UlpsDiff; 7]

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

type AbsDiff = [<T as FloatDiff>::AbsDiff; 8]

type UlpsDiff = [<T as FloatDiff>::UlpsDiff; 8]

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

type AbsDiff = [<T as FloatDiff>::AbsDiff; 9]

type UlpsDiff = [<T as FloatDiff>::UlpsDiff; 9]

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

type AbsDiff = [<T as FloatDiff>::AbsDiff; 10]

type UlpsDiff = [<T as FloatDiff>::UlpsDiff; 10]

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

type AbsDiff = [<T as FloatDiff>::AbsDiff; 11]

type UlpsDiff = [<T as FloatDiff>::UlpsDiff; 11]

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

type AbsDiff = [<T as FloatDiff>::AbsDiff; 12]

type UlpsDiff = [<T as FloatDiff>::UlpsDiff; 12]

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

type AbsDiff = [<T as FloatDiff>::AbsDiff; 13]

type UlpsDiff = [<T as FloatDiff>::UlpsDiff; 13]

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

type AbsDiff = [<T as FloatDiff>::AbsDiff; 14]

type UlpsDiff = [<T as FloatDiff>::UlpsDiff; 14]

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

type AbsDiff = [<T as FloatDiff>::AbsDiff; 15]

type UlpsDiff = [<T as FloatDiff>::UlpsDiff; 15]

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

type AbsDiff = [<T as FloatDiff>::AbsDiff; 16]

type UlpsDiff = [<T as FloatDiff>::UlpsDiff; 16]

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

type AbsDiff = [<T as FloatDiff>::AbsDiff; 17]

type UlpsDiff = [<T as FloatDiff>::UlpsDiff; 17]

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

type AbsDiff = [<T as FloatDiff>::AbsDiff; 18]

type UlpsDiff = [<T as FloatDiff>::UlpsDiff; 18]

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

type AbsDiff = [<T as FloatDiff>::AbsDiff; 19]

type UlpsDiff = [<T as FloatDiff>::UlpsDiff; 19]

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

type AbsDiff = [<T as FloatDiff>::AbsDiff; 20]

type UlpsDiff = [<T as FloatDiff>::UlpsDiff; 20]

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

type AbsDiff = [<T as FloatDiff>::AbsDiff; 21]

type UlpsDiff = [<T as FloatDiff>::UlpsDiff; 21]

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

type AbsDiff = [<T as FloatDiff>::AbsDiff; 22]

type UlpsDiff = [<T as FloatDiff>::UlpsDiff; 22]

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

type AbsDiff = [<T as FloatDiff>::AbsDiff; 23]

type UlpsDiff = [<T as FloatDiff>::UlpsDiff; 23]

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

type AbsDiff = [<T as FloatDiff>::AbsDiff; 24]

type UlpsDiff = [<T as FloatDiff>::UlpsDiff; 24]

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

type AbsDiff = [<T as FloatDiff>::AbsDiff; 25]

type UlpsDiff = [<T as FloatDiff>::UlpsDiff; 25]

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

type AbsDiff = [<T as FloatDiff>::AbsDiff; 26]

type UlpsDiff = [<T as FloatDiff>::UlpsDiff; 26]

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

type AbsDiff = [<T as FloatDiff>::AbsDiff; 27]

type UlpsDiff = [<T as FloatDiff>::UlpsDiff; 27]

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

type AbsDiff = [<T as FloatDiff>::AbsDiff; 28]

type UlpsDiff = [<T as FloatDiff>::UlpsDiff; 28]

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

type AbsDiff = [<T as FloatDiff>::AbsDiff; 29]

type UlpsDiff = [<T as FloatDiff>::UlpsDiff; 29]

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

type AbsDiff = [<T as FloatDiff>::AbsDiff; 30]

type UlpsDiff = [<T as FloatDiff>::UlpsDiff; 30]

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

type AbsDiff = [<T as FloatDiff>::AbsDiff; 31]

type UlpsDiff = [<T as FloatDiff>::UlpsDiff; 31]

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

type AbsDiff = [<T as FloatDiff>::AbsDiff; 32]

type UlpsDiff = [<T as FloatDiff>::UlpsDiff; 32]

impl FloatDiff<f32> for f32[src]

type AbsDiff = Self

type UlpsDiff = u32

impl FloatDiff<f64> for f64[src]

type AbsDiff = Self

type UlpsDiff = u64

impl FloatDiff<()> for ()[src]

type AbsDiff = ()

type UlpsDiff = ()

impl<A> FloatDiff<(A,)> for (A,) where
    A: FloatDiff + ?Sized
[src]

type AbsDiff = (A::AbsDiff,)

type UlpsDiff = (A::UlpsDiff,)

impl<A: FloatDiff, B> FloatDiff<(A, B)> for (A, B) where
    B: FloatDiff + ?Sized
[src]

type AbsDiff = (A::AbsDiff, B::AbsDiff)

type UlpsDiff = (A::UlpsDiff, B::UlpsDiff)

impl<A: FloatDiff, B: FloatDiff, C> FloatDiff<(A, B, C)> for (A, B, C) where
    C: FloatDiff + ?Sized
[src]

type AbsDiff = (A::AbsDiff, B::AbsDiff, C::AbsDiff)

type UlpsDiff = (A::UlpsDiff, B::UlpsDiff, C::UlpsDiff)

impl<A: FloatDiff, B: FloatDiff, C: FloatDiff, D> FloatDiff<(A, B, C, D)> for (A, B, C, D) where
    D: FloatDiff + ?Sized
[src]

type AbsDiff = (A::AbsDiff, B::AbsDiff, C::AbsDiff, D::AbsDiff)

type UlpsDiff = (A::UlpsDiff, B::UlpsDiff, C::UlpsDiff, D::UlpsDiff)

impl<A: FloatDiff, B: FloatDiff, C: FloatDiff, D: FloatDiff, E> FloatDiff<(A, B, C, D, E)> for (A, B, C, D, E) where
    E: FloatDiff + ?Sized
[src]

type AbsDiff = (A::AbsDiff, B::AbsDiff, C::AbsDiff, D::AbsDiff, E::AbsDiff)

type UlpsDiff = (A::UlpsDiff, B::UlpsDiff, C::UlpsDiff, D::UlpsDiff, E::UlpsDiff)

impl<A: FloatDiff, B: FloatDiff, C: FloatDiff, D: FloatDiff, E: FloatDiff, F> FloatDiff<(A, B, C, D, E, F)> for (A, B, C, D, E, F) where
    F: FloatDiff + ?Sized
[src]

type AbsDiff = (A::AbsDiff, B::AbsDiff, C::AbsDiff, D::AbsDiff, E::AbsDiff, F::AbsDiff)

type UlpsDiff = (A::UlpsDiff, B::UlpsDiff, C::UlpsDiff, D::UlpsDiff, E::UlpsDiff, F::UlpsDiff)

impl<A: FloatDiff, B: FloatDiff, C: FloatDiff, D: FloatDiff, E: FloatDiff, F: FloatDiff, G> FloatDiff<(A, B, C, D, E, F, G)> for (A, B, C, D, E, F, G) where
    G: FloatDiff + ?Sized
[src]

type AbsDiff = (A::AbsDiff, B::AbsDiff, C::AbsDiff, D::AbsDiff, E::AbsDiff, F::AbsDiff, G::AbsDiff)

type UlpsDiff = (A::UlpsDiff, B::UlpsDiff, C::UlpsDiff, D::UlpsDiff, E::UlpsDiff, F::UlpsDiff, G::UlpsDiff)

impl<A: FloatDiff, B: FloatDiff, C: FloatDiff, D: FloatDiff, E: FloatDiff, F: FloatDiff, G: FloatDiff, H> FloatDiff<(A, B, C, D, E, F, G, H)> for (A, B, C, D, E, F, G, H) where
    H: FloatDiff + ?Sized
[src]

type AbsDiff = (A::AbsDiff, B::AbsDiff, C::AbsDiff, D::AbsDiff, E::AbsDiff, F::AbsDiff, G::AbsDiff, H::AbsDiff)

type UlpsDiff = (A::UlpsDiff, B::UlpsDiff, C::UlpsDiff, D::UlpsDiff, E::UlpsDiff, F::UlpsDiff, G::UlpsDiff, H::UlpsDiff)

impl<A: FloatDiff, B: FloatDiff, C: FloatDiff, D: FloatDiff, E: FloatDiff, F: FloatDiff, G: FloatDiff, H: FloatDiff, I> FloatDiff<(A, B, C, D, E, F, G, H, I)> for (A, B, C, D, E, F, G, H, I) where
    I: FloatDiff + ?Sized
[src]

type AbsDiff = (A::AbsDiff, B::AbsDiff, C::AbsDiff, D::AbsDiff, E::AbsDiff, F::AbsDiff, G::AbsDiff, H::AbsDiff, I::AbsDiff)

type UlpsDiff = (A::UlpsDiff, B::UlpsDiff, C::UlpsDiff, D::UlpsDiff, E::UlpsDiff, F::UlpsDiff, G::UlpsDiff, H::UlpsDiff, I::UlpsDiff)

impl<A: FloatDiff, B: FloatDiff, C: FloatDiff, D: FloatDiff, E: FloatDiff, F: FloatDiff, G: FloatDiff, H: FloatDiff, I: FloatDiff, J> FloatDiff<(A, B, C, D, E, F, G, H, I, J)> for (A, B, C, D, E, F, G, H, I, J) where
    J: FloatDiff + ?Sized
[src]

type AbsDiff = (A::AbsDiff, B::AbsDiff, C::AbsDiff, D::AbsDiff, E::AbsDiff, F::AbsDiff, G::AbsDiff, H::AbsDiff, I::AbsDiff, J::AbsDiff)

type UlpsDiff = (A::UlpsDiff, B::UlpsDiff, C::UlpsDiff, D::UlpsDiff, E::UlpsDiff, F::UlpsDiff, G::UlpsDiff, H::UlpsDiff, I::UlpsDiff, J::UlpsDiff)

impl<A: FloatDiff, B: FloatDiff, C: FloatDiff, D: FloatDiff, E: FloatDiff, F: FloatDiff, G: FloatDiff, H: FloatDiff, I: FloatDiff, J: FloatDiff, K> FloatDiff<(A, B, C, D, E, F, G, H, I, J, K)> for (A, B, C, D, E, F, G, H, I, J, K) where
    K: FloatDiff + ?Sized
[src]

type AbsDiff = (A::AbsDiff, B::AbsDiff, C::AbsDiff, D::AbsDiff, E::AbsDiff, F::AbsDiff, G::AbsDiff, H::AbsDiff, I::AbsDiff, J::AbsDiff, K::AbsDiff)

type UlpsDiff = (A::UlpsDiff, B::UlpsDiff, C::UlpsDiff, D::UlpsDiff, E::UlpsDiff, F::UlpsDiff, G::UlpsDiff, H::UlpsDiff, I::UlpsDiff, J::UlpsDiff, K::UlpsDiff)

impl<A: FloatDiff, B: FloatDiff, C: FloatDiff, D: FloatDiff, E: FloatDiff, F: FloatDiff, G: FloatDiff, H: FloatDiff, I: FloatDiff, J: FloatDiff, K: FloatDiff, L> FloatDiff<(A, B, C, D, E, F, G, H, I, J, K, L)> for (A, B, C, D, E, F, G, H, I, J, K, L) where
    L: FloatDiff + ?Sized
[src]

type AbsDiff = (A::AbsDiff, B::AbsDiff, C::AbsDiff, D::AbsDiff, E::AbsDiff, F::AbsDiff, G::AbsDiff, H::AbsDiff, I::AbsDiff, J::AbsDiff, K::AbsDiff, L::AbsDiff)

type UlpsDiff = (A::UlpsDiff, B::UlpsDiff, C::UlpsDiff, D::UlpsDiff, E::UlpsDiff, F::UlpsDiff, G::UlpsDiff, H::UlpsDiff, I::UlpsDiff, J::UlpsDiff, K::UlpsDiff, L::UlpsDiff)

impl<T> FloatDiff<Complex<T>> for Complex<T> where
    T: FloatDiff
[src]

type AbsDiff = Complex<T::AbsDiff>

type UlpsDiff = ComplexUlps<T::UlpsDiff>

Loading content...

Implementors

Loading content...