ospf_rust_math/algebra/operator/comparison/
greater.rs

1use std::ops::{Add, Sub};
2
3use crate::algebra::concept::*;
4use crate::algebra::operator::Abs;
5
6use super::ComparisonOperator;
7
8pub trait GreaterOpr<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 GreaterOpr<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 GreaterOpr<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 GreaterOpr<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 GreaterOpr<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 GreaterOpr<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 GreaterOpr<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 GreaterInt {}
56
57impl GreaterInt {
58    pub fn new() -> Self {
59        Self {}
60    }
61}
62
63impl<T: PartialOrd<Rhs>, Rhs> ComparisonOperator<T, Rhs> for GreaterInt {
64    fn cmp(&self, lhs: &T, rhs: &Rhs) -> bool {
65        lhs > rhs
66    }
67}
68
69impl<T: PartialOrd<Rhs>, Rhs> GreaterOpr<T, Rhs> for GreaterInt {
70    default fn precision(&self) -> Option<&T> {
71        None
72    }
73}
74
75impl<T: SemiArithmetic + PartialOrd<Rhs>, Rhs> GreaterOpr<T, Rhs> for GreaterInt {
76    fn precision(&self) -> Option<&T> {
77        Some(T::ZERO)
78    }
79}
80
81#[derive(Clone, Copy, Debug)]
82pub struct GreaterFlt<T> {
83    pub(self) precision: T,
84}
85
86impl<T> From<T> for GreaterFlt<T> {
87    default fn from(precision: T) -> Self {
88        Self { precision }
89    }
90}
91
92impl<T: Signed> From<&T> for GreaterFlt<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 GreaterFlt<T> {
104    fn from(precision: T) -> Self {
105        Self {
106            precision: precision.abs(),
107        }
108    }
109}
110
111impl<T> GreaterFlt<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 GreaterFlt<T>
130where
131    for<'a> &'a T: Sub,
132    for<'a> <&'a T as Sub>::Output: PartialOrd<Rhs>,
133{
134    fn cmp(&self, x: &T, y: &Rhs) -> bool {
135        if x < y {
136            false
137        } else {
138            &(x - &self.precision) > y
139        }
140    }
141}
142
143impl<T: PartialOrd<Rhs>, Rhs> GreaterOpr<T, Rhs> for GreaterFlt<T>
144where
145    for<'a> &'a T: Sub,
146    for<'a> <&'a T as Sub>::Output: PartialOrd<Rhs>,
147{
148    fn precision(&self) -> Option<&T> {
149        Some(&self.precision)
150    }
151}
152
153pub trait GreaterOprBuilder<T, Rhs = T> {
154    fn new() -> Box<dyn GreaterOpr<T, Rhs>>;
155    fn new_with(precision: T) -> Box<dyn GreaterOpr<T, Rhs>>;
156}
157
158pub struct Greater {}
159
160impl<T: PartialOrd<Rhs>, Rhs> GreaterOprBuilder<T, Rhs> for Greater {
161    default fn new() -> Box<dyn GreaterOpr<T, Rhs>> {
162        Box::new(GreaterInt::new())
163    }
164
165    default fn new_with(precision: T) -> Box<dyn GreaterOpr<T, Rhs>> {
166        Box::new(GreaterInt::new())
167    }
168}
169
170impl<T: 'static + PartialOrd<Rhs>, Rhs> GreaterOprBuilder<T, Rhs> for Greater
171where
172    for<'a> &'a T: Sub,
173    for<'a> <&'a T as Sub>::Output: PartialOrd<Rhs>,
174{
175    default fn new() -> Box<dyn GreaterOpr<T, Rhs>> {
176        Box::new(GreaterInt::new())
177    }
178
179    default fn new_with(precision: T) -> Box<dyn GreaterOpr<T, Rhs>> {
180        Box::new(GreaterFlt::new_with(precision))
181    }
182}
183
184impl<T: FloatingNumber + Clone + PartialOrd<Rhs>, Rhs> GreaterOprBuilder<T, Rhs> for Greater
185where
186    for<'a> &'a T: Sub,
187    for<'a> <&'a T as Sub>::Output: PartialOrd<Rhs>,
188{
189    fn new() -> Box<dyn GreaterOpr<T, Rhs>> {
190        Box::new(GreaterFlt::new())
191    }
192
193    fn new_with(precision: T) -> Box<dyn GreaterOpr<T, Rhs>>
194    where
195        GreaterFlt<T>: From<T>,
196    {
197        Box::new(GreaterFlt::new_with(precision))
198    }
199}
200
201#[cfg(test)]
202mod tests {
203    use super::*;
204
205    #[test]
206    fn test_gr_int() {
207        let gr = Greater::new();
208        assert_eq!(gr(&1, &2), false);
209        assert_eq!(gr(&2, &1), true);
210        assert_eq!(gr(&1, &1), false);
211    }
212
213    #[test]
214    fn test_gr_flt() {
215        let gr = Greater::new();
216        assert_eq!(gr(&0.0, &0.0), false);
217        assert_eq!(gr(&0.0, &1e-6), false);
218        assert_eq!(gr(&1e-6, &0.0), true);
219        assert_eq!(gr(&0.0, &1e-4), false);
220        assert_eq!(gr(&1e-4, &0.0), true);
221
222        let gr = Greater::new_with(1e-5);
223        assert_eq!(gr(&0.0, &0.0), false);
224        assert_eq!(gr(&0.0, &1e-6), false);
225        assert_eq!(gr(&1e-6, &0.0), false);
226        assert_eq!(gr(&0.0, &1e-4), false);
227        assert_eq!(gr(&1e-4, &0.0), true);
228    }
229}