1#[cfg(feature = "num-traits")]
5#[allow(unused_imports)]
6use num_traits::float::FloatCore;
7use super::Ulps;
8
9pub trait ApproxEqUlps {
14 type Flt: Ulps;
15
16 fn approx_eq_ulps(&self, other: &Self, ulps: <Self::Flt as Ulps>::U) -> bool;
22
23 #[inline]
29 fn approx_ne_ulps(&self, other: &Self, ulps: <Self::Flt as Ulps>::U) -> bool {
30 !self.approx_eq_ulps(other, ulps)
31 }
32}
33
34impl ApproxEqUlps for f32 {
35 type Flt = f32;
36
37 fn approx_eq_ulps(&self, other: &f32, ulps: i32) -> bool {
38 if *self==*other { return true; }
41
42 if self.is_sign_positive() != other.is_sign_positive() { return false; }
46
47 let diff: i32 = self.ulps(other);
48 diff >= -ulps && diff <= ulps
49 }
50}
51
52#[test]
53fn f32_approx_eq_ulps_test1() {
54 let f: f32 = 0.1_f32;
55 let mut sum: f32 = 0.0_f32;
56 for _ in 0_isize..10_isize { sum += f; }
57 let product: f32 = f * 10.0_f32;
58 assert!(sum != product); assert!(sum.approx_eq_ulps(&product,1) == true); assert!(sum.approx_eq_ulps(&product,0) == false);
61}
62#[test]
63fn f32_approx_eq_ulps_test2() {
64 let x: f32 = 1000000_f32;
65 let y: f32 = 1000000.1_f32;
66 assert!(x != y); assert!(x.approx_eq_ulps(&y,2) == true);
68 assert!(x.approx_eq_ulps(&y,1) == false);
69}
70#[test]
71fn f32_approx_eq_ulps_test_zeroes() {
72 let x: f32 = 0.0_f32;
73 let y: f32 = -0.0_f32;
74 assert!(x.approx_eq_ulps(&y,0) == true);
75}
76
77impl ApproxEqUlps for f64 {
78 type Flt = f64;
79
80 fn approx_eq_ulps(&self, other: &f64, ulps: i64) -> bool {
81 if *self==*other { return true; }
84
85 if self.is_sign_positive() != other.is_sign_positive() { return false; }
89
90 let diff: i64 = self.ulps(other);
91 diff >= -ulps && diff <= ulps
92 }
93}
94
95#[test]
96fn f64_approx_eq_ulps_test1() {
97 let f: f64 = 0.1_f64;
98 let mut sum: f64 = 0.0_f64;
99 for _ in 0_isize..10_isize { sum += f; }
100 let product: f64 = f * 10.0_f64;
101 assert!(sum != product); assert!(sum.approx_eq_ulps(&product,1) == true); assert!(sum.approx_eq_ulps(&product,0) == false);
104}
105#[test]
106fn f64_approx_eq_ulps_test2() {
107 let x: f64 = 1000000_f64;
108 let y: f64 = 1000000.0000000003_f64;
109 assert!(x != y); assert!(x.approx_eq_ulps(&y,3) == true);
111 assert!(x.approx_eq_ulps(&y,2) == false);
112}
113#[test]
114fn f64_approx_eq_ulps_test_zeroes() {
115 let x: f64 = 0.0_f64;
116 let y: f64 = -0.0_f64;
117 assert!(x.approx_eq_ulps(&y,0) == true);
118}