Skip to main content

use_congruence/
lib.rs

1#![forbid(unsafe_code)]
2#![doc = include_str!("../README.md")]
3
4/// A non-negative tolerance for congruence-style comparisons.
5#[derive(Debug, Clone, Copy, PartialEq)]
6pub struct CongruenceTolerance {
7    value: f64,
8}
9
10impl CongruenceTolerance {
11    /// Creates a finite, non-negative tolerance.
12    #[must_use]
13    pub const fn new(value: f64) -> Option<Self> {
14        if value.is_finite() && value >= 0.0 {
15            Some(Self { value })
16        } else {
17            None
18        }
19    }
20
21    /// Returns the tolerance value.
22    #[must_use]
23    pub const fn value(self) -> f64 {
24        self.value
25    }
26
27    /// Returns `true` when two lengths match within this tolerance.
28    #[must_use]
29    pub fn matches_lengths(self, left: f64, right: f64) -> bool {
30        (left - right).abs() <= self.value
31    }
32}
33
34#[cfg(test)]
35mod tests {
36    use super::CongruenceTolerance;
37
38    #[test]
39    fn compares_lengths_with_tolerance() {
40        let tolerance = CongruenceTolerance::new(0.01).expect("valid tolerance");
41
42        assert!(tolerance.matches_lengths(3.0, 3.005));
43        assert!(!tolerance.matches_lengths(3.0, 3.02));
44        assert_eq!(CongruenceTolerance::new(-1.0), None);
45    }
46}