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