use crate::ComparisonResult;
pub(crate) fn compare_approximate_equality_by_margin(
expected : f64,
actual : f64,
margin_factor : f64,
) -> ComparisonResult {
debug_assert!(
margin_factor >= 0.0,
"`margin_factor` must not be negative, but {margin_factor} given"
);
if expected == actual {
return ComparisonResult::ExactlyEqual;
}
#[cfg(feature = "nan-equality")]
{
if expected.is_nan() && actual.is_nan() {
return ComparisonResult::ExactlyEqual;
}
}
if 0.0 == margin_factor {
return ComparisonResult::Unequal;
}
let expected_lo = expected - margin_factor;
let expected_hi = expected + margin_factor;
result_from_range_(expected_lo, expected_hi, actual)
}
pub(crate) fn compare_approximate_equality_by_multiplier(
expected : f64,
actual : f64,
multiplier_factor : f64,
) -> ComparisonResult {
debug_assert!(
multiplier_factor >= 0.0,
"`multiplier_factor` must not be negative, but {multiplier_factor} given"
);
if expected == actual {
return ComparisonResult::ExactlyEqual;
}
#[cfg(feature = "nan-equality")]
{
if expected.is_nan() && actual.is_nan() {
return ComparisonResult::ExactlyEqual;
}
}
if 0.0 == multiplier_factor {
return ComparisonResult::Unequal;
}
let expected_lo = expected * (1.0 - multiplier_factor);
let expected_hi = expected * (1.0 + multiplier_factor);
result_from_range_(expected_lo, expected_hi, actual)
}
pub(crate) fn compare_approximate_equality_by_zero_margin_or_multiplier(
expected : f64,
actual : f64,
multiplier_factor : f64,
margin_factor : f64,
) -> ComparisonResult {
debug_assert!(
multiplier_factor >= 0.0,
"`multiplier_factor` must not be negative, but {multiplier_factor} given"
);
debug_assert!(
margin_factor >= 0.0,
"`margin_factor` must not be negative, but {margin_factor} given"
);
if expected == actual {
return ComparisonResult::ExactlyEqual;
}
#[cfg(feature = "nan-equality")]
{
if expected.is_nan() && actual.is_nan() {
return ComparisonResult::ExactlyEqual;
}
}
let (expected_lo, expected_hi) = if 0.0 == expected || 0.0 == actual {
if 0.0 == margin_factor {
return ComparisonResult::Unequal;
}
let expected_lo = expected - margin_factor;
let expected_hi = expected + margin_factor;
(expected_lo, expected_hi)
} else {
if 0.0 == multiplier_factor {
return ComparisonResult::Unequal;
}
let expected_lo = expected * (1.0 - multiplier_factor);
let expected_hi = expected * (1.0 + multiplier_factor);
(expected_lo, expected_hi)
};
result_from_range_(expected_lo, expected_hi, actual)
}
fn result_from_range_(
lo : f64,
hi : f64,
actual : f64,
) -> ComparisonResult {
let r = if lo <= hi { lo..=hi } else { hi..=lo };
if r.contains(&actual) {
ComparisonResult::ApproximatelyEqual
} else {
ComparisonResult::Unequal
}
}
#[cfg(test)]
#[rustfmt::skip]
mod tests {
#![allow(non_snake_case)]
#![cfg_attr(debug_assertions, allow(unused_imports))]
use super::{
compare_approximate_equality_by_margin,
compare_approximate_equality_by_multiplier,
compare_approximate_equality_by_zero_margin_or_multiplier,
};
use crate::ComparisonResult;
#[test]
fn TEST_compare_approximate_equality_by_margin_1() {
{
assert_eq!(ComparisonResult::ExactlyEqual, compare_approximate_equality_by_margin(0.0, 0.0, 0.0));
assert_eq!(ComparisonResult::ExactlyEqual, compare_approximate_equality_by_margin(0.0, 0.0, 0.0000001));
assert_eq!(ComparisonResult::ExactlyEqual, compare_approximate_equality_by_margin(0.0, 0.0, 0.000001));
assert_eq!(ComparisonResult::ExactlyEqual, compare_approximate_equality_by_margin(0.0, 0.0, 0.00001));
assert_eq!(ComparisonResult::ExactlyEqual, compare_approximate_equality_by_margin(0.0, 0.0, 0.0001));
assert_eq!(ComparisonResult::ExactlyEqual, compare_approximate_equality_by_margin(0.0, 0.0, 0.001));
assert_eq!(ComparisonResult::ExactlyEqual, compare_approximate_equality_by_margin(0.0, 0.0, 0.01));
assert_eq!(ComparisonResult::ExactlyEqual, compare_approximate_equality_by_margin(0.0, 0.0, 0.1));
assert_eq!(ComparisonResult::ExactlyEqual, compare_approximate_equality_by_margin(0.0, 0.0, 0.5));
}
{
assert_eq!(ComparisonResult::Unequal, compare_approximate_equality_by_margin(0.0, 0.1, 0.0));
assert_eq!(ComparisonResult::Unequal, compare_approximate_equality_by_margin(0.0, 0.1, 0.0000001));
assert_eq!(ComparisonResult::Unequal, compare_approximate_equality_by_margin(0.0, 0.1, 0.000001));
assert_eq!(ComparisonResult::Unequal, compare_approximate_equality_by_margin(0.0, 0.1, 0.00001));
assert_eq!(ComparisonResult::Unequal, compare_approximate_equality_by_margin(0.0, 0.1, 0.0001));
assert_eq!(ComparisonResult::Unequal, compare_approximate_equality_by_margin(0.0, 0.1, 0.001));
assert_eq!(ComparisonResult::Unequal, compare_approximate_equality_by_margin(0.0, 0.1, 0.01));
assert_eq!(ComparisonResult::ApproximatelyEqual, compare_approximate_equality_by_margin(0.0, 0.1, 0.1));
assert_eq!(ComparisonResult::ApproximatelyEqual, compare_approximate_equality_by_margin(0.0, 0.1, 0.5));
}
{
assert_eq!(ComparisonResult::Unequal, compare_approximate_equality_by_margin(0.099, 0.1, 0.0));
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)); }
}
#[test]
fn TEST_compare_approximate_equality_by_multiplier_1() {
{
assert_eq!(ComparisonResult::ExactlyEqual, compare_approximate_equality_by_multiplier(0.0, 0.0, 0.0));
assert_eq!(ComparisonResult::ExactlyEqual, compare_approximate_equality_by_multiplier(0.0, 0.0, 0.0000001));
assert_eq!(ComparisonResult::ExactlyEqual, compare_approximate_equality_by_multiplier(0.0, 0.0, 0.000001));
assert_eq!(ComparisonResult::ExactlyEqual, compare_approximate_equality_by_multiplier(0.0, 0.0, 0.00001));
assert_eq!(ComparisonResult::ExactlyEqual, compare_approximate_equality_by_multiplier(0.0, 0.0, 0.0001));
assert_eq!(ComparisonResult::ExactlyEqual, compare_approximate_equality_by_multiplier(0.0, 0.0, 0.001));
assert_eq!(ComparisonResult::ExactlyEqual, compare_approximate_equality_by_multiplier(0.0, 0.0, 0.01));
assert_eq!(ComparisonResult::ExactlyEqual, compare_approximate_equality_by_multiplier(0.0, 0.0, 0.1));
assert_eq!(ComparisonResult::ExactlyEqual, compare_approximate_equality_by_multiplier(0.0, 0.0, 0.5));
}
{
assert_eq!(ComparisonResult::Unequal, compare_approximate_equality_by_multiplier(0.0, 0.1, 0.0));
assert_eq!(ComparisonResult::Unequal, compare_approximate_equality_by_multiplier(0.0, 0.1, 0.0000001));
assert_eq!(ComparisonResult::Unequal, compare_approximate_equality_by_multiplier(0.0, 0.1, 0.000001));
assert_eq!(ComparisonResult::Unequal, compare_approximate_equality_by_multiplier(0.0, 0.1, 0.00001));
assert_eq!(ComparisonResult::Unequal, compare_approximate_equality_by_multiplier(0.0, 0.1, 0.0001));
assert_eq!(ComparisonResult::Unequal, compare_approximate_equality_by_multiplier(0.0, 0.1, 0.001));
assert_eq!(ComparisonResult::Unequal, compare_approximate_equality_by_multiplier(0.0, 0.1, 0.01));
assert_eq!(ComparisonResult::Unequal, compare_approximate_equality_by_multiplier(0.0, 0.1, 0.1));
assert_eq!(ComparisonResult::Unequal, compare_approximate_equality_by_multiplier(0.0, 0.1, 0.5));
}
{
assert_eq!(ComparisonResult::Unequal, compare_approximate_equality_by_multiplier(0.099, 0.1, 0.0));
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)); }
}
#[test]
fn TEST_compare_approximate_equality_by_zero_margin_or_multiplier_1() {
{
assert_eq!(ComparisonResult::ExactlyEqual, compare_approximate_equality_by_zero_margin_or_multiplier(0.0, 0.0, 0.0, 0.0));
assert_eq!(ComparisonResult::ExactlyEqual, compare_approximate_equality_by_zero_margin_or_multiplier(0.0, 0.0, 0.0000001, 0.0000001));
assert_eq!(ComparisonResult::ExactlyEqual, compare_approximate_equality_by_zero_margin_or_multiplier(0.0, 0.0, 0.000001, 0.000001));
assert_eq!(ComparisonResult::ExactlyEqual, compare_approximate_equality_by_zero_margin_or_multiplier(0.0, 0.0, 0.00001, 0.00001));
assert_eq!(ComparisonResult::ExactlyEqual, compare_approximate_equality_by_zero_margin_or_multiplier(0.0, 0.0, 0.0001, 0.0001));
assert_eq!(ComparisonResult::ExactlyEqual, compare_approximate_equality_by_zero_margin_or_multiplier(0.0, 0.0, 0.001, 0.001));
assert_eq!(ComparisonResult::ExactlyEqual, compare_approximate_equality_by_zero_margin_or_multiplier(0.0, 0.0, 0.01, 0.01));
assert_eq!(ComparisonResult::ExactlyEqual, compare_approximate_equality_by_zero_margin_or_multiplier(0.0, 0.0, 0.1, 0.1));
assert_eq!(ComparisonResult::ExactlyEqual, compare_approximate_equality_by_zero_margin_or_multiplier(0.0, 0.0, 0.5, 0.5));
}
{
assert_eq!(ComparisonResult::Unequal, compare_approximate_equality_by_zero_margin_or_multiplier(0.0, 0.1, 0.0, 0.0));
assert_eq!(ComparisonResult::Unequal, compare_approximate_equality_by_zero_margin_or_multiplier(0.0, 0.1, 0.0000001, 0.0000001));
assert_eq!(ComparisonResult::Unequal, compare_approximate_equality_by_zero_margin_or_multiplier(0.0, 0.1, 0.000001, 0.000001));
assert_eq!(ComparisonResult::Unequal, compare_approximate_equality_by_zero_margin_or_multiplier(0.0, 0.1, 0.00001, 0.00001));
assert_eq!(ComparisonResult::Unequal, compare_approximate_equality_by_zero_margin_or_multiplier(0.0, 0.1, 0.0001, 0.0001));
assert_eq!(ComparisonResult::Unequal, compare_approximate_equality_by_zero_margin_or_multiplier(0.0, 0.1, 0.001, 0.001));
assert_eq!(ComparisonResult::Unequal, compare_approximate_equality_by_zero_margin_or_multiplier(0.0, 0.1, 0.01, 0.01));
assert_eq!(ComparisonResult::ApproximatelyEqual, compare_approximate_equality_by_zero_margin_or_multiplier(0.0, 0.1, 0.1, 0.1));
assert_eq!(ComparisonResult::ApproximatelyEqual, compare_approximate_equality_by_zero_margin_or_multiplier(0.0, 0.1, 0.5, 0.5));
}
{
assert_eq!(ComparisonResult::Unequal, compare_approximate_equality_by_zero_margin_or_multiplier(0.099, 0.1, 0.0, 0.0));
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)); }
}
}