ospf_rust_math/algebra/operator/comparison/
greater_equal.rs

1use std::ops::Add;
2
3use crate::algebra::concept::*;
4use crate::algebra::operator::Abs;
5
6use super::ComparisonOperator;
7
8pub trait GreaterEqualOpr<T, Rhs = T>: ComparisonOperator<T, Rhs> {
9    fn precision(&self) -> Option<&T> {
10        None
11    }
12}
13
14impl<T, Rhs> FnOnce<(&T, &Rhs)> for &dyn GreaterEqualOpr<T, Rhs> {
15    type Output = bool;
16
17    extern "rust-call" fn call_once(self, (x, y): (&T, &Rhs)) -> Self::Output {
18        self.cmp(x, y)
19    }
20}
21
22impl<T, Rhs> FnMut<(&T, &Rhs)> for &dyn GreaterEqualOpr<T, Rhs> {
23    extern "rust-call" fn call_mut(&mut self, (x, y): (&T, &Rhs)) -> Self::Output {
24        self.cmp(x, y)
25    }
26}
27
28impl<T, Rhs> Fn<(&T, &Rhs)> for &dyn GreaterEqualOpr<T, Rhs> {
29    extern "rust-call" fn call(&self, (x, y): (&T, &Rhs)) -> Self::Output {
30        self.cmp(x, y)
31    }
32}
33
34impl<T, Rhs> FnOnce<(&T, &Rhs)> for Box<dyn GreaterEqualOpr<T, Rhs>> {
35    type Output = bool;
36
37    extern "rust-call" fn call_once(self, (x, y): (&T, &Rhs)) -> Self::Output {
38        self.cmp(x, y)
39    }
40}
41
42impl<T, Rhs> FnMut<(&T, &Rhs)> for Box<dyn GreaterEqualOpr<T, Rhs>> {
43    extern "rust-call" fn call_mut(&mut self, (x, y): (&T, &Rhs)) -> Self::Output {
44        self.cmp(x, y)
45    }
46}
47
48impl<T, Rhs> Fn<(&T, &Rhs)> for Box<dyn GreaterEqualOpr<T, Rhs>> {
49    extern "rust-call" fn call(&self, (x, y): (&T, &Rhs)) -> Self::Output {
50        self.cmp(x, y)
51    }
52}
53
54#[derive(Clone, Copy, Debug)]
55pub struct GreaterEqualInt {}
56
57impl GreaterEqualInt {
58    pub fn new() -> Self {
59        Self {}
60    }
61}
62
63impl<T: PartialOrd<Rhs>, Rhs> ComparisonOperator<T, Rhs> for GreaterEqualInt {
64    fn cmp(&self, x: &T, y: &Rhs) -> bool {
65        x >= y
66    }
67}
68
69impl<T: PartialOrd<Rhs>, Rhs> GreaterEqualOpr<T, Rhs> for GreaterEqualInt {
70    default fn precision(&self) -> Option<&T> {
71        None
72    }
73}
74
75impl<T: SemiArithmetic + PartialOrd<Rhs>, Rhs> GreaterEqualOpr<T, Rhs> for GreaterEqualInt {
76    fn precision(&self) -> Option<&T> {
77        Some(T::ZERO)
78    }
79}
80
81#[derive(Clone, Copy, Debug)]
82pub struct GreaterEqualFlt<T> {
83    pub(self) precision: T,
84}
85
86impl<T> From<T> for GreaterEqualFlt<T> {
87    default fn from(precision: T) -> Self {
88        Self { precision }
89    }
90}
91
92impl<T: Signed> From<&T> for GreaterEqualFlt<T>
93where
94    for<'a> &'a T: Abs<Output = T>,
95{
96    fn from(precision: &T) -> Self {
97        Self {
98            precision: precision.abs(),
99        }
100    }
101}
102
103impl<T: Signed + Copy + Abs<Output = T>> From<T> for GreaterEqualFlt<T> {
104    fn from(precision: T) -> Self {
105        Self {
106            precision: precision.abs(),
107        }
108    }
109}
110
111impl<T> GreaterEqualFlt<T> {
112    pub fn new() -> Self
113    where
114        T: Precision + Clone,
115    {
116        Self {
117            precision: <T as Precision>::DECIMAL_PRECISION.clone(),
118        }
119    }
120
121    pub fn new_with(precision: T) -> Self
122    where
123        Self: From<T>,
124    {
125        Self::from(precision)
126    }
127}
128
129impl<T: PartialOrd<Rhs>, Rhs> ComparisonOperator<T, Rhs> for GreaterEqualFlt<T>
130where
131    for<'a> &'a T: Add,
132    for<'a> <&'a T as Add>::Output: PartialOrd<Rhs>,
133{
134    fn cmp(&self, x: &T, y: &Rhs) -> bool {
135        if x > y {
136            true
137        } else {
138            &(x + &self.precision) >= y
139        }
140    }
141}
142
143impl<T: PartialOrd<Rhs>, Rhs> GreaterEqualOpr<T, Rhs> for GreaterEqualFlt<T>
144where
145    for<'a> &'a T: Add,
146    for<'a> <&'a T as Add>::Output: PartialOrd<Rhs>,
147{
148    fn precision(&self) -> Option<&T> {
149        Some(&self.precision)
150    }
151}
152
153pub trait GreaterEqualOprBuilder<T, Rhs = T> {
154    fn new() -> Box<dyn GreaterEqualOpr<T, Rhs>>;
155    fn new_with(precision: T) -> Box<dyn GreaterEqualOpr<T, Rhs>>;
156}
157
158pub struct GreaterEqual {}
159
160impl<T: PartialOrd<Rhs>, Rhs> GreaterEqualOprBuilder<T, Rhs> for GreaterEqual {
161    default fn new() -> Box<dyn GreaterEqualOpr<T, Rhs>> {
162        Box::new(GreaterEqualInt::new())
163    }
164
165    default fn new_with(precision: T) -> Box<dyn GreaterEqualOpr<T, Rhs>> {
166        Box::new(GreaterEqualInt::new())
167    }
168}
169
170impl<T: 'static + PartialOrd<Rhs>, Rhs> GreaterEqualOprBuilder<T, Rhs> for GreaterEqual
171where
172    for<'a> &'a T: Add,
173    for<'a> <&'a T as Add>::Output: PartialOrd<Rhs>,
174{
175    default fn new() -> Box<dyn GreaterEqualOpr<T, Rhs>> {
176        Box::new(GreaterEqualInt::new())
177    }
178
179    default fn new_with(precision: T) -> Box<dyn GreaterEqualOpr<T, Rhs>> {
180        Box::new(GreaterEqualFlt::new_with(precision))
181    }
182}
183
184impl<T: FloatingNumber + Clone + PartialOrd<Rhs>, Rhs> GreaterEqualOprBuilder<T, Rhs>
185    for GreaterEqual
186where
187    for<'a> &'a T: Add,
188    for<'a> <&'a T as Add>::Output: PartialOrd<Rhs>,
189{
190    fn new() -> Box<dyn GreaterEqualOpr<T, Rhs>> {
191        Box::new(GreaterEqualFlt::new())
192    }
193
194    fn new_with(precision: T) -> Box<dyn GreaterEqualOpr<T, Rhs>> {
195        Box::new(GreaterEqualFlt::new_with(precision))
196    }
197}
198
199#[cfg(test)]
200mod tests {
201    use super::*;
202
203    #[test]
204    fn test_geq_int() {
205        let geq = GreaterEqual::new();
206        assert_eq!(geq(&1, &2), false);
207        assert_eq!(geq(&2, &1), true);
208        assert_eq!(geq(&1, &1), true);
209    }
210
211    #[test]
212    fn test_geq_flt() {
213        let geq = GreaterEqual::new();
214        assert_eq!(geq(&0.0, &0.0), true);
215        assert_eq!(geq(&0.0, &1e-6), false);
216        assert_eq!(geq(&1e-6, &0.0), true);
217        assert_eq!(geq(&0.0, &1e-4), false);
218        assert_eq!(geq(&1e-4, &0.0), true);
219
220        let geq = GreaterEqual::new_with(1e-5);
221        assert_eq!(geq(&0.0, &0.0), true);
222        assert_eq!(geq(&0.0, &1e-6), true);
223        assert_eq!(geq(&1e-6, &0.0), true);
224        assert_eq!(geq(&0.0, &1e-4), false);
225        assert_eq!(geq(&1e-4, &0.0), true);
226    }
227}