1#[macro_export]
35macro_rules! assert_pos_relative_eq {
36 ($left:expr, $right:expr, $epsilon:expr) => {{
37 let left: $crate::Positive = $left;
38 let right: $crate::Positive = $right;
39 let epsilon: $crate::Positive = $epsilon;
40 let diff_f64 = (left.to_f64() - right.to_f64()).abs();
41
42 if diff_f64 == 0.0 {
44 } else {
46 let abs_diff: $crate::Positive = $crate::Positive::new(diff_f64)
50 .expect("abs_diff must be positive"); let max_abs = left.max(right);
52
53 if left.is_zero() || right.is_zero() {
54 let non_zero_value = if left.is_zero() {
55 right
56 } else {
57 left
58 };
59 assert!(
60 non_zero_value <= epsilon,
61 "assertion failed: `(left == right)` \
62 (left: `{}`, right: `{}`, expected max value: `{}`, actual value: `{}`)",
63 left,
64 right,
65 epsilon,
66 non_zero_value
67 );
68 } else {
69 let relative_diff = abs_diff / max_abs;
70 assert!(
71 relative_diff <= epsilon,
72 "assertion failed: `(left ≈ right)` \
73 (left: `{}`, right: `{}`, expected relative diff: `{}`, real relative diff: `{}`)",
74 left,
75 right,
76 epsilon,
77 relative_diff
78 );
79 }
80 }
81 }};
82}
83
84#[cfg(test)]
85mod tests_assert_positivef64_relative_eq {
86 use crate::Positive;
87
88 #[test]
89 fn test_exact_equality() {
90 let a = pos_or_panic!(1.0);
91 let b = pos_or_panic!(1.0);
92 let epsilon = pos_or_panic!(0.0001);
93 assert_pos_relative_eq!(a, b, epsilon);
94 }
95
96 #[test]
97 fn test_close_values() {
98 let a = pos_or_panic!(1.0);
99 let b = pos_or_panic!(1.0001);
100 let epsilon = pos_or_panic!(0.001);
101 assert_pos_relative_eq!(a, b, epsilon);
102 }
103
104 #[test]
105 fn test_zero_values() {
106 let a = Positive::ZERO;
107 let b = Positive::ZERO;
108 let epsilon = pos_or_panic!(0.0001);
109 assert_pos_relative_eq!(a, b, epsilon);
110 }
111
112 #[test]
113 fn test_zero_and_small_value() {
114 let a = Positive::ZERO;
115 let b = pos_or_panic!(0.00001);
116 let epsilon = pos_or_panic!(0.00001);
117 assert_pos_relative_eq!(a, b, epsilon);
118 }
119
120 #[test]
121 #[should_panic(expected = "assertion failed")]
122 fn test_values_exceeding_epsilon() {
123 let a = pos_or_panic!(1.0);
124 let b = pos_or_panic!(1.002);
125 let epsilon = pos_or_panic!(0.001);
126 assert_pos_relative_eq!(a, b, epsilon);
127 }
128
129 #[test]
130 fn test_large_values() {
131 let a = pos_or_panic!(1000000.0);
132 let b = pos_or_panic!(1000001.0);
133 let epsilon = pos_or_panic!(0.000002);
134 assert_pos_relative_eq!(a, b, epsilon);
135 }
136
137 #[test]
138 fn test_very_small_values() {
139 let a = pos_or_panic!(0.0000001);
140 let b = pos_or_panic!(0.0000001000001);
141 let epsilon = pos_or_panic!(0.000002);
142 assert_pos_relative_eq!(a, b, epsilon);
143 }
144
145 #[test]
146 #[should_panic(expected = "assertion failed")]
147 fn test_significantly_different_values() {
148 let a = pos_or_panic!(1.0);
149 let b = pos_or_panic!(2.0);
150 let epsilon = pos_or_panic!(0.1);
151 assert_pos_relative_eq!(a, b, epsilon);
152 }
153
154 #[test]
155 fn test_equal_within_epsilon() {
156 let a = pos_or_panic!(100.0);
157 let b = pos_or_panic!(100.1);
158 let epsilon = pos_or_panic!(0.002);
159 assert_pos_relative_eq!(a, b, epsilon);
160 }
161
162 #[test]
163 #[should_panic(expected = "assertion failed")]
164 fn test_zero_and_large_value() {
165 let a = Positive::ZERO;
166 let b = pos_or_panic!(1.0);
167 let epsilon = pos_or_panic!(0.0001);
168 assert_pos_relative_eq!(a, b, epsilon);
169 }
170}