]> git.proxmox.com Git - rustc.git/blob - src/vendor/hamcrest/src/matchers/close_to.rs
New upstream version 1.19.0+dfsg1
[rustc.git] / src / vendor / hamcrest / src / matchers / close_to.rs
1 // Copyright 2014 Steve Klabnik, Valerii Hiora, Oliver Mader
2 // Copyright 2015 Carl Lerche, Oliver Mader, Alex Crichton, Graham Dennis,
3 // Tamir Duberstein, Robin Gloster
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 use num::{Float, Zero};
12 use std::fmt::{self, Display, Debug, Formatter};
13 use {success, Matcher, MatchResult};
14
15 /// Compares two floating point values for equality.
16 ///
17 /// The comparison is based on a relative error metric and uses special
18 /// fallbacks for certain edge cases like very small numbers. The exact
19 /// algorithm is described [here](http://floating-point-gui.de/errors/comparison/).
20 pub struct CloseTo<T> {
21 expected: T,
22 epsilon: T,
23 }
24
25 impl<T: Debug> Display for CloseTo<T> {
26 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
27 self.expected.fmt(f)
28 }
29 }
30
31 impl<T: Float + Zero + Debug> Matcher<T> for CloseTo<T> {
32 fn matches(&self, actual: T) -> MatchResult {
33 let a = self.expected.abs();
34 let b = actual.abs();
35
36 let d = (a - b).abs();
37
38 let close =
39 // shortcut, handles infinities
40 a == b
41 // a or b is zero or both are extremely close to it
42 // relative error is less meaningful here
43 || ((a == Zero::zero() || b == Zero::zero() || d < Float::min_positive_value()) &&
44 d < (self.epsilon * Float::min_positive_value()))
45 // use relative error
46 || d / (a + b).min(Float::max_value()) < self.epsilon;
47
48 if close {
49 success()
50 } else {
51 Err(format!("was {:?}", actual))
52 }
53 }
54 }
55
56 pub fn close_to<T>(expected: T, epsilon: T) -> CloseTo<T> {
57 CloseTo {
58 expected: expected,
59 epsilon: epsilon
60 }
61 }
62
63 #[cfg(test)]
64 mod test {
65 use std::f64;
66 use {assert_that,is,not,close_to};
67
68 #[test]
69 fn equality_of_floats() {
70 assert_that(1.0f64, is(close_to(1.0, 0.00001)));
71 assert_that(1e-40f32, is(close_to(0.0, 0.01)));
72 assert_that(1e-40f32, is(not(close_to(0.0, 0.000001))));
73 assert_that(2.0, is(not(close_to(1.0f64, 0.00001))));
74 }
75
76 #[test]
77 fn it_can_handle_infinity() {
78 assert_that(f64::INFINITY, is(close_to(f64::INFINITY, 0.00001)));
79 }
80
81 #[test]
82 fn it_can_handle_nan() {
83 assert_that(f64::NAN, is(not(close_to(f64::NAN, 0.00001))));
84 }
85 }