Skip to main content

fuzzycomp/
lib.rs

1/// Reexporting assert_approx_eq macro from assert_approx_eq
2pub use assert_approx_eq::assert_approx_eq;
3
4/// Equal within margin (equal enough)
5///
6/// Compares two f64 with a given margin. Returns true if
7/// they are equal enough.
8///
9/// ```
10/// if(fuzzycomp::eq(std::f64::consts::PI, 3.0, 0.2)) {
11///     println!("Precision engineering!");
12/// }
13/// ```
14pub fn eq<T>(lh: T, rh: T, margin: T) -> bool
15where
16    T: PartialOrd + std::ops::Add<Output = T> + std::ops::Sub<Output = T> + Copy,
17{
18    (rh <= (lh + margin)) & (rh >= (lh - margin))
19}
20
21/// Not equal within margin (unequal enough)
22///
23/// Compares two f64 with a given margin. Returns true if
24/// they are unequal enough.
25///
26/// ```
27/// if(fuzzycomp::ne(std::f64::consts::PI, 3.0, 0.1)) {
28///     println!("We need better approximation!");
29/// }
30/// ```
31pub fn ne<T>(lh: T, rh: T, margin: T) -> bool
32where
33    T: PartialOrd + std::ops::Add<Output = T> + std::ops::Sub<Output = T> + Copy,
34{
35    (lh + margin < rh) | (lh - margin > rh)
36}
37
38/// Surely greater (greater enough)
39///
40/// Compares two f64 with a given margin. Returns true if
41/// first is obviously greater (despite margins).
42///
43/// ```
44/// if(fuzzycomp::gt(std::f64::consts::PI, 3.0, 0.1)) {
45///     println!("π is more than 3!");
46/// }
47/// ```
48pub fn gt<T>(lh: T, rh: T, margin: T) -> bool
49where
50    T: PartialOrd + std::ops::Add<Output = T> + std::ops::Sub<Output = T> + Copy,
51{
52    lh > (rh + margin)
53}
54
55/// Surely less (less enough)
56///
57/// Compares two f64 with a given margin. Returns true if
58/// first is obviously lesser (despite margins).
59///
60/// ```
61/// if(fuzzycomp::lt(std::f64::consts::PI, 4.0, 0.5)) {
62///     println!("π is a lot less than 3!");
63/// }
64/// ```
65pub fn lt<T>(lh: T, rh: T, margin: T) -> bool
66where
67    T: PartialOrd + std::ops::Add<Output = T> + std::ops::Sub<Output = T> + Copy,
68{
69    lh < (rh - margin)
70}
71
72/// Not surely smaller (at least equal)
73///
74/// Compares two f64 with a given margin. Returns true if
75/// first is not obviously lesser (despite margins).
76///
77/// ```
78/// if(fuzzycomp::ge(1.0, 0.0, 0.1)) {
79///     println!("1.0 is a at least 0, give or take!");
80/// }
81/// ```
82pub fn ge<T>(lh: T, rh: T, margin: T) -> bool
83where
84    T: PartialOrd + std::ops::Add<Output = T> + std::ops::Sub<Output = T> + Copy,
85{
86    lh >= (rh - margin)
87}
88
89/// Not surely larger (at most equal)
90///
91/// Compares two f64 with a given margin. Returns true if
92/// first is not obviously lesser (despite margins).
93///
94/// ```
95/// if(fuzzycomp::le(0.0, 1.0, 0.1)) {
96///     println!("0 is not even 1!");
97/// }
98/// ```
99pub fn le<T>(lh: T, rh: T, margin: T) -> bool
100where
101    T: PartialOrd + std::ops::Add<Output = T> + std::ops::Sub<Output = T> + Copy,
102{
103    lh <= (rh + margin)
104}
105
106#[cfg(test)]
107mod tests {
108
109    #[test]
110    fn eq() {
111        assert!(super::eq(std::f64::consts::PI, 3.0, 0.2));
112        assert!(super::eq(9.1, 9.1, 0.0));
113        assert!(super::eq(8.4, 9.1, 1.0));
114        assert!(super::eq(-0.1, -0.3, 0.2));
115        assert!(super::eq(-0.1, 0.1, 0.2));
116        assert!(!super::eq(0.1, 0.2, 0.01));
117        assert!(super::eq(1, 1, 0));
118    }
119
120    #[test]
121    fn ne() {
122        assert!(!super::ne(9.1, 9.1, 0.0));
123        assert!(!super::ne(8.4, 9.1, 1.0));
124        assert!(!super::ne(-0.1, -0.3, 0.2));
125        assert!(!super::ne(-0.1, 0.1, 0.2));
126        assert!(super::ne(0.1, 0.2, 0.01));
127        assert!(super::ne(1, 3, 1));
128    }
129
130    #[test]
131    fn gt() {
132        assert!(super::gt(8.1, 8.0, 0.0));
133        assert!(super::gt(8.1, 8.0, 0.05));
134        assert!(!super::gt(8.1, 8.0, 0.1));
135        assert!(super::gt(10, 8, 1));
136    }
137
138    #[test]
139    fn lt() {
140        assert!(super::lt(8.0, 8.1, 0.0));
141        assert!(super::lt(8.0, 8.1, 0.05));
142        assert!(!super::lt(8.0, 8.1, 0.1));
143        assert!(super::lt(8, 10, 1));
144    }
145
146    #[test]
147    fn ge() {
148        assert!(super::ge(8.1, 8.0, 0.0));
149        assert!(super::ge(8.1, 8.0, 0.05));
150        assert!(super::ge(8.1, 8.0, 0.1));
151        assert!(super::ge(8.0, 8.1, 0.1));
152        assert!(!super::ge(7.9, 8.1, 0.1));
153        assert!(super::ge(8, 7, 1));
154    }
155
156    #[test]
157    fn le() {
158        assert!(super::le(8.0, 8.1, 0.0));
159        assert!(super::le(8.0, 8.1, 0.05));
160        assert!(super::le(8.0, 8.1, 0.1));
161        assert!(super::le(8.1, 8.0, 0.1));
162        assert!(!super::le(8.2, 8.0, 0.1));
163        assert!(super::le(8, 8, 1));
164    }
165}