ospf_rust_math/algebra/operator/comparison/
less_equal.rs1use std::ops::{Add, Sub};
2
3use crate::algebra::concept::*;
4use crate::algebra::operator::Abs;
5
6use super::ComparisonOperator;
7
8pub trait LessEqualOpr<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 LessEqualOpr<T, Rhs> {
15 type Output = bool;
16
17 extern "rust-call" fn call_once(self, (x, y): (&T, &Rhs)) -> bool {
18 self.cmp(x, y)
19 }
20}
21
22impl<T, Rhs> FnMut<(&T, &Rhs)> for &dyn LessEqualOpr<T, Rhs> {
23 extern "rust-call" fn call_mut(&mut self, (x, y): (&T, &Rhs)) -> bool {
24 self.cmp(x, y)
25 }
26}
27
28impl<T, Rhs> Fn<(&T, &Rhs)> for &dyn LessEqualOpr<T, Rhs> {
29 extern "rust-call" fn call(&self, (x, y): (&T, &Rhs)) -> bool {
30 self.cmp(x, y)
31 }
32}
33
34impl<T, Rhs> FnOnce<(&T, &Rhs)> for Box<dyn LessEqualOpr<T, Rhs>> {
35 type Output = bool;
36
37 extern "rust-call" fn call_once(self, (x, y): (&T, &Rhs)) -> bool {
38 self.cmp(x, y)
39 }
40}
41
42impl<T, Rhs> FnMut<(&T, &Rhs)> for Box<dyn LessEqualOpr<T, Rhs>> {
43 extern "rust-call" fn call_mut(&mut self, (x, y): (&T, &Rhs)) -> bool {
44 self.cmp(x, y)
45 }
46}
47
48impl<T, Rhs> Fn<(&T, &Rhs)> for Box<dyn LessEqualOpr<T, Rhs>> {
49 extern "rust-call" fn call(&self, (x, y): (&T, &Rhs)) -> bool {
50 self.cmp(x, y)
51 }
52}
53
54#[derive(Clone, Copy, Debug)]
55pub struct LessEqualInt {}
56
57impl LessEqualInt {
58 pub fn new() -> Self {
59 Self {}
60 }
61}
62
63impl<T: PartialOrd<Rhs>, Rhs> ComparisonOperator<T, Rhs> for LessEqualInt {
64 fn cmp(&self, x: &T, y: &Rhs) -> bool {
65 x <= y
66 }
67}
68
69impl<T: PartialOrd<Rhs>, Rhs> LessEqualOpr<T, Rhs> for LessEqualInt {
70 default fn precision(&self) -> Option<&T> {
71 None
72 }
73}
74
75impl<T: SemiArithmetic + PartialOrd<Rhs>, Rhs> LessEqualOpr<T, Rhs> for LessEqualInt {
76 fn precision(&self) -> Option<&T> {
77 Some(T::ZERO)
78 }
79}
80
81#[derive(Clone, Copy, Debug)]
82pub struct LessEqualFlt<T> {
83 pub(self) precision: T,
84}
85
86impl<T> From<T> for LessEqualFlt<T> {
87 default fn from(precision: T) -> Self {
88 Self { precision }
89 }
90}
91
92impl<T: Signed> From<&T> for LessEqualFlt<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 LessEqualFlt<T> {
104 fn from(precision: T) -> Self {
105 Self {
106 precision: precision.abs(),
107 }
108 }
109}
110
111impl<T> LessEqualFlt<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 LessEqualFlt<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 true
137 } else {
138 &(x - &self.precision) <= y
139 }
140 }
141}
142
143impl<T: PartialOrd<Rhs>, Rhs> LessEqualOpr<T, Rhs> for LessEqualFlt<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 LessEqualOprBuilder<T, Rhs = T> {
154 fn new() -> Box<dyn LessEqualOpr<T, Rhs>>;
155 fn new_with(precision: T) -> Box<dyn LessEqualOpr<T, Rhs>>;
156}
157
158pub struct LessEqual {}
159
160impl<T: PartialOrd<Rhs>, Rhs> LessEqualOprBuilder<T, Rhs> for LessEqual {
161 default fn new() -> Box<dyn LessEqualOpr<T, Rhs>> {
162 Box::new(LessEqualInt::new())
163 }
164
165 default fn new_with(precision: T) -> Box<dyn LessEqualOpr<T, Rhs>> {
166 Box::new(LessEqualInt::new())
167 }
168}
169
170impl<T: 'static + PartialOrd<Rhs>, Rhs> LessEqualOprBuilder<T, Rhs> for LessEqual
171where
172 for<'a> &'a T: Sub,
173 for<'a> <&'a T as Sub>::Output: PartialOrd<Rhs>,
174{
175 default fn new() -> Box<dyn LessEqualOpr<T, Rhs>> {
176 Box::new(LessEqualInt::new())
177 }
178
179 default fn new_with(precision: T) -> Box<dyn LessEqualOpr<T, Rhs>> {
180 Box::new(LessEqualFlt::new_with(precision))
181 }
182}
183
184impl<T: FloatingNumber + Clone + PartialOrd<Rhs>, Rhs> LessEqualOprBuilder<T, Rhs> for LessEqual
185where
186 for<'a> &'a T: Sub,
187 for<'a> <&'a T as Sub>::Output: PartialOrd<Rhs>,
188{
189 fn new() -> Box<dyn LessEqualOpr<T, Rhs>> {
190 Box::new(LessEqualFlt::new())
191 }
192
193 fn new_with(precision: T) -> Box<dyn LessEqualOpr<T, Rhs>> {
194 Box::new(LessEqualFlt::new_with(precision))
195 }
196}
197
198#[cfg(test)]
199mod tests {
200 use super::*;
201
202 #[test]
203 fn test_leq_int() {
204 let leq = LessEqual::new();
205 assert_eq!(leq(&1, &2), true);
206 assert_eq!(leq(&2, &1), false);
207 assert_eq!(leq(&1, &1), true);
208 }
209
210 #[test]
211 fn test_leq_flt() {
212 let leq = LessEqual::new();
213 assert_eq!(leq(&0.0, &0.0), true);
214 assert_eq!(leq(&0.0, &1e-6), true);
215 assert_eq!(leq(&1e-6, &0.0), false);
216 assert_eq!(leq(&0.0, &1e-4), true);
217 assert_eq!(leq(&1e-4, &0.0), false);
218
219 let leq = LessEqual::new_with(1e-5);
220 assert_eq!(leq(&0.0, &0.0), true);
221 assert_eq!(leq(&0.0, &1e-6), true);
222 assert_eq!(leq(&1e-6, &0.0), true);
223 assert_eq!(leq(&0.0, &1e-4), true);
224 assert_eq!(leq(&1e-4, &0.0), false);
225 }
226}