1#![allow(non_camel_case_types)]
4
5
6#![cfg_attr(test, feature(more_float_constants))]
10
11
12use std::{
20 convert as std_convert,
21 fmt as std_fmt,
22};
23
24
25pub mod constants {
30
31 pub const DEFAULT_MARGIN : f64 = 0.0001;
33
34 pub const DEFAULT_MULTIPLIER : f64 = 0.000001;
36}
37
38
39#[derive(Debug)]
44#[derive(PartialEq)]
45#[derive(PartialOrd)]
46pub enum ComparisonResult {
47 ExactlyEqual,
49 ApproximatelyEqual,
52 Unequal,
55}
56
57#[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
74pub mod traits {
76 use super::ComparisonResult;
77
78 use base_traits::ToF64;
79
80 use std::fmt as std_fmt;
81
82
83 pub trait ApproximateEqualityEvaluator {
86 fn evaluate(
87 &self,
88 expected : f64,
89 actual : f64,
90 ) -> (
91 ComparisonResult, Option<f64>, Option<f64>, );
95 }
96
97 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 #[derive(Debug)]
132 pub struct MarginEvaluator {
133 pub(crate) factor : f64,
134 }
135
136 #[derive(Debug)]
138 pub struct MultiplierEvaluator {
139 pub(crate) factor : f64,
140 }
141
142 #[derive(Debug)]
144 pub struct ZeroMarginOrMultiplierEvaluator {
145 pub(crate) multiplier_factor : f64,
146 pub(crate) zero_margin_factor : f64,
147 }
148
149 impl ApproximateEqualityEvaluator for MarginEvaluator {
152 fn evaluate(
153 &self,
154 expected : f64,
155 actual : f64,
156 ) -> (
157 ComparisonResult, Option<f64>, Option<f64>, ) {
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, Option<f64>, Option<f64>, ) {
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, Option<f64>, Option<f64>, ) {
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 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 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 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 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 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 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 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 {
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 {
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 {
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)); assert_eq!(ComparisonResult::Unequal, compare_approximate_equality_by_margin(0.099, 0.1, 0.000001)); assert_eq!(ComparisonResult::Unequal, compare_approximate_equality_by_margin(0.099, 0.1, 0.00001)); assert_eq!(ComparisonResult::Unequal, compare_approximate_equality_by_margin(0.099, 0.1, 0.0001)); assert_eq!(ComparisonResult::ApproximatelyEqual, compare_approximate_equality_by_margin(0.099, 0.1, 0.001)); assert_eq!(ComparisonResult::ApproximatelyEqual, compare_approximate_equality_by_margin(0.099, 0.1, 0.01)); assert_eq!(ComparisonResult::ApproximatelyEqual, compare_approximate_equality_by_margin(0.099, 0.1, 0.02)); }
402 }
403
404 #[test]
405 fn TEST_compare_approximate_equality_by_multiplier_1() {
406
407 {
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 {
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 {
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)); assert_eq!(ComparisonResult::Unequal, compare_approximate_equality_by_multiplier(0.099, 0.1, 0.000001)); assert_eq!(ComparisonResult::Unequal, compare_approximate_equality_by_multiplier(0.099, 0.1, 0.00001)); assert_eq!(ComparisonResult::Unequal, compare_approximate_equality_by_multiplier(0.099, 0.1, 0.0001)); assert_eq!(ComparisonResult::Unequal, compare_approximate_equality_by_multiplier(0.099, 0.1, 0.001)); assert_eq!(ComparisonResult::Unequal, compare_approximate_equality_by_multiplier(0.099, 0.1, 0.01)); assert_eq!(ComparisonResult::ApproximatelyEqual, compare_approximate_equality_by_multiplier(0.099, 0.1, 0.1)); assert_eq!(ComparisonResult::ApproximatelyEqual, compare_approximate_equality_by_multiplier(0.099, 0.1, 0.5)); }
445 }
446
447 #[test]
448 fn TEST_compare_approximate_equality_by_zero_margin_or_multiplier_1() {
449
450 {
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 {
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 {
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)); assert_eq!(ComparisonResult::Unequal, compare_approximate_equality_by_zero_margin_or_multiplier(0.099, 0.1, 0.000001, 0.000001)); assert_eq!(ComparisonResult::Unequal, compare_approximate_equality_by_zero_margin_or_multiplier(0.099, 0.1, 0.00001, 0.00001)); assert_eq!(ComparisonResult::Unequal, compare_approximate_equality_by_zero_margin_or_multiplier(0.099, 0.1, 0.0001, 0.0001)); assert_eq!(ComparisonResult::Unequal, compare_approximate_equality_by_zero_margin_or_multiplier(0.099, 0.1, 0.001, 0.001)); assert_eq!(ComparisonResult::Unequal, compare_approximate_equality_by_zero_margin_or_multiplier(0.099, 0.1, 0.01, 0.01)); assert_eq!(ComparisonResult::ApproximatelyEqual, compare_approximate_equality_by_zero_margin_or_multiplier(0.099, 0.1, 0.1, 0.1)); assert_eq!(ComparisonResult::ApproximatelyEqual, compare_approximate_equality_by_zero_margin_or_multiplier(0.099, 0.1, 0.5, 0.5)); }
488 }
489 }
490}
491
492
493pub 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, Option<f64>, Option<f64>, )
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, Option<f64>, Option<f64>, )
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 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
614pub fn margin(factor : f64) -> impl traits::ApproximateEqualityEvaluator {
617 internal::MarginEvaluator {
618 factor,
619 }
620}
621
622pub fn multiplier(factor : f64) -> impl traits::ApproximateEqualityEvaluator {
625 internal::MultiplierEvaluator {
626 factor,
627 }
628}
629
630pub 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#[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 {
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 {
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 let expected = &$expected;
793 let actual = &$actual;
794 let evaluator : &dyn $crate::traits::ApproximateEqualityEvaluator = &$evaluator;
795
796 {
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 let expected = &$expected;
868 let actual = &$actual;
869 let evaluator : &dyn $crate::traits::ApproximateEqualityEvaluator = &$evaluator;
870
871 {
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, Option<f64>, Option<f64>, )
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 #[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