ospf_rust_math/algebra/operator/comparison/
greater_equal.rs1use 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}