test_helpers/
lib.rs

1// lib.rs : test_help-rs
2
3#![allow(non_camel_case_types)]
4
5
6// /////////////////////////////////////////////////////////
7// crate-level feature definitions
8
9#![cfg_attr(test, feature(more_float_constants))]
10
11
12// /////////////////////////////////////////////////////////
13// crate-level feature discrimination
14
15
16// /////////////////////////////////////////////////////////
17// imports
18
19use std::{
20    convert as std_convert,
21    fmt as std_fmt,
22};
23
24
25// /////////////////////////////////////////////////////////
26// constants
27
28/// Constants.
29pub mod constants {
30
31    /// The default margin.
32    pub const DEFAULT_MARGIN : f64 = 0.0001;
33
34    /// The default multiplier.
35    pub const DEFAULT_MULTIPLIER : f64 = 0.000001;
36}
37
38
39// /////////////////////////////////////////////////////////
40// types
41
42/// Comparison result type.
43#[derive(Debug)]
44#[derive(PartialEq)]
45#[derive(PartialOrd)]
46pub enum ComparisonResult {
47    /// The comparands are exactly equal.
48    ExactlyEqual,
49    /// The comparands are equal within the tolerance of the given margin or
50    /// multiplier.
51    ApproximatelyEqual,
52    /// The comparands are not equal within the tolerance of the given
53    /// margin or multiplier.
54    Unequal,
55}
56
57/// Vector comparison result type.
58#[derive(Debug)]
59pub enum VectorComparisonResult {
60    ExactlyEqual,
61    ApproximatelyEqual,
62    DifferentLengths {
63        expected_length : usize,
64        actual_length :   usize,
65    },
66    UnequalElements {
67        index_of_first_unequal_element :          usize,
68        expected_value_of_first_unequal_element : f64,
69        actual_value_of_first_unequal_element :   f64,
70    },
71}
72
73
74/// Traits.
75pub mod traits {
76    use super::ComparisonResult;
77
78    use base_traits::ToF64;
79
80    use std::fmt as std_fmt;
81
82
83    /// Trait that defines a mechanism for performing approximate equality
84    /// evaluation.
85    pub trait ApproximateEqualityEvaluator {
86        fn evaluate(
87            &self,
88            expected : f64,
89            actual : f64,
90        ) -> (
91            ComparisonResult, // comparison_result
92            Option<f64>,      // margin_factor
93            Option<f64>,      // multiplier_factor
94        );
95    }
96
97    /// Trait that allows an implementing type instance to be evaluated with the
98    /// constructs of this crate.
99    ///
100    /// NOTE: it is implemented for any types that implement
101    /// `base_traits::ToF64` (and `std::fmt::Debug`).
102    pub trait TestableAsF64: std_fmt::Debug {
103        fn testable_as_f64(&self) -> f64;
104    }
105
106    impl<T> TestableAsF64 for T
107    where
108        T : ToF64 + std_fmt::Debug,
109    {
110        fn testable_as_f64(&self) -> f64 {
111            self.to_f64()
112        }
113    }
114}
115
116
117mod internal {
118
119    use super::{
120        traits::ApproximateEqualityEvaluator,
121        utils::{
122            compare_approximate_equality_by_margin,
123            compare_approximate_equality_by_multiplier,
124            compare_approximate_equality_by_zero_margin_or_multiplier,
125        },
126        ComparisonResult,
127    };
128
129
130    /// T.B.C.
131    #[derive(Debug)]
132    pub struct MarginEvaluator {
133        pub(crate) factor : f64,
134    }
135
136    /// T.B.C.
137    #[derive(Debug)]
138    pub struct MultiplierEvaluator {
139        pub(crate) factor : f64,
140    }
141
142    /// T.B.C.
143    #[derive(Debug)]
144    pub struct ZeroMarginOrMultiplierEvaluator {
145        pub(crate) multiplier_factor :  f64,
146        pub(crate) zero_margin_factor : f64,
147    }
148
149    // Trait implementations
150
151    impl ApproximateEqualityEvaluator for MarginEvaluator {
152        fn evaluate(
153            &self,
154            expected : f64,
155            actual : f64,
156        ) -> (
157            ComparisonResult, // comparison_result
158            Option<f64>,      // margin_factor
159            Option<f64>,      // multiplier_factor
160        ) {
161            let comparison_result = compare_approximate_equality_by_margin(expected, actual, self.factor);
162
163            (comparison_result, Some(self.factor), None)
164        }
165    }
166
167    impl ApproximateEqualityEvaluator for MultiplierEvaluator {
168        fn evaluate(
169            &self,
170            expected : f64,
171            actual : f64,
172        ) -> (
173            ComparisonResult, // comparison_result
174            Option<f64>,      // margin_factor
175            Option<f64>,      // multiplier_factor
176        ) {
177            let comparison_result = compare_approximate_equality_by_multiplier(expected, actual, self.factor);
178
179            (comparison_result, None, Some(self.factor))
180        }
181    }
182
183    impl ApproximateEqualityEvaluator for ZeroMarginOrMultiplierEvaluator {
184        fn evaluate(
185            &self,
186            expected : f64,
187            actual : f64,
188        ) -> (
189            ComparisonResult, // comparison_result
190            Option<f64>,      // margin_factor
191            Option<f64>,      // multiplier_factor
192        ) {
193            let comparison_result = compare_approximate_equality_by_zero_margin_or_multiplier(
194                expected,
195                actual,
196                self.multiplier_factor,
197                self.zero_margin_factor,
198            );
199
200            (
201                comparison_result,
202                Some(self.zero_margin_factor),
203                Some(self.multiplier_factor),
204            )
205        }
206    }
207}
208
209
210mod utils {
211    use super::ComparisonResult;
212
213
214    /// T.B.C.
215    pub(crate) fn compare_approximate_equality_by_margin(
216        expected : f64,
217        actual : f64,
218        margin_factor : f64,
219    ) -> ComparisonResult {
220        debug_assert!(
221            margin_factor >= 0.0,
222            "`margin_factor` must not be negative, but {margin_factor} given"
223        );
224
225        if expected == actual {
226            return ComparisonResult::ExactlyEqual;
227        }
228
229        #[cfg(feature = "nan-equality")]
230        {
231            if expected.is_nan() && actual.is_nan() {
232                return ComparisonResult::ExactlyEqual;
233            }
234        }
235
236        // TODO: determine if can elide this explicit check
237        if 0.0 == margin_factor {
238            return ComparisonResult::Unequal;
239        }
240
241        let expected_lo = expected - margin_factor;
242        let expected_hi = expected + margin_factor;
243
244        result_from_range_(expected_lo, expected_hi, actual)
245    }
246
247    /// T.B.C.
248    pub(crate) fn compare_approximate_equality_by_multiplier(
249        expected : f64,
250        actual : f64,
251        multiplier_factor : f64,
252    ) -> ComparisonResult {
253        debug_assert!(
254            multiplier_factor >= 0.0,
255            "`multiplier_factor` must not be negative, but {multiplier_factor} given"
256        );
257
258        if expected == actual {
259            return ComparisonResult::ExactlyEqual;
260        }
261
262        #[cfg(feature = "nan-equality")]
263        {
264            if expected.is_nan() && actual.is_nan() {
265                return ComparisonResult::ExactlyEqual;
266            }
267        }
268
269        // TODO: determine if can elide this explicit check
270        if 0.0 == multiplier_factor {
271            return ComparisonResult::Unequal;
272        }
273
274        let expected_lo = expected * (1.0 - multiplier_factor);
275        let expected_hi = expected * (1.0 + multiplier_factor);
276
277        result_from_range_(expected_lo, expected_hi, actual)
278    }
279
280    /// T.B.C.
281    pub(crate) fn compare_approximate_equality_by_zero_margin_or_multiplier(
282        expected : f64,
283        actual : f64,
284        multiplier_factor : f64,
285        margin_factor : f64,
286    ) -> ComparisonResult {
287        debug_assert!(
288            multiplier_factor >= 0.0,
289            "`multiplier_factor` must not be negative, but {multiplier_factor} given"
290        );
291        debug_assert!(
292            margin_factor >= 0.0,
293            "`margin_factor` must not be negative, but {margin_factor} given"
294        );
295
296        if expected == actual {
297            return ComparisonResult::ExactlyEqual;
298        }
299
300        #[cfg(feature = "nan-equality")]
301        {
302            if expected.is_nan() && actual.is_nan() {
303                return ComparisonResult::ExactlyEqual;
304            }
305        }
306
307        let (expected_lo, expected_hi) = if 0.0 == expected || 0.0 == actual {
308            // TODO: determine if can elide this explicit check
309            if 0.0 == margin_factor {
310                return ComparisonResult::Unequal;
311            }
312
313            let expected_lo = expected - margin_factor;
314            let expected_hi = expected + margin_factor;
315
316            (expected_lo, expected_hi)
317        } else {
318            // TODO: determine if can elide this explicit check
319            if 0.0 == multiplier_factor {
320                return ComparisonResult::Unequal;
321            }
322
323            let expected_lo = expected * (1.0 - multiplier_factor);
324            let expected_hi = expected * (1.0 + multiplier_factor);
325
326            (expected_lo, expected_hi)
327        };
328
329        result_from_range_(expected_lo, expected_hi, actual)
330    }
331
332    fn result_from_range_(
333        lo : f64,
334        hi : f64,
335        actual : f64,
336    ) -> ComparisonResult {
337        let r = if lo <= hi { lo..=hi } else { hi..=lo };
338
339        if r.contains(&actual) {
340            ComparisonResult::ApproximatelyEqual
341        } else {
342            ComparisonResult::Unequal
343        }
344    }
345
346
347    #[cfg(test)]
348    #[rustfmt::skip]
349    mod tests {
350        #![allow(non_snake_case)]
351
352
353        use super::{
354            compare_approximate_equality_by_margin,
355            compare_approximate_equality_by_multiplier,
356            compare_approximate_equality_by_zero_margin_or_multiplier,
357        };
358
359        use super::super::ComparisonResult;
360
361
362        #[test]
363        fn TEST_compare_approximate_equality_by_margin_1() {
364
365            // expected == actual == 0.0
366            {
367                assert_eq!(ComparisonResult::ExactlyEqual, compare_approximate_equality_by_margin(0.0, 0.0, 0.0));
368                assert_eq!(ComparisonResult::ExactlyEqual, compare_approximate_equality_by_margin(0.0, 0.0, 0.0000001));
369                assert_eq!(ComparisonResult::ExactlyEqual, compare_approximate_equality_by_margin(0.0, 0.0, 0.000001));
370                assert_eq!(ComparisonResult::ExactlyEqual, compare_approximate_equality_by_margin(0.0, 0.0, 0.00001));
371                assert_eq!(ComparisonResult::ExactlyEqual, compare_approximate_equality_by_margin(0.0, 0.0, 0.0001));
372                assert_eq!(ComparisonResult::ExactlyEqual, compare_approximate_equality_by_margin(0.0, 0.0, 0.001));
373                assert_eq!(ComparisonResult::ExactlyEqual, compare_approximate_equality_by_margin(0.0, 0.0, 0.01));
374                assert_eq!(ComparisonResult::ExactlyEqual, compare_approximate_equality_by_margin(0.0, 0.0, 0.1));
375                assert_eq!(ComparisonResult::ExactlyEqual, compare_approximate_equality_by_margin(0.0, 0.0, 0.5));
376            }
377
378            // expected == 0.0, actual == 0.1, f == *
379            {
380                assert_eq!(ComparisonResult::Unequal, compare_approximate_equality_by_margin(0.0, 0.1, 0.0));
381                assert_eq!(ComparisonResult::Unequal, compare_approximate_equality_by_margin(0.0, 0.1, 0.0000001));
382                assert_eq!(ComparisonResult::Unequal, compare_approximate_equality_by_margin(0.0, 0.1, 0.000001));
383                assert_eq!(ComparisonResult::Unequal, compare_approximate_equality_by_margin(0.0, 0.1, 0.00001));
384                assert_eq!(ComparisonResult::Unequal, compare_approximate_equality_by_margin(0.0, 0.1, 0.0001));
385                assert_eq!(ComparisonResult::Unequal, compare_approximate_equality_by_margin(0.0, 0.1, 0.001));
386                assert_eq!(ComparisonResult::Unequal, compare_approximate_equality_by_margin(0.0, 0.1, 0.01));
387                assert_eq!(ComparisonResult::ApproximatelyEqual, compare_approximate_equality_by_margin(0.0, 0.1, 0.1));
388                assert_eq!(ComparisonResult::ApproximatelyEqual, compare_approximate_equality_by_margin(0.0, 0.1, 0.5));
389            }
390
391            // expected == 0.099, actual == 0.1, f == *
392            {
393                assert_eq!(ComparisonResult::Unequal, compare_approximate_equality_by_margin(0.099, 0.1, 0.0));
394                assert_eq!(ComparisonResult::Unequal, compare_approximate_equality_by_margin(0.099, 0.1, 0.0000001));        // expected [ 0.0989999-0.0990001 ]
395                assert_eq!(ComparisonResult::Unequal, compare_approximate_equality_by_margin(0.099, 0.1, 0.000001));         // expected [  0.098999-0.099001  ]
396                assert_eq!(ComparisonResult::Unequal, compare_approximate_equality_by_margin(0.099, 0.1, 0.00001));          // expected [   0.09899-0.09901   ]
397                assert_eq!(ComparisonResult::Unequal, compare_approximate_equality_by_margin(0.099, 0.1, 0.0001));           // expected [    0.0989-0.0991    ]
398                assert_eq!(ComparisonResult::ApproximatelyEqual, compare_approximate_equality_by_margin(0.099, 0.1, 0.001)); // expected [     0.098-0.1       ]
399                assert_eq!(ComparisonResult::ApproximatelyEqual, compare_approximate_equality_by_margin(0.099, 0.1, 0.01));  // expected [     0.089-0.109     ]
400                assert_eq!(ComparisonResult::ApproximatelyEqual, compare_approximate_equality_by_margin(0.099, 0.1, 0.02));  // expected [     0.089-0.119     ]
401            }
402        }
403
404        #[test]
405        fn TEST_compare_approximate_equality_by_multiplier_1() {
406
407            // expected == actual == 0.0
408            {
409                assert_eq!(ComparisonResult::ExactlyEqual, compare_approximate_equality_by_multiplier(0.0, 0.0, 0.0));
410                assert_eq!(ComparisonResult::ExactlyEqual, compare_approximate_equality_by_multiplier(0.0, 0.0, 0.0000001));
411                assert_eq!(ComparisonResult::ExactlyEqual, compare_approximate_equality_by_multiplier(0.0, 0.0, 0.000001));
412                assert_eq!(ComparisonResult::ExactlyEqual, compare_approximate_equality_by_multiplier(0.0, 0.0, 0.00001));
413                assert_eq!(ComparisonResult::ExactlyEqual, compare_approximate_equality_by_multiplier(0.0, 0.0, 0.0001));
414                assert_eq!(ComparisonResult::ExactlyEqual, compare_approximate_equality_by_multiplier(0.0, 0.0, 0.001));
415                assert_eq!(ComparisonResult::ExactlyEqual, compare_approximate_equality_by_multiplier(0.0, 0.0, 0.01));
416                assert_eq!(ComparisonResult::ExactlyEqual, compare_approximate_equality_by_multiplier(0.0, 0.0, 0.1));
417                assert_eq!(ComparisonResult::ExactlyEqual, compare_approximate_equality_by_multiplier(0.0, 0.0, 0.5));
418            }
419
420            // expected == 0.0, actual == 0.1, f == *
421            {
422                assert_eq!(ComparisonResult::Unequal, compare_approximate_equality_by_multiplier(0.0, 0.1, 0.0));
423                assert_eq!(ComparisonResult::Unequal, compare_approximate_equality_by_multiplier(0.0, 0.1, 0.0000001));
424                assert_eq!(ComparisonResult::Unequal, compare_approximate_equality_by_multiplier(0.0, 0.1, 0.000001));
425                assert_eq!(ComparisonResult::Unequal, compare_approximate_equality_by_multiplier(0.0, 0.1, 0.00001));
426                assert_eq!(ComparisonResult::Unequal, compare_approximate_equality_by_multiplier(0.0, 0.1, 0.0001));
427                assert_eq!(ComparisonResult::Unequal, compare_approximate_equality_by_multiplier(0.0, 0.1, 0.001));
428                assert_eq!(ComparisonResult::Unequal, compare_approximate_equality_by_multiplier(0.0, 0.1, 0.01));
429                assert_eq!(ComparisonResult::Unequal, compare_approximate_equality_by_multiplier(0.0, 0.1, 0.1));
430                assert_eq!(ComparisonResult::Unequal, compare_approximate_equality_by_multiplier(0.0, 0.1, 0.5));
431            }
432
433            // expected == 0.099, actual == 0.1, f == *
434            {
435                assert_eq!(ComparisonResult::Unequal, compare_approximate_equality_by_multiplier(0.099, 0.1, 0.0));
436                assert_eq!(ComparisonResult::Unequal, compare_approximate_equality_by_multiplier(0.099, 0.1, 0.0000001)); // expected [ 0.0989999901-0.0990000099 ]
437                assert_eq!(ComparisonResult::Unequal, compare_approximate_equality_by_multiplier(0.099, 0.1, 0.000001));   // expected [  0.098999901-0.099000099  ]
438                assert_eq!(ComparisonResult::Unequal, compare_approximate_equality_by_multiplier(0.099, 0.1, 0.00001));     // expected [   0.09899901-0.09900099   ]
439                assert_eq!(ComparisonResult::Unequal, compare_approximate_equality_by_multiplier(0.099, 0.1, 0.0001));       // expected [    0.0989901-0.0990099    ]
440                assert_eq!(ComparisonResult::Unequal, compare_approximate_equality_by_multiplier(0.099, 0.1, 0.001));         // expected [     0.098901-0.099099     ]
441                assert_eq!(ComparisonResult::Unequal, compare_approximate_equality_by_multiplier(0.099, 0.1, 0.01));           // expected [      0.09801-0.09999      ]
442                assert_eq!(ComparisonResult::ApproximatelyEqual, compare_approximate_equality_by_multiplier(0.099, 0.1, 0.1));  // expected [       0.0891-0.1089       ]
443                assert_eq!(ComparisonResult::ApproximatelyEqual, compare_approximate_equality_by_multiplier(0.099, 0.1, 0.5));  // expected [       0.0495-0.1485       ]
444            }
445        }
446
447        #[test]
448        fn TEST_compare_approximate_equality_by_zero_margin_or_multiplier_1() {
449
450            // expected == actual == 0.0
451            {
452                assert_eq!(ComparisonResult::ExactlyEqual, compare_approximate_equality_by_zero_margin_or_multiplier(0.0, 0.0, 0.0, 0.0));
453                assert_eq!(ComparisonResult::ExactlyEqual, compare_approximate_equality_by_zero_margin_or_multiplier(0.0, 0.0, 0.0000001, 0.0000001));
454                assert_eq!(ComparisonResult::ExactlyEqual, compare_approximate_equality_by_zero_margin_or_multiplier(0.0, 0.0, 0.000001, 0.000001));
455                assert_eq!(ComparisonResult::ExactlyEqual, compare_approximate_equality_by_zero_margin_or_multiplier(0.0, 0.0, 0.00001, 0.00001));
456                assert_eq!(ComparisonResult::ExactlyEqual, compare_approximate_equality_by_zero_margin_or_multiplier(0.0, 0.0, 0.0001, 0.0001));
457                assert_eq!(ComparisonResult::ExactlyEqual, compare_approximate_equality_by_zero_margin_or_multiplier(0.0, 0.0, 0.001, 0.001));
458                assert_eq!(ComparisonResult::ExactlyEqual, compare_approximate_equality_by_zero_margin_or_multiplier(0.0, 0.0, 0.01, 0.01));
459                assert_eq!(ComparisonResult::ExactlyEqual, compare_approximate_equality_by_zero_margin_or_multiplier(0.0, 0.0, 0.1, 0.1));
460                assert_eq!(ComparisonResult::ExactlyEqual, compare_approximate_equality_by_zero_margin_or_multiplier(0.0, 0.0, 0.5, 0.5));
461            }
462
463            // expected == 0.0, actual == 0.1, f == *
464            {
465                assert_eq!(ComparisonResult::Unequal, compare_approximate_equality_by_zero_margin_or_multiplier(0.0, 0.1, 0.0, 0.0));
466                assert_eq!(ComparisonResult::Unequal, compare_approximate_equality_by_zero_margin_or_multiplier(0.0, 0.1, 0.0000001, 0.0000001));
467                assert_eq!(ComparisonResult::Unequal, compare_approximate_equality_by_zero_margin_or_multiplier(0.0, 0.1, 0.000001, 0.000001));
468                assert_eq!(ComparisonResult::Unequal, compare_approximate_equality_by_zero_margin_or_multiplier(0.0, 0.1, 0.00001, 0.00001));
469                assert_eq!(ComparisonResult::Unequal, compare_approximate_equality_by_zero_margin_or_multiplier(0.0, 0.1, 0.0001, 0.0001));
470                assert_eq!(ComparisonResult::Unequal, compare_approximate_equality_by_zero_margin_or_multiplier(0.0, 0.1, 0.001, 0.001));
471                assert_eq!(ComparisonResult::Unequal, compare_approximate_equality_by_zero_margin_or_multiplier(0.0, 0.1, 0.01, 0.01));
472                assert_eq!(ComparisonResult::ApproximatelyEqual, compare_approximate_equality_by_zero_margin_or_multiplier(0.0, 0.1, 0.1, 0.1));
473                assert_eq!(ComparisonResult::ApproximatelyEqual, compare_approximate_equality_by_zero_margin_or_multiplier(0.0, 0.1, 0.5, 0.5));
474            }
475
476            // expected == 0.099, actual == 0.1, f == *
477            {
478                assert_eq!(ComparisonResult::Unequal, compare_approximate_equality_by_zero_margin_or_multiplier(0.099, 0.1, 0.0, 0.0));
479                assert_eq!(ComparisonResult::Unequal, compare_approximate_equality_by_zero_margin_or_multiplier(0.099, 0.1, 0.0000001, 0.0000001)); // expected [ 0.0989999901-0.0990000099 ]
480                assert_eq!(ComparisonResult::Unequal, compare_approximate_equality_by_zero_margin_or_multiplier(0.099, 0.1, 0.000001, 0.000001));     // expected [  0.098999901-0.099000099  ]
481                assert_eq!(ComparisonResult::Unequal, compare_approximate_equality_by_zero_margin_or_multiplier(0.099, 0.1, 0.00001, 0.00001));         // expected [   0.09899901-0.09900099   ]
482                assert_eq!(ComparisonResult::Unequal, compare_approximate_equality_by_zero_margin_or_multiplier(0.099, 0.1, 0.0001, 0.0001));             // expected [    0.0989901-0.0990099    ]
483                assert_eq!(ComparisonResult::Unequal, compare_approximate_equality_by_zero_margin_or_multiplier(0.099, 0.1, 0.001, 0.001));                 // expected [     0.098901-0.099099     ]
484                assert_eq!(ComparisonResult::Unequal, compare_approximate_equality_by_zero_margin_or_multiplier(0.099, 0.1, 0.01, 0.01));                     // expected [      0.09801-0.09999      ]
485                assert_eq!(ComparisonResult::ApproximatelyEqual, compare_approximate_equality_by_zero_margin_or_multiplier(0.099, 0.1, 0.1, 0.1));              // expected [       0.0891-0.1089       ]
486                assert_eq!(ComparisonResult::ApproximatelyEqual, compare_approximate_equality_by_zero_margin_or_multiplier(0.099, 0.1, 0.5, 0.5));              // expected [       0.0495-0.1485       ]
487            }
488        }
489    }
490}
491
492
493// /////////////////////////////////////////////////////////
494// API functions
495
496pub fn evaluate_scalar_eq_approx<T_expected, T_actual>(
497    expected : &T_expected,
498    actual : &T_actual,
499    evaluator : &dyn traits::ApproximateEqualityEvaluator,
500) -> (
501    ComparisonResult, // comparison_result
502    Option<f64>,      // margin_factor
503    Option<f64>,      // multiplier_factor
504)
505where
506    T_expected : traits::TestableAsF64 + std_fmt::Debug,
507    T_actual : traits::TestableAsF64 + std_fmt::Debug,
508{
509    let (expected, actual) = {
510        let expected : &dyn traits::TestableAsF64 = expected;
511        let actual : &dyn traits::TestableAsF64 = actual;
512
513        let expected = expected.testable_as_f64();
514        let actual = actual.testable_as_f64();
515
516        (expected, actual)
517    };
518
519    evaluator.evaluate(expected, actual)
520}
521
522pub fn evaluate_vector_eq_approx<T_expected, T_actual, T_expectedElement, T_actualElement>(
523    expected : &T_expected,
524    actual : &T_actual,
525    evaluator : &dyn traits::ApproximateEqualityEvaluator,
526) -> (
527    VectorComparisonResult, // comparison_result
528    Option<f64>,            // margin_factor
529    Option<f64>,            // multiplier_factor
530)
531where
532    T_expected : std_convert::AsRef<[T_expectedElement]>,
533    T_actual : std_convert::AsRef<[T_actualElement]>,
534    T_expectedElement : traits::TestableAsF64 + std_fmt::Debug,
535    T_actualElement : traits::TestableAsF64 + std_fmt::Debug,
536{
537    /*
538    let expected_param = expected;
539    let actual_param = actual;
540     */
541
542    let expected = expected.as_ref();
543    let actual = actual.as_ref();
544
545    let expected_length = expected.len();
546    let actual_length = actual.len();
547
548    if expected_length != actual_length {
549        (
550            VectorComparisonResult::DifferentLengths {
551                expected_length,
552                actual_length,
553            },
554            None,
555            None,
556        )
557    } else {
558        let mut any_inexact = false;
559        let mut margin_factor = None;
560        let mut multiplier_factor = None;
561
562        for ix in 0..expected_length {
563            let expected_element = &expected[ix];
564            let actual_element = &actual[ix];
565
566            let (scalar_comparison_result, scalar_margin_factor, scalar_multiplier_factor) =
567                evaluate_scalar_eq_approx(expected_element, actual_element, evaluator);
568
569            match scalar_comparison_result {
570                ComparisonResult::ExactlyEqual => (),
571                ComparisonResult::ApproximatelyEqual => {
572                    if !any_inexact {
573                        any_inexact = true;
574                        margin_factor = scalar_margin_factor;
575                        multiplier_factor = scalar_multiplier_factor;
576                    }
577                },
578                ComparisonResult::Unequal => {
579                    let (expected_value_of_first_unequal_element, actual_value_of_first_unequal_element) = {
580                        let expected : &dyn traits::TestableAsF64 = &expected[ix];
581                        let actual : &dyn traits::TestableAsF64 = &actual[ix];
582
583                        let expected = expected.testable_as_f64();
584                        let actual = actual.testable_as_f64();
585
586                        (expected, actual)
587                    };
588
589                    return (
590                        VectorComparisonResult::UnequalElements {
591                            index_of_first_unequal_element : ix,
592                            expected_value_of_first_unequal_element,
593                            actual_value_of_first_unequal_element,
594                        },
595                        scalar_margin_factor,
596                        scalar_multiplier_factor,
597                    );
598                },
599            };
600        }
601
602        (
603            if any_inexact {
604                VectorComparisonResult::ApproximatelyEqual
605            } else {
606                VectorComparisonResult::ExactlyEqual
607            },
608            margin_factor,
609            multiplier_factor,
610        )
611    }
612}
613
614/// Creates an [`ApproximateEqualityEvaluator`] that operates by applying
615/// the given `factor` as a margin to determine approximate equality.
616pub fn margin(factor : f64) -> impl traits::ApproximateEqualityEvaluator {
617    internal::MarginEvaluator {
618        factor,
619    }
620}
621
622/// Creates an [`ApproximateEqualityEvaluator`] that operates by applying
623/// the given `factor` as a multiplier to determine approximate equality.
624pub fn multiplier(factor : f64) -> impl traits::ApproximateEqualityEvaluator {
625    internal::MultiplierEvaluator {
626        factor,
627    }
628}
629
630/// Creates an [`ApproximateEqualityEvaluator`] that operates by applying
631/// the given `multiplier_factor` as a multiplier to determine approximate
632/// equality in all cases except when or both comparands is zero, in which
633/// case it applies the `zero_margin_factor` as a margin to determine
634/// approximate equality.
635pub fn zero_margin_or_multiplier(
636    multiplier_factor : f64,
637    zero_margin_factor : f64,
638) -> impl traits::ApproximateEqualityEvaluator {
639    internal::ZeroMarginOrMultiplierEvaluator {
640        multiplier_factor,
641        zero_margin_factor,
642    }
643}
644
645
646// /////////////////////////////////////////////////////////
647// macros
648
649#[macro_export]
650macro_rules! assert_scalar_eq_approx {
651    ($expected:expr, $actual:expr, $evaluator:expr) => {
652        let expected_param = &$expected;
653        let actual_param = &$actual;
654
655        let (expected, actual) = {
656            let expected : &dyn $crate::traits::TestableAsF64 = expected_param;
657            let actual : &dyn $crate::traits::TestableAsF64 = actual_param;
658
659            let expected = expected.testable_as_f64();
660            let actual = actual.testable_as_f64();
661
662            (expected, actual)
663        };
664        let evaluator : &dyn $crate::traits::ApproximateEqualityEvaluator = &$evaluator;
665
666        // scope to protect against multiple `use`s of crate type(s)
667        {
668            use $crate::ComparisonResult as CR;
669
670            let (comparison_result, margin_factor, multiplier_factor) = evaluator.evaluate(expected, actual);
671
672            match comparison_result {
673                CR::ExactlyEqual | CR::ApproximatelyEqual => (),
674                CR::Unequal => {
675                    match margin_factor {
676                        Some(margin_factor) => {
677                            match multiplier_factor {
678                                Some(multiplier_factor) => {
679                                    assert!(
680                                        false,
681                                        "assertion failed: failed to verify approximate equality: expected={expected_param:?}, actual={actual_param:?}, margin_factor={margin_factor}, multiplier_factor={multiplier_factor}",
682                                    );
683                                },
684                                None => {
685                                    assert!(
686                                        false,
687                                        "assertion failed: failed to verify approximate equality: expected={expected_param:?}, actual={actual_param:?}, margin_factor={margin_factor}",
688                                    );
689                                },
690                            };
691                        },
692                        None => {
693                            match multiplier_factor {
694                                Some(multiplier_factor) => {
695                                    assert!(
696                                        false,
697                                        "assertion failed: failed to verify approximate equality: expected={expected_param:?}, actual={actual_param:?}, multiplier_factor={multiplier_factor}",
698                                    );
699                                },
700                                None => {
701                                    panic!("VIOLATION: This should not occur, and may only result from an improperly written implementor of `ApproximateEqualityEvaluator`");
702                                }
703                            };
704                        },
705                    };
706                },
707            };
708        }
709    };
710    ($expected:expr, $actual:expr) => {
711        let evaluator = $crate::zero_margin_or_multiplier($crate::constants::DEFAULT_MULTIPLIER, $crate::constants::DEFAULT_MARGIN);
712
713        assert_scalar_eq_approx!($expected, $actual, evaluator);
714    };
715}
716
717#[macro_export]
718macro_rules! assert_scalar_ne_approx {
719    ($expected:expr, $actual:expr, $evaluator:expr) => {
720        let expected_param = &$expected;
721        let actual_param = &$actual;
722
723        let (expected, actual) = {
724            let expected : &dyn $crate::traits::TestableAsF64 = expected_param;
725            let actual : &dyn $crate::traits::TestableAsF64 = actual_param;
726
727            let expected = expected.testable_as_f64();
728            let actual = actual.testable_as_f64();
729
730            (expected, actual)
731        };
732        let evaluator : &dyn $crate::traits::ApproximateEqualityEvaluator = &$evaluator;
733
734        // scope to protect against multiple `use`s of crate type(s)
735        {
736            use $crate::ComparisonResult as CR;
737
738            let (comparison_result, margin_factor, multiplier_factor) = evaluator.evaluate(expected, actual);
739
740            match comparison_result {
741                CR::Unequal => (),
742                CR::ExactlyEqual | CR::ApproximatelyEqual => {
743                    match margin_factor {
744                        Some(margin_factor) => {
745                            match multiplier_factor {
746                                Some(multiplier_factor) => {
747                                    assert!(
748                                        false,
749                                        "assertion failed: failed to verify approximate inequality: expected={expected_param:?}, actual={actual_param:?}, margin_factor={margin_factor}, multiplier_factor={multiplier_factor}",
750                                    );
751                                },
752                                None => {
753                                    assert!(
754                                        false,
755                                        "assertion failed: failed to verify approximate inequality: expected={expected_param:?}, actual={actual_param:?}, margin_factor={margin_factor}",
756                                    );
757                                },
758                            };
759                        },
760                        None => {
761                            match multiplier_factor {
762                                Some(multiplier_factor) => {
763                                    assert!(
764                                        false,
765                                        "assertion failed: failed to verify approximate inequality: expected={expected_param:?}, actual={actual_param:?}, multiplier_factor={multiplier_factor}",
766                                    );
767                                },
768                                None => {
769                                    panic!("VIOLATION: This should not occur, and may only result from an improperly written implementor of `ApproximateEqualityEvaluator`");
770                                }
771                            };
772                        }
773                    };
774                },
775            };
776        }
777    };
778    ($expected:expr, $actual:expr) => {
779        let evaluator = $crate::zero_margin_or_multiplier($crate::constants::DEFAULT_MULTIPLIER, $crate::constants::DEFAULT_MARGIN);
780
781        assert_scalar_ne_approx!($expected, $actual, evaluator);
782    };
783}
784
785#[macro_export]
786macro_rules! assert_vector_eq_approx {
787    ($expected:expr, $actual:expr, $evaluator:expr) => {
788        /*
789        let expected_param = &$expected;
790        let actual_param = &$actual;
791         */
792        let expected = &$expected;
793        let actual = &$actual;
794        let evaluator : &dyn $crate::traits::ApproximateEqualityEvaluator = &$evaluator;
795
796        // scope to protect against multiple `use`s of crate type(s)
797        {
798            use $crate::VectorComparisonResult as CR;
799
800            let (comparison_result, margin_factor, multiplier_factor) = $crate::evaluate_vector_eq_approx(&expected, &actual, evaluator);
801
802            match comparison_result {
803                CR::ExactlyEqual | CR::ApproximatelyEqual => (),
804                CR::DifferentLengths {
805                    expected_length,
806                    actual_length,
807                } => {
808                    assert!(
809                        false,
810                        "assertion failed: failed to verify approximate equality for vectors: expected-length {expected_length} differs from actual-length {actual_length}",
811                    );
812                },
813                CR::UnequalElements {
814                    index_of_first_unequal_element,
815                    expected_value_of_first_unequal_element,
816                    actual_value_of_first_unequal_element,
817                } => {
818                    match margin_factor {
819                        Some(margin_factor) => {
820                            match multiplier_factor {
821                                Some(multiplier_factor) => {
822                                    assert!(
823                                        false,
824                                        "assertion failed: failed to verify approximate equality for vectors: at index {index_of_first_unequal_element} expected={expected_value_of_first_unequal_element:?}, actual={actual_value_of_first_unequal_element:?}, margin_factor={margin_factor}, multiplier_factor={multiplier_factor}",
825                                    );
826                                },
827                                None => {
828                                    assert!(
829                                        false,
830                                        "assertion failed: failed to verify approximate equality for vectors: at index {index_of_first_unequal_element} expected={expected_value_of_first_unequal_element:?}, actual={actual_value_of_first_unequal_element:?}, margin_factor={margin_factor}",
831                                    );
832                                },
833                            };
834                        },
835                        None => {
836                            match multiplier_factor {
837                                Some(multiplier_factor) => {
838                                    assert!(
839                                        false,
840                                        "assertion failed: failed to verify approximate equality for vectors: at index {index_of_first_unequal_element} expected={expected_value_of_first_unequal_element:?}, actual={actual_value_of_first_unequal_element:?}, multiplier_factor={multiplier_factor}",
841                                    );
842                                },
843                                None => {
844                                    panic!("VIOLATION: This should not occur, and may only result from an improperly written implementor of `ApproximateEqualityEvaluator`");
845                                }
846                            };
847                        },
848                    };
849                },
850            };
851        }
852    };
853    ($expected:expr, $actual:expr) => {
854        let evaluator = $crate::zero_margin_or_multiplier($crate::constants::DEFAULT_MULTIPLIER, $crate::constants::DEFAULT_MARGIN);
855
856        assert_vector_eq_approx!($expected, $actual, evaluator);
857    };
858}
859
860#[macro_export]
861macro_rules! assert_vector_ne_approx {
862    ($expected:expr, $actual:expr, $evaluator:expr) => {
863        /*
864        let expected_param = &$expected;
865        let actual_param = &$actual;
866         */
867        let expected = &$expected;
868        let actual = &$actual;
869        let evaluator : &dyn $crate::traits::ApproximateEqualityEvaluator = &$evaluator;
870
871        // scope to protect against multiple `use`s of crate type(s)
872        {
873            use $crate::VectorComparisonResult as CR;
874
875            let (comparison_result, margin_factor, multiplier_factor) = $crate::evaluate_vector_eq_approx(&expected, &actual, evaluator);
876
877            match comparison_result {
878                CR::DifferentLengths { ..} | CR::UnequalElements {..} => (),
879                CR::ExactlyEqual | CR::ApproximatelyEqual => {
880                    match margin_factor {
881                        Some(margin_factor) => {
882                            match multiplier_factor {
883                                Some(multiplier_factor) => {
884                                    assert!(
885                                        false,
886                                        "assertion failed: failed to verify approximate inequality for vectors; margin_factor={margin_factor},  multiplier_factor={multiplier_factor}",
887                                    );
888                                },
889                                None => {
890                                    assert!(
891                                        false,
892                                        "assertion failed: failed to verify approximate inequality for vectors; margin_factor={margin_factor}",
893                                    );
894                                },
895                            };
896                        },
897                        None => {
898                            match multiplier_factor {
899                                Some(multiplier_factor) => {
900                                    assert!(
901                                        false,
902                                        "assertion failed: failed to verify approximate inequality for vectors; multiplier_factor={multiplier_factor}",
903                                    );
904                                },
905                                None => {
906                                    assert!(
907                                        false,
908                                        "assertion failed: failed to verify approximate inequality for vectors",
909                                    );
910                                }
911                            };
912                        }
913                    };
914                },
915            };
916        }
917    };
918    ($expected:expr, $actual:expr) => {
919        let evaluator =
920            $crate::zero_margin_or_multiplier($crate::constants::DEFAULT_MULTIPLIER, $crate::constants::DEFAULT_MARGIN);
921
922        assert_vector_ne_approx!($expected, $actual, evaluator);
923    };
924}
925
926
927#[cfg(test)]
928#[rustfmt::skip]
929mod tests {
930    #![allow(non_snake_case)]
931
932    use crate as test_helpers;
933
934    use test_helpers::{
935        traits::ApproximateEqualityEvaluator,
936        ComparisonResult,
937        margin,
938        multiplier,
939        zero_margin_or_multiplier,
940    };
941
942    use std::rc as std_rc;
943
944
945    mod TEST_margin {
946        #![allow(non_snake_case)]
947
948        use super::*;
949
950
951        #[test]
952        fn TEST_margin_TEST_1() {
953            let margin_factor = 0.0;
954            let m = margin(margin_factor);
955
956            assert_eq!(ComparisonResult::ExactlyEqual, m.evaluate(0.0, 0.0).0);
957
958            assert_eq!(ComparisonResult::Unequal, m.evaluate(0.000001, 0.0).0);
959            assert_eq!(ComparisonResult::Unequal, m.evaluate(0.00001, 0.0).0);
960            assert_eq!(ComparisonResult::Unequal, m.evaluate(0.0001, 0.0).0);
961            assert_eq!(ComparisonResult::Unequal, m.evaluate(0.001, 0.0).0);
962            assert_eq!(ComparisonResult::Unequal, m.evaluate(0.01, 0.0).0);
963            assert_eq!(ComparisonResult::Unequal, m.evaluate(0.1, 0.0).0);
964        }
965
966        #[test]
967        fn TEST_margin_TEST_2() {
968            let margin_factor = 0.001;
969            let m = margin(margin_factor);
970
971            assert_eq!(ComparisonResult::ExactlyEqual, m.evaluate(0.0, 0.0).0);
972
973            assert_eq!(ComparisonResult::ApproximatelyEqual, m.evaluate(0.000001, 0.0).0);
974            assert_eq!(ComparisonResult::ApproximatelyEqual, m.evaluate(0.00001, 0.0).0);
975            assert_eq!(ComparisonResult::ApproximatelyEqual, m.evaluate(0.0001, 0.0).0);
976            assert_eq!(ComparisonResult::ApproximatelyEqual, m.evaluate(0.001, 0.0).0);
977            assert_eq!(ComparisonResult::Unequal, m.evaluate(0.0010001, 0.0).0);
978            assert_eq!(ComparisonResult::Unequal, m.evaluate(0.001001, 0.0).0);
979            assert_eq!(ComparisonResult::Unequal, m.evaluate(0.00101, 0.0).0);
980            assert_eq!(ComparisonResult::Unequal, m.evaluate(0.0011, 0.0).0);
981            assert_eq!(ComparisonResult::Unequal, m.evaluate(0.01, 0.0).0);
982            assert_eq!(ComparisonResult::Unequal, m.evaluate(0.1, 0.0).0);
983        }
984    }
985
986
987    mod TEST_multiplier {
988        #![allow(non_snake_case)]
989
990        use super::*;
991
992
993        #[test]
994        fn TEST_multiplier_TEST_1() {
995            let multiplier_factor = 0.0;
996            let m = multiplier(multiplier_factor);
997
998            assert_eq!(ComparisonResult::ExactlyEqual, m.evaluate(0.0, 0.0).0);
999
1000            assert_eq!(ComparisonResult::Unequal, m.evaluate(0.000001, 0.0).0);
1001            assert_eq!(ComparisonResult::Unequal, m.evaluate(0.00001, 0.0).0);
1002            assert_eq!(ComparisonResult::Unequal, m.evaluate(0.0001, 0.0).0);
1003            assert_eq!(ComparisonResult::Unequal, m.evaluate(0.001, 0.0).0);
1004            assert_eq!(ComparisonResult::Unequal, m.evaluate(0.01, 0.0).0);
1005            assert_eq!(ComparisonResult::Unequal, m.evaluate(0.1, 0.0).0);
1006        }
1007
1008        #[test]
1009        fn TEST_multiplier_TEST_2() {
1010            let multiplier_factor = 0.001;
1011            let m = multiplier(multiplier_factor);
1012
1013            assert_eq!(ComparisonResult::ExactlyEqual, m.evaluate(0.0, 0.0).0);
1014
1015            assert_eq!(ComparisonResult::ExactlyEqual, m.evaluate(1.0, 1.0).0);
1016            assert_eq!(ComparisonResult::ApproximatelyEqual, m.evaluate(1.000001, 1.0).0);
1017            assert_eq!(ComparisonResult::ApproximatelyEqual, m.evaluate(1.00001, 1.0).0);
1018            assert_eq!(ComparisonResult::ApproximatelyEqual, m.evaluate(1.0001, 1.0).0);
1019            assert_eq!(ComparisonResult::ApproximatelyEqual, m.evaluate(1.001, 1.0).0);
1020            assert_eq!(ComparisonResult::Unequal, m.evaluate(0.0010001, 0.0).0);
1021            assert_eq!(ComparisonResult::Unequal, m.evaluate(0.001001, 0.0).0);
1022            assert_eq!(ComparisonResult::Unequal, m.evaluate(0.00101, 0.0).0);
1023            assert_eq!(ComparisonResult::Unequal, m.evaluate(0.0011, 0.0).0);
1024            assert_eq!(ComparisonResult::Unequal, m.evaluate(0.01, 0.0).0);
1025            assert_eq!(ComparisonResult::Unequal, m.evaluate(0.1, 0.0).0);
1026        }
1027    }
1028
1029
1030    mod TEST_SCALAR_ASSERTS {
1031        #![allow(non_snake_case)]
1032
1033        use super::*;
1034
1035
1036        struct CustomEvaluator{}
1037
1038        impl ApproximateEqualityEvaluator for CustomEvaluator {
1039            fn evaluate(
1040                &self,
1041                expected : f64,
1042                actual : f64,
1043            ) -> (
1044                ComparisonResult, // comparison_result
1045                Option<f64>,      // margin_factor
1046                Option<f64>,      // multiplier_factor
1047            )
1048            {
1049                (
1050                    if expected == actual {
1051                        ComparisonResult::ExactlyEqual
1052                    } else {
1053                        ComparisonResult::Unequal
1054                    },
1055                    Some(0.0),
1056                    Some(0.0),
1057                )
1058            }
1059        }
1060
1061
1062        #[test]
1063        fn TEST_assert_scalar_eq_approx_2_PARAMETER_FOR_EXACTLY_EQUAL_VALUES() {
1064
1065            assert_scalar_eq_approx!(-1.23456789e-10, -1.23456789e-10);
1066            assert_scalar_eq_approx!(-0.123456789, -0.123456789);
1067            assert_scalar_eq_approx!(-0.1, -0.1);
1068            assert_scalar_eq_approx!(0.0, 0.0);
1069            assert_scalar_eq_approx!(0.1, 0.1);
1070            assert_scalar_eq_approx!(0.123456789, 0.123456789);
1071            assert_scalar_eq_approx!(1.23456789e+10, 1.23456789e+10);
1072
1073            assert_scalar_eq_approx!(f64::INFINITY, f64::INFINITY);
1074            assert_scalar_eq_approx!(f64::NEG_INFINITY, f64::NEG_INFINITY);
1075
1076            assert_scalar_eq_approx!(f64::MIN, f64::MIN);
1077            assert_scalar_eq_approx!(f64::MIN_POSITIVE, f64::MIN_POSITIVE);
1078            assert_scalar_eq_approx!(f64::MAX, f64::MAX);
1079
1080            #[cfg(feature = "nan-equality")]
1081            {
1082                assert_scalar_eq_approx!(f64::NAN, f64::NAN);
1083            }
1084            #[cfg(not(feature = "nan-equality"))]
1085            {
1086                assert_scalar_ne_approx!(f64::NAN, f64::NAN);
1087            }
1088
1089            {
1090                use std::f64::consts::*;
1091
1092                assert_scalar_eq_approx!(PI, PI);
1093                assert_scalar_eq_approx!(TAU, TAU);
1094                assert_scalar_eq_approx!(PHI, PHI);
1095                assert_scalar_eq_approx!(EGAMMA, EGAMMA);
1096                assert_scalar_eq_approx!(FRAC_PI_2, FRAC_PI_2);
1097                assert_scalar_eq_approx!(FRAC_PI_3, FRAC_PI_3);
1098                assert_scalar_eq_approx!(FRAC_PI_4, FRAC_PI_4);
1099                assert_scalar_eq_approx!(FRAC_PI_6, FRAC_PI_6);
1100                assert_scalar_eq_approx!(FRAC_PI_8, FRAC_PI_8);
1101                assert_scalar_eq_approx!(FRAC_1_PI, FRAC_1_PI);
1102                assert_scalar_eq_approx!(FRAC_1_SQRT_PI, FRAC_1_SQRT_PI);
1103                assert_scalar_eq_approx!(FRAC_1_SQRT_2PI, FRAC_1_SQRT_2PI);
1104                assert_scalar_eq_approx!(FRAC_2_PI, FRAC_2_PI);
1105                assert_scalar_eq_approx!(FRAC_2_SQRT_PI, FRAC_2_SQRT_PI);
1106                assert_scalar_eq_approx!(SQRT_2, SQRT_2);
1107                assert_scalar_eq_approx!(FRAC_1_SQRT_2, FRAC_1_SQRT_2);
1108                assert_scalar_eq_approx!(SQRT_3, SQRT_3);
1109                assert_scalar_eq_approx!(FRAC_1_SQRT_3, FRAC_1_SQRT_3);
1110                assert_scalar_eq_approx!(E, E);
1111                assert_scalar_eq_approx!(LOG2_10, LOG2_10);
1112                assert_scalar_eq_approx!(LOG2_E, LOG2_E);
1113                assert_scalar_eq_approx!(LOG10_2, LOG10_2);
1114                assert_scalar_eq_approx!(LOG10_E, LOG10_E);
1115                assert_scalar_eq_approx!(LN_2, LN_2);
1116                assert_scalar_eq_approx!(LN_10, LN_10);
1117            }
1118        }
1119
1120        #[test]
1121        #[cfg_attr(not(feature = "nan-equality"), should_panic(expected = "assertion failed: failed to verify approximate equality: expected=NaN, actual=NaN, margin_factor=0.0001, multiplier_factor=0.000001"))]
1122        fn TEST_assert_scalar_eq_approx_2_PARAMETER_WITH_NAN() {
1123
1124            assert_scalar_eq_approx!(f64::NAN, f64::NAN);
1125        }
1126        #[test]
1127        #[cfg_attr(feature = "nan-equality", should_panic(expected = "assertion failed: failed to verify approximate inequality: expected=NaN, actual=NaN, margin_factor=0.0001, multiplier_factor=0.000001"))]
1128        fn TEST_assert_scalar_ne_approx_2_PARAMETER_WITH_NAN() {
1129
1130            assert_scalar_ne_approx!(f64::NAN, f64::NAN);
1131        }
1132
1133        /// Demonstrate that feature `"nan-equality"` only changes stock behaviour
1134        #[test]
1135        fn TEST_assert_scalar_ne_approx_3_PARAMETER_WITH_CustomEvaluator() {
1136
1137            assert_scalar_ne_approx!(f64::NAN, f64::NAN, CustomEvaluator{});
1138        }
1139
1140        #[test]
1141        fn TEST_assert_scalar_eq_approx_2_PARAMETER_FOR_APPROXIMATELY_EQUAL_VALUES() {
1142
1143            assert_scalar_eq_approx!(0.12345678, 0.12345679);
1144            assert_scalar_eq_approx!(0.12345678, 0.12345677);
1145        }
1146
1147        #[test]
1148        fn TEST_assert_scalar_eq_approx_3_PARAMETER_margin_FOR_APPROXIMATELY_EQUAL_VALUES() {
1149            assert_scalar_eq_approx!(0.12345678, 0.12345679, margin(0.1));
1150            assert_scalar_eq_approx!(0.12345678, 0.12345679, margin(0.01));
1151            assert_scalar_eq_approx!(0.12345678, 0.12345679, margin(0.001));
1152            assert_scalar_eq_approx!(0.12345678, 0.12345679, margin(0.0001));
1153            assert_scalar_eq_approx!(0.12345678, 0.12345679, margin(0.00001));
1154            assert_scalar_eq_approx!(0.12345678, Box::new(0.12345679), margin(0.000001));
1155            assert_scalar_eq_approx!(std_rc::Rc::new(0.123456780), 0.12345679, margin(0.0000001));
1156            assert_scalar_eq_approx!(0.12345678, 0.12345679, margin(0.00000001));
1157        }
1158
1159        #[test]
1160        #[should_panic(expected = "assertion failed: failed to verify approximate equality: expected=0.12345678, actual=0.12345679, margin_factor=0.000000001")]
1161        fn TEST_assert_scalar_eq_approx_3_PARAMETER_margin_SHOULD_FAIL_1() {
1162            assert_scalar_eq_approx!(0.12345678, 0.12345679, margin(0.000000001));
1163        }
1164
1165        #[test]
1166        #[should_panic(expected = "assertion failed: failed to verify approximate inequality: expected=0.12345678, actual=0.12345678, margin_factor=0.0001, multiplier_factor=0.000001")]
1167        fn TEST_assert_scalar_ne_approx_2_PARAMETER_FOR_APPROXIMATELY_EQUAL_VALUES_SHOULD_FAIL_1() {
1168
1169            assert_scalar_ne_approx!(0.12345678, 0.12345678);
1170        }
1171    }
1172
1173
1174    mod TEST_VECTOR_ASSERTS {
1175        #![allow(non_snake_case)]
1176
1177        use super::*;
1178
1179
1180        #[test]
1181        fn TEST_assert_vector_eq_approx_2_PARAMETER_EMPTY_ARRAY_INSTANCES() {
1182            let expected : [f64; 0] = [];
1183            let actual : [f64; 0] = [];
1184
1185            assert_vector_eq_approx!(expected, actual);
1186        }
1187
1188        #[test]
1189        #[should_panic(expected = "assertion failed: failed to verify approximate inequality for vectors")]
1190        fn TEST_assert_vector_ne_approx_2_PARAMETER_EMPTY_ARRAY_INSTANCES() {
1191            let expected : [f64; 0] = [];
1192            let actual : [f64; 0] = [];
1193
1194            assert_vector_ne_approx!(expected, actual);
1195        }
1196
1197        #[test]
1198        fn TEST_assert_vector_eq_approx_3_PARAMETER_EMPTY_SLICE_INSTANCES() {
1199            let expected : &[f64] = &[];
1200            let actual : &[f64] = &[];
1201
1202            assert_vector_eq_approx!(expected, actual, margin(0.0001));
1203        }
1204
1205        #[test]
1206        fn TEST_assert_vector_eq_approx_2_PARAMETER_EMPTY_Vec_INSTANCES() {
1207            let expected : Vec<f64> = Vec::new();
1208            let actual : Vec<f64> = Vec::new();
1209
1210            assert_vector_eq_approx!(expected, actual);
1211        }
1212
1213        #[test]
1214        #[should_panic(expected = "assertion failed: failed to verify approximate equality for vectors: expected-length 2 differs from actual-length 1")]
1215        fn TEST_assert_vector_eq_approx_2_PARAMETER_SLICE_INSTANCES_DIFFERENT_LENGTHS() {
1216            let expected : &[f64] = &[ -2.0, -3.0 ];
1217            let actual : &[f64] = &[ 0.0 ];
1218
1219            assert_vector_eq_approx!(expected, actual);
1220        }
1221
1222        #[test]
1223        #[should_panic(expected = "assertion failed: failed to verify approximate equality for vectors: at index 1 expected=-3.0, actual=-3.001, margin_factor=0.01, multiplier_factor=0.0001")]
1224        fn TEST_assert_vector_eq_approx_3_PARAMETER_VECTORS_SAME_LENGTH_DIFFERENT_ELEMENTS() {
1225            let expected : &[f64] = &[ -2.0, -3.0, -4.0 ];
1226            let actual = Vec::from([ -2.0, -3.001, -4.0 ]);
1227
1228            assert_vector_eq_approx!(expected, actual, zero_margin_or_multiplier(0.0001, 0.01));
1229        }
1230
1231        #[test]
1232        fn TEST_assert_vector_eq_approx_3_PARAMETER_VECTORS_SAME_LENGTH_DIFFERENT_ELEMENTS_WITH_PERMISSIVE_multiplier() {
1233            let expected : &[f64] = &[ -2.0, -3.0, -4.0 ];
1234            let actual = Vec::from([ -2.0, -3.000001, -4.0 ]);
1235
1236            assert_vector_eq_approx!(expected, actual, multiplier(0.01));
1237        }
1238    }
1239
1240
1241    mod TEST_README_EXAMPLES {
1242        #![allow(non_snake_case)]
1243
1244        use super::*;
1245
1246
1247        #[test]
1248        fn example_test_of_scalar_evaluation() {
1249            let expected = 3.0;
1250            let actual = 3.0001;
1251            assert_scalar_eq_approx!(expected, actual, margin(0.0001));
1252        }
1253
1254        #[test]
1255        fn example_test_of_vector_evaluation() {
1256            let expected = &[ 3.0, -40404.0, 1.23456 ];
1257            let actual = Vec::from([ 3.0, -40410.0, 1.234567 ]);
1258            assert_vector_eq_approx!(expected, actual, multiplier(0.00015));
1259        }
1260
1261    }
1262}
1263
1264
1265// ///////////////////////////// end of file //////////////////////////// //