hmath/ratio/
comp.rs

1use crate::Ratio;
2use std::cmp::Ordering;
3
4impl Ratio {
5
6    /// self < other
7    pub fn lt_rat(&self, other: &Ratio) -> bool {
8        // self - other < 0
9        self.sub_rat(other).is_neg()
10    }
11
12    /// self > other
13    pub fn gt_rat(&self, other: &Ratio) -> bool {
14        // other - self < 0
15        other.sub_rat(self).is_neg()
16    }
17
18    /// self == other
19    pub fn eq_rat(&self, other: &Ratio) -> bool {
20        self == other
21    }
22
23    /// self != other
24    pub fn neq_rat(&self, other: &Ratio) -> bool {
25        self != other
26    }
27
28    /// self <= other
29    pub fn leq_rat(&self, other: &Ratio) -> bool {
30        !self.gt_rat(other)
31    }
32
33    /// self >= other
34    pub fn geq_rat(&self, other: &Ratio) -> bool {
35        !self.lt_rat(other)
36    }
37
38    pub fn comp_rat(&self, other: &Ratio) -> Ordering {
39        self.numer.mul_bi(&other.denom).comp_bi(&other.numer.mul_bi(&self.denom))
40    }
41
42    /// self < 1
43    pub fn lt_one(&self) -> bool {
44        self.is_neg() || self.numer.lt_bi(&self.denom)
45    }
46
47    /// self > 1
48    pub fn gt_one(&self) -> bool {
49        !self.is_neg() && self.numer.gt_bi(&self.denom)
50    }
51
52    /// self < other
53    pub fn lt_i32(&self, other: i32) -> bool {
54        self.numer.lt_bi(&self.denom.mul_i32(other))
55    }
56
57    /// self > other
58    pub fn gt_i32(&self, other: i32) -> bool {
59        self.numer.gt_bi(&self.denom.mul_i32(other))
60    }
61
62    /// self == other
63    pub fn eq_i32(&self, other: i32) -> bool {
64        self.denom.is_one() && self.numer.eq_i32(other)
65    }
66
67    /// self != other
68    pub fn neq_i32(&self, other: i32) -> bool {
69        !self.eq_i32(other)
70    }
71
72    /// self <= other
73    pub fn leq_i32(&self, other: i32) -> bool {
74        !self.gt_i32(other)
75    }
76
77    /// self >= other
78    pub fn geq_i32(&self, other: i32) -> bool {
79        !self.lt_i32(other)
80    }
81
82    pub fn comp_i32(&self, other: i32) -> Ordering {
83        self.numer.comp_bi(&self.denom.mul_i32(other))
84    }
85
86}
87
88impl PartialOrd for Ratio {
89
90    fn partial_cmp(&self, other: &Ratio) -> Option<Ordering> {
91        Some(self.comp_rat(other))
92    }
93
94}
95
96impl Ord for Ratio {
97
98    fn cmp(&self, other: &Ratio) -> Ordering {
99        self.comp_rat(other)
100    }
101
102}
103
104#[cfg(test)]
105mod tests {
106    use crate::Ratio;
107    use std::cmp::Ordering;
108
109    #[test]
110    fn rat_comp_test() {
111
112        for d1 in 1..6 {
113
114            for d2 in 1..6 {
115
116                for n1 in -7..7 {
117
118                    for n2 in -7..7 {
119                        comp_test_worker(d1, d2, n1, n2);
120                    }
121
122                }
123
124            }
125
126        }
127
128    }
129
130    fn comp_test_worker(d1: i32, d2: i32, n1: i32, n2: i32) {
131        let a = Ratio::from_denom_and_numer_i32(d1, n1);
132        let b = Ratio::from_denom_and_numer_i32(d2, n2);
133
134        match a.comp_rat(&b) {
135            Ordering::Greater => {
136                assert!(a.gt_rat(&b));
137                assert!(!a.eq_rat(&b));
138                assert!(!a.lt_rat(&b));
139            }
140            Ordering::Equal => {
141                assert!(!a.gt_rat(&b));
142                assert!(a.eq_rat(&b));
143                assert!(!a.lt_rat(&b));
144            }
145            Ordering::Less => {
146                assert!(!a.gt_rat(&b));
147                assert!(!a.eq_rat(&b));
148                assert!(a.lt_rat(&b));
149            }
150        }
151
152        match a.comp_i32(d2 * n2) {
153            Ordering::Greater => {
154                assert!(a.gt_i32(d2 * n2));
155                assert!(!a.eq_i32(d2 * n2));
156                assert!(!a.lt_i32(d2 * n2));
157            }
158            Ordering::Equal => {
159                assert!(!a.gt_i32(d2 * n2));
160                assert!(a.eq_i32(d2 * n2));
161                assert!(!a.lt_i32(d2 * n2));
162            }
163            Ordering::Less => {
164                assert!(!a.gt_i32(d2 * n2));
165                assert!(!a.eq_i32(d2 * n2));
166                assert!(a.lt_i32(d2 * n2));
167            }
168        }
169
170        assert!(a.lt_one() && a.lt_i32(1) || a.gt_one() && a.gt_i32(1) || a.eq_i32(1));
171    }
172
173}