1#![cfg(feature = "std")]
2
3use crate::nearly_eq::{NearlyEq, NearlyEqEps, NearlyEqTol, NearlyEqUlps};
4use crate::nearly_ord::{NearlyOrd, NearlyOrdEps, NearlyOrdTol, NearlyOrdUlps};
5use crate::tolerance::{
6 EpsTolerance, EpsToleranceType, Tolerance, UlpsTolerance, UlpsToleranceType,
7};
8
9use std::collections::{BTreeMap, HashMap};
10use std::hash::{BuildHasher, Hash};
11
12impl<K, Lhs, Rhs, S> NearlyEqEps<HashMap<K, Rhs, S>, Lhs, Rhs> for HashMap<K, Lhs, S>
17where
18 K: Eq + Hash,
19 Lhs: NearlyEqEps<Rhs> + EpsTolerance<Rhs>,
20 S: BuildHasher,
21{
22 fn nearly_eq_eps(&self, other: &HashMap<K, Rhs, S>, eps: &EpsToleranceType<Lhs, Rhs>) -> bool {
23 self.len() == other.len()
24 && self.iter().all(|(key, v_lhs)| {
25 other
26 .get(key)
27 .map_or(false, |v_rhs| NearlyEqEps::nearly_eq_eps(v_lhs, v_rhs, eps))
28 })
29 }
30}
31
32impl<K, Lhs, Rhs, S> NearlyEqUlps<HashMap<K, Rhs, S>, Lhs, Rhs> for HashMap<K, Lhs, S>
33where
34 K: Eq + Hash,
35 Lhs: NearlyEqUlps<Rhs> + UlpsTolerance<Rhs>,
36 S: BuildHasher,
37{
38 fn nearly_eq_ulps(
39 &self,
40 other: &HashMap<K, Rhs, S>,
41 ulps: &UlpsToleranceType<Lhs, Rhs>,
42 ) -> bool {
43 self.len() == other.len()
44 && self.iter().all(|(key, v_lhs)| {
45 other.get(key).map_or(false, |v_rhs| {
46 NearlyEqUlps::nearly_eq_ulps(v_lhs, v_rhs, ulps)
47 })
48 })
49 }
50}
51
52impl<K, Lhs, Rhs, S> NearlyEqTol<HashMap<K, Rhs, S>, Lhs, Rhs> for HashMap<K, Lhs, S>
53where
54 K: Eq + Hash,
55 Lhs: NearlyEqTol<Rhs> + EpsTolerance<Rhs> + UlpsTolerance<Rhs>,
56 S: BuildHasher,
57{
58 fn nearly_eq_tol(&self, other: &HashMap<K, Rhs, S>, tol: &Tolerance<Lhs, Rhs>) -> bool {
59 self.len() == other.len()
60 && self.iter().all(|(key, v_lhs)| {
61 other
62 .get(key)
63 .map_or(false, |v_rhs| NearlyEqTol::nearly_eq_tol(v_lhs, v_rhs, tol))
64 })
65 }
66}
67
68impl<K, Lhs, Rhs, S> NearlyEq<HashMap<K, Rhs, S>, Lhs, Rhs> for HashMap<K, Lhs, S>
69where
70 K: Eq + Hash,
71 Lhs: NearlyEq<Rhs> + EpsTolerance<Rhs> + UlpsTolerance<Rhs>,
72 S: BuildHasher,
73{
74}
75
76impl<K, Lhs, Rhs> NearlyEqEps<BTreeMap<K, Rhs>, Lhs, Rhs> for BTreeMap<K, Lhs>
77where
78 K: PartialEq,
79 Lhs: NearlyEqEps<Rhs> + EpsTolerance<Rhs>,
80{
81 fn nearly_eq_eps(&self, other: &BTreeMap<K, Rhs>, eps: &EpsToleranceType<Lhs, Rhs>) -> bool {
82 self.len() == other.len()
83 && self
84 .iter()
85 .zip(other)
86 .all(|(a, b)| a.0 == b.0 && NearlyEqEps::nearly_eq_eps(a.1, b.1, eps))
87 }
88}
89
90impl<K, Lhs, Rhs> NearlyEqUlps<BTreeMap<K, Rhs>, Lhs, Rhs> for BTreeMap<K, Lhs>
91where
92 K: PartialEq,
93 Lhs: NearlyEqUlps<Rhs> + UlpsTolerance<Rhs>,
94{
95 fn nearly_eq_ulps(&self, other: &BTreeMap<K, Rhs>, ulps: &UlpsToleranceType<Lhs, Rhs>) -> bool {
96 self.len() == other.len()
97 && self
98 .iter()
99 .zip(other)
100 .all(|(a, b)| a.0 == b.0 && NearlyEqUlps::nearly_eq_ulps(a.1, b.1, ulps))
101 }
102}
103
104impl<K, Lhs, Rhs> NearlyEqTol<BTreeMap<K, Rhs>, Lhs, Rhs> for BTreeMap<K, Lhs>
105where
106 K: PartialEq,
107 Lhs: NearlyEqTol<Rhs> + EpsTolerance<Rhs> + UlpsTolerance<Rhs>,
108{
109 fn nearly_eq_tol(&self, other: &BTreeMap<K, Rhs>, tol: &Tolerance<Lhs, Rhs>) -> bool {
110 self.len() == other.len()
111 && self
112 .iter()
113 .zip(other)
114 .all(|(a, b)| a.0 == b.0 && NearlyEqTol::nearly_eq_tol(a.1, b.1, tol))
115 }
116}
117
118impl<K, Lhs, Rhs> NearlyEq<BTreeMap<K, Rhs>, Lhs, Rhs> for BTreeMap<K, Lhs>
119where
120 K: PartialEq,
121 Lhs: NearlyEq<Rhs> + EpsTolerance<Rhs> + UlpsTolerance<Rhs>,
122{
123}
124
125impl<K, Lhs, Rhs, S> NearlyOrdEps<HashMap<K, Rhs, S>, Lhs, Rhs> for HashMap<K, Lhs, S>
130where
131 K: Eq + Hash,
132 Lhs: NearlyOrdEps<Rhs> + EpsTolerance<Rhs>,
133 S: BuildHasher,
134{
135 fn nearly_lt_eps(&self, other: &HashMap<K, Rhs, S>, eps: &EpsToleranceType<Lhs, Rhs>) -> bool {
136 self.len() == other.len()
137 && self.iter().all(|(key, v_lhs)| {
138 other.get(key).map_or(false, |v_rhs| {
139 NearlyOrdEps::nearly_lt_eps(v_lhs, v_rhs, eps)
140 })
141 })
142 }
143
144 fn nearly_le_eps(&self, other: &HashMap<K, Rhs, S>, eps: &EpsToleranceType<Lhs, Rhs>) -> bool {
145 self.len() == other.len()
146 && self.iter().all(|(key, v_lhs)| {
147 other.get(key).map_or(false, |v_rhs| {
148 NearlyOrdEps::nearly_le_eps(v_lhs, v_rhs, eps)
149 })
150 })
151 }
152
153 fn nearly_gt_eps(&self, other: &HashMap<K, Rhs, S>, eps: &EpsToleranceType<Lhs, Rhs>) -> bool {
154 self.len() == other.len()
155 && self.iter().all(|(key, v_lhs)| {
156 other.get(key).map_or(false, |v_rhs| {
157 NearlyOrdEps::nearly_gt_eps(v_lhs, v_rhs, eps)
158 })
159 })
160 }
161
162 fn nearly_ge_eps(&self, other: &HashMap<K, Rhs, S>, eps: &EpsToleranceType<Lhs, Rhs>) -> bool {
163 self.len() == other.len()
164 && self.iter().all(|(key, v_lhs)| {
165 other.get(key).map_or(false, |v_rhs| {
166 NearlyOrdEps::nearly_ge_eps(v_lhs, v_rhs, eps)
167 })
168 })
169 }
170}
171
172impl<K, Lhs, Rhs, S> NearlyOrdUlps<HashMap<K, Rhs, S>, Lhs, Rhs> for HashMap<K, Lhs, S>
173where
174 K: Eq + Hash,
175 Lhs: NearlyOrdUlps<Rhs> + UlpsTolerance<Rhs>,
176 S: BuildHasher,
177{
178 fn nearly_lt_ulps(
179 &self,
180 other: &HashMap<K, Rhs, S>,
181 ulps: &UlpsToleranceType<Lhs, Rhs>,
182 ) -> bool {
183 self.len() == other.len()
184 && self.iter().all(|(key, v_lhs)| {
185 other.get(key).map_or(false, |v_rhs| {
186 NearlyOrdUlps::nearly_lt_ulps(v_lhs, v_rhs, ulps)
187 })
188 })
189 }
190
191 fn nearly_le_ulps(
192 &self,
193 other: &HashMap<K, Rhs, S>,
194 ulps: &UlpsToleranceType<Lhs, Rhs>,
195 ) -> bool {
196 self.len() == other.len()
197 && self.iter().all(|(key, v_lhs)| {
198 other.get(key).map_or(false, |v_rhs| {
199 NearlyOrdUlps::nearly_le_ulps(v_lhs, v_rhs, ulps)
200 })
201 })
202 }
203
204 fn nearly_gt_ulps(
205 &self,
206 other: &HashMap<K, Rhs, S>,
207 ulps: &UlpsToleranceType<Lhs, Rhs>,
208 ) -> bool {
209 self.len() == other.len()
210 && self.iter().all(|(key, v_lhs)| {
211 other.get(key).map_or(false, |v_rhs| {
212 NearlyOrdUlps::nearly_gt_ulps(v_lhs, v_rhs, ulps)
213 })
214 })
215 }
216
217 fn nearly_ge_ulps(
218 &self,
219 other: &HashMap<K, Rhs, S>,
220 ulps: &UlpsToleranceType<Lhs, Rhs>,
221 ) -> bool {
222 self.len() == other.len()
223 && self.iter().all(|(key, v_lhs)| {
224 other.get(key).map_or(false, |v_rhs| {
225 NearlyOrdUlps::nearly_ge_ulps(v_lhs, v_rhs, ulps)
226 })
227 })
228 }
229}
230
231impl<K, Lhs, Rhs, S> NearlyOrdTol<HashMap<K, Rhs, S>, Lhs, Rhs> for HashMap<K, Lhs, S>
232where
233 K: Eq + Hash,
234 Lhs: NearlyOrdTol<Rhs> + EpsTolerance<Rhs> + UlpsTolerance<Rhs>,
235 S: BuildHasher,
236{
237 fn nearly_lt_tol(&self, other: &HashMap<K, Rhs, S>, tol: &Tolerance<Lhs, Rhs>) -> bool {
238 self.len() == other.len()
239 && self.iter().all(|(key, v_lhs)| {
240 other.get(key).map_or(false, |v_rhs| {
241 NearlyOrdTol::nearly_lt_tol(v_lhs, v_rhs, tol)
242 })
243 })
244 }
245
246 fn nearly_le_tol(&self, other: &HashMap<K, Rhs, S>, tol: &Tolerance<Lhs, Rhs>) -> bool {
247 self.len() == other.len()
248 && self.iter().all(|(key, v_lhs)| {
249 other.get(key).map_or(false, |v_rhs| {
250 NearlyOrdTol::nearly_le_tol(v_lhs, v_rhs, tol)
251 })
252 })
253 }
254
255 fn nearly_gt_tol(&self, other: &HashMap<K, Rhs, S>, tol: &Tolerance<Lhs, Rhs>) -> bool {
256 self.len() == other.len()
257 && self.iter().all(|(key, v_lhs)| {
258 other.get(key).map_or(false, |v_rhs| {
259 NearlyOrdTol::nearly_gt_tol(v_lhs, v_rhs, tol)
260 })
261 })
262 }
263
264 fn nearly_ge_tol(&self, other: &HashMap<K, Rhs, S>, tol: &Tolerance<Lhs, Rhs>) -> bool {
265 self.len() == other.len()
266 && self.iter().all(|(key, v_lhs)| {
267 other.get(key).map_or(false, |v_rhs| {
268 NearlyOrdTol::nearly_ge_tol(v_lhs, v_rhs, tol)
269 })
270 })
271 }
272}
273
274impl<K, Lhs, Rhs, S> NearlyOrd<HashMap<K, Rhs, S>, Lhs, Rhs> for HashMap<K, Lhs, S>
275where
276 K: Eq + Hash,
277 Lhs: NearlyOrd<Rhs> + EpsTolerance<Rhs> + UlpsTolerance<Rhs>,
278 S: BuildHasher,
279{
280}
281
282impl<K, Lhs, Rhs> NearlyOrdEps<BTreeMap<K, Rhs>, Lhs, Rhs> for BTreeMap<K, Lhs>
283where
284 K: PartialEq,
285 Lhs: NearlyOrdEps<Rhs> + EpsTolerance<Rhs>,
286{
287 fn nearly_lt_eps(&self, other: &BTreeMap<K, Rhs>, eps: &EpsToleranceType<Lhs, Rhs>) -> bool {
288 self.len() == other.len()
289 && self
290 .iter()
291 .zip(other)
292 .all(|(a, b)| a.0 == b.0 && NearlyOrdEps::nearly_lt_eps(a.1, b.1, eps))
293 }
294
295 fn nearly_le_eps(&self, other: &BTreeMap<K, Rhs>, eps: &EpsToleranceType<Lhs, Rhs>) -> bool {
296 self.len() == other.len()
297 && self
298 .iter()
299 .zip(other)
300 .all(|(a, b)| a.0 == b.0 && NearlyOrdEps::nearly_le_eps(a.1, b.1, eps))
301 }
302
303 fn nearly_gt_eps(&self, other: &BTreeMap<K, Rhs>, eps: &EpsToleranceType<Lhs, Rhs>) -> bool {
304 self.len() == other.len()
305 && self
306 .iter()
307 .zip(other)
308 .all(|(a, b)| a.0 == b.0 && NearlyOrdEps::nearly_gt_eps(a.1, b.1, eps))
309 }
310
311 fn nearly_ge_eps(&self, other: &BTreeMap<K, Rhs>, eps: &EpsToleranceType<Lhs, Rhs>) -> bool {
312 self.len() == other.len()
313 && self
314 .iter()
315 .zip(other)
316 .all(|(a, b)| a.0 == b.0 && NearlyOrdEps::nearly_ge_eps(a.1, b.1, eps))
317 }
318}
319
320impl<K, Lhs, Rhs> NearlyOrdUlps<BTreeMap<K, Rhs>, Lhs, Rhs> for BTreeMap<K, Lhs>
321where
322 K: PartialEq,
323 Lhs: NearlyOrdUlps<Rhs> + UlpsTolerance<Rhs>,
324{
325 fn nearly_lt_ulps(&self, other: &BTreeMap<K, Rhs>, ulps: &UlpsToleranceType<Lhs, Rhs>) -> bool {
326 self.len() == other.len()
327 && self
328 .iter()
329 .zip(other)
330 .all(|(a, b)| a.0 == b.0 && NearlyOrdUlps::nearly_lt_ulps(a.1, b.1, ulps))
331 }
332
333 fn nearly_le_ulps(&self, other: &BTreeMap<K, Rhs>, ulps: &UlpsToleranceType<Lhs, Rhs>) -> bool {
334 self.len() == other.len()
335 && self
336 .iter()
337 .zip(other)
338 .all(|(a, b)| a.0 == b.0 && NearlyOrdUlps::nearly_le_ulps(a.1, b.1, ulps))
339 }
340
341 fn nearly_gt_ulps(&self, other: &BTreeMap<K, Rhs>, ulps: &UlpsToleranceType<Lhs, Rhs>) -> bool {
342 self.len() == other.len()
343 && self
344 .iter()
345 .zip(other)
346 .all(|(a, b)| a.0 == b.0 && NearlyOrdUlps::nearly_gt_ulps(a.1, b.1, ulps))
347 }
348
349 fn nearly_ge_ulps(&self, other: &BTreeMap<K, Rhs>, ulps: &UlpsToleranceType<Lhs, Rhs>) -> bool {
350 self.len() == other.len()
351 && self
352 .iter()
353 .zip(other)
354 .all(|(a, b)| a.0 == b.0 && NearlyOrdUlps::nearly_ge_ulps(a.1, b.1, ulps))
355 }
356}
357
358impl<K, Lhs, Rhs> NearlyOrdTol<BTreeMap<K, Rhs>, Lhs, Rhs> for BTreeMap<K, Lhs>
359where
360 K: PartialEq,
361 Lhs: NearlyOrdTol<Rhs> + EpsTolerance<Rhs> + UlpsTolerance<Rhs>,
362{
363 fn nearly_lt_tol(&self, other: &BTreeMap<K, Rhs>, tol: &Tolerance<Lhs, Rhs>) -> bool {
364 self.len() == other.len()
365 && self
366 .iter()
367 .zip(other)
368 .all(|(a, b)| a.0 == b.0 && NearlyOrdTol::nearly_lt_tol(a.1, b.1, tol))
369 }
370
371 fn nearly_le_tol(&self, other: &BTreeMap<K, Rhs>, tol: &Tolerance<Lhs, Rhs>) -> bool {
372 self.len() == other.len()
373 && self
374 .iter()
375 .zip(other)
376 .all(|(a, b)| a.0 == b.0 && NearlyOrdTol::nearly_le_tol(a.1, b.1, tol))
377 }
378
379 fn nearly_gt_tol(&self, other: &BTreeMap<K, Rhs>, tol: &Tolerance<Lhs, Rhs>) -> bool {
380 self.len() == other.len()
381 && self
382 .iter()
383 .zip(other)
384 .all(|(a, b)| a.0 == b.0 && NearlyOrdTol::nearly_gt_tol(a.1, b.1, tol))
385 }
386
387 fn nearly_ge_tol(&self, other: &BTreeMap<K, Rhs>, tol: &Tolerance<Lhs, Rhs>) -> bool {
388 self.len() == other.len()
389 && self
390 .iter()
391 .zip(other)
392 .all(|(a, b)| a.0 == b.0 && NearlyOrdTol::nearly_ge_tol(a.1, b.1, tol))
393 }
394}
395
396impl<K, Lhs, Rhs> NearlyOrd<BTreeMap<K, Rhs>, Lhs, Rhs> for BTreeMap<K, Lhs>
397where
398 K: PartialEq,
399 Lhs: NearlyOrd<Rhs> + EpsTolerance<Rhs> + UlpsTolerance<Rhs>,
400{
401}