Skip to main content

weavatrix_graph/algo/
measure.rs

1use core::cmp::Ordering;
2
3/// Ordered path cost with checked addition.
4///
5/// Implementations must return a consistent total order for valid values.
6pub trait Measure: Copy {
7    fn zero() -> Self;
8    fn checked_add(self, other: Self) -> Option<Self>;
9    fn compare(self, other: Self) -> Option<Ordering>;
10
11    fn is_negative(self) -> bool {
12        false
13    }
14
15    fn is_valid(self) -> bool {
16        self.compare(self).is_some()
17    }
18}
19
20macro_rules! unsigned_measure {
21    ($($type:ty),+ $(,)?) => {
22        $(
23            impl Measure for $type {
24                fn zero() -> Self {
25                    0
26                }
27
28                fn checked_add(self, other: Self) -> Option<Self> {
29                    self.checked_add(other)
30                }
31
32                fn compare(self, other: Self) -> Option<Ordering> {
33                    Some(self.cmp(&other))
34                }
35            }
36        )+
37    };
38}
39
40macro_rules! signed_measure {
41    ($($type:ty),+ $(,)?) => {
42        $(
43            impl Measure for $type {
44                fn zero() -> Self {
45                    0
46                }
47
48                fn checked_add(self, other: Self) -> Option<Self> {
49                    self.checked_add(other)
50                }
51
52                fn compare(self, other: Self) -> Option<Ordering> {
53                    Some(self.cmp(&other))
54                }
55
56                fn is_negative(self) -> bool {
57                    self < 0
58                }
59            }
60        )+
61    };
62}
63
64macro_rules! float_measure {
65    ($($type:ty),+ $(,)?) => {
66        $(
67            impl Measure for $type {
68                fn zero() -> Self {
69                    0.0
70                }
71
72                fn checked_add(self, other: Self) -> Option<Self> {
73                    let sum = self + other;
74                    sum.is_finite().then_some(sum)
75                }
76
77                fn compare(self, other: Self) -> Option<Ordering> {
78                    self.partial_cmp(&other)
79                }
80
81                fn is_negative(self) -> bool {
82                    self < 0.0
83                }
84
85                fn is_valid(self) -> bool {
86                    self.is_finite()
87                }
88            }
89        )+
90    };
91}
92
93unsigned_measure!(u8, u16, u32, u64, u128, usize);
94signed_measure!(i8, i16, i32, i64, i128, isize);
95float_measure!(f32, f64);