1#![forbid(unsafe_code)]
2#![doc = include_str!("../README.md")]
3
4#[derive(Debug, Clone, Copy, PartialEq)]
6pub struct CongruenceTolerance {
7 value: f64,
8}
9
10impl CongruenceTolerance {
11 #[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 #[must_use]
23 pub const fn value(self) -> f64 {
24 self.value
25 }
26
27 #[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}