ospf_rust_math/algebra/operator/comparison/
unequal.rs

1use std::ops::{Add, Sub};
2
3use num::CheckedMul;
4
5use crate::algebra::concept::*;
6use crate::algebra::operator::Abs;
7
8use super::ComparisonOperator;
9
10pub trait UnequalOpr<T, Rhs = T>: ComparisonOperator<T, Rhs> {
11    fn precision(&self) -> Option<&T>;
12}
13
14impl<T, Rhs> FnOnce<(&T, &Rhs)> for &dyn UnequalOpr<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 UnequalOpr<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 UnequalOpr<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 UnequalOpr<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 UnequalOpr<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 UnequalOpr<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 UnequalInt {}
56
57impl UnequalInt {
58    fn new() -> Self {
59        Self {}
60    }
61}
62
63impl<T: PartialEq<Rhs>, Rhs> ComparisonOperator<T, Rhs> for UnequalInt {
64    fn cmp(&self, x: &T, y: &Rhs) -> bool {
65        x != y
66    }
67}
68
69impl<T: PartialEq<Rhs>, Rhs> UnequalOpr<T, Rhs> for UnequalInt {
70    default fn precision(&self) -> Option<&T> {
71        None
72    }
73}
74
75impl<T: SemiArithmetic + PartialEq<Rhs>, Rhs> UnequalOpr<T, Rhs> for UnequalInt {
76    fn precision(&self) -> Option<&T> {
77        Some(T::ZERO)
78    }
79}
80
81#[derive(Clone, Copy, Debug)]
82pub struct UnequalFlt<T> {
83    pub(self) precision: T,
84}
85
86impl<T> From<T> for UnequalFlt<T> {
87    default fn from(precision: T) -> Self {
88        Self { precision }
89    }
90}
91
92impl<T: Signed> From<&T> for UnequalFlt<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 UnequalFlt<T> {
104    fn from(precision: T) -> Self {
105        Self {
106            precision: precision.abs(),
107        }
108    }
109}
110
111impl<T> UnequalFlt<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 UnequalFlt<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> UnequalOpr<T, Rhs> for UnequalFlt<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 UnequalOprBuilder<T, Rhs = T> {
152    fn new() -> Box<dyn UnequalOpr<T, Rhs>>;
153    fn new_with(precision: T) -> Box<dyn UnequalOpr<T, Rhs>>;
154}
155
156pub struct Unequal<T> {
157    _marker: std::marker::PhantomData<T>,
158}
159
160impl<T: PartialEq<Rhs>, Rhs> UnequalOprBuilder<T, Rhs> for Unequal<T> {
161    default fn new() -> Box<dyn UnequalOpr<T, Rhs>> {
162        Box::new(UnequalInt::new())
163    }
164
165    default fn new_with(precision: T) -> Box<dyn UnequalOpr<T, Rhs>> {
166        Box::new(UnequalInt::new())
167    }
168}
169
170impl<T: 'static + PartialOrd<Rhs>, Rhs> UnequalOprBuilder<T, Rhs> for Unequal<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 UnequalOpr<T, Rhs>> {
177        Box::new(UnequalInt::new())
178    }
179
180    default fn new_with(precision: T) -> Box<dyn UnequalOpr<T, Rhs>> {
181        Box::new(UnequalFlt::new_with(precision))
182    }
183}
184
185impl<T: FloatingNumber + Clone + PartialOrd<Rhs>, Rhs> UnequalOprBuilder<T, Rhs> for Unequal<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 UnequalOpr<T, Rhs>> {
192        Box::new(UnequalFlt::new())
193    }
194
195    fn new_with(precision: T) -> Box<dyn UnequalOpr<T, Rhs>> {
196        Box::new(UnequalFlt::new_with(precision))
197    }
198}
199
200#[cfg(test)]
201mod tests {
202    use super::*;
203
204    #[test]
205    fn test_neq_int() {
206        let neq = Unequal::<i64>::new();
207        assert_eq!(neq(&0, &0), false);
208        assert_eq!(neq(&1, &0), true);
209    }
210
211    #[test]
212    fn test_neq_flt() {
213        let neq = Unequal::<f64>::new();
214        assert_eq!(neq(&0.0, &0.0), false);
215        assert_eq!(neq(&1e-6, &0.0), true);
216
217        let neq = Unequal::<f64>::new_with(1e-5);
218        assert_eq!(neq(&0.0, &0.0), false);
219        assert_eq!(neq(&1e-6, &0.0), false);
220    }
221}