ospf_rust_math/algebra/operator/algorithmic/
int_div.rs

1use std::ops::Div;
2
3use crate::algebra::concept::FloatingNumber;
4
5pub trait IntDiv<Rhs = Self> {
6    type Output;
7
8    fn int_div(self, rhs: Rhs) -> Self::Output;
9}
10
11pub fn int_div<T: IntDiv>(lhs: T, rhs: T) -> T::Output {
12    lhs.int_div(rhs)
13}
14
15macro_rules! int_int_div_template {
16    ($($type:ident)*) => ($(
17        impl<U> IntDiv<U> for $type where $type: Div<U> {
18            type Output = <$type as Div<U>>::Output;
19
20            default fn int_div(self, rhs: U) -> Self::Output {
21                self / rhs
22            }
23        }
24
25        impl<U, V> IntDiv<U> for $type where $type: Div<U, Output=V>, V: FloatingNumber {
26            fn int_div(self, rhs: U) -> Self::Output {
27                (self / rhs).floor()
28            }
29        }
30
31        impl<U> IntDiv<U> for &$type where for<'a> &'a $type: Div<U> {
32            type Output = <Self as Div<U>>::Output;
33
34            default fn int_div(self, rhs: U) -> Self::Output {
35                self / rhs
36            }
37        }
38
39        impl<U, V> IntDiv<U> for &$type where for<'a> &'a $type: Div<U, Output=V>, V: FloatingNumber {
40            fn int_div(self, rhs: U) -> Self::Output {
41                (self / rhs).floor()
42            }
43        }
44    )*)
45}
46int_int_div_template! { bool i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize }
47
48macro_rules! floating_int_div_template {
49    ($($type:ident)*) => ($(
50        impl<U, V> IntDiv<U> for $type where $type: Div<U, Output=V>, V: FloatingNumber {
51            type Output = <$type as Div<U>>::Output;
52
53            fn int_div(self, rhs: U) -> Self::Output {
54                (self / rhs).floor()
55            }
56        }
57
58        impl<U, V> IntDiv<U> for &$type where for<'a> &'a $type: Div<U, Output=V>, V: FloatingNumber {
59            type Output = <Self as Div<U>>::Output;
60
61            fn int_div(self, rhs: U) -> Self::Output {
62                (self / rhs).floor()
63            }
64        }
65    )*)
66}
67floating_int_div_template! { f32 f64 }
68
69#[cfg(test)]
70mod tests {
71    use std::fmt::Debug;
72
73    use crate::algebra::concept::RealNumber;
74
75    use super::*;
76
77    fn test_real<T: RealNumber + IntDiv<Output = T> + Debug>()
78    where
79        for<'a> &'a T: IntDiv<&'a T, Output = T>,
80    {
81        assert_eq!(&(T::ONE.clone().int_div(T::TWO.clone())), T::ZERO);
82        assert_eq!(&(T::ONE.int_div(T::TWO)), T::ZERO);
83        assert_eq!(&int_div(T::ONE.clone(), T::TWO.clone()), T::ZERO);
84        assert_eq!(&int_div(T::ONE, T::TWO), T::ZERO);
85
86        assert_eq!(&(T::TWO.clone().int_div(T::ONE.clone())), T::TWO);
87        assert_eq!(&(T::TWO.int_div(T::ONE)), T::TWO);
88        assert_eq!(&int_div(T::TWO.clone(), T::ONE.clone()), T::TWO);
89        assert_eq!(&int_div(T::TWO, T::ONE), T::TWO);
90
91        assert_eq!(&(T::FIVE.clone().int_div(T::TWO.clone())), T::TWO);
92        assert_eq!(&(T::FIVE.int_div(T::TWO)), T::TWO);
93        assert_eq!(&int_div(T::FIVE.clone(), T::TWO.clone()), T::TWO);
94        assert_eq!(&int_div(T::FIVE, T::TWO), T::TWO);
95    }
96
97    #[test]
98    fn test() {
99        test_real::<u8>();
100        test_real::<u16>();
101        test_real::<u32>();
102        test_real::<u64>();
103        test_real::<u128>();
104        test_real::<i8>();
105        test_real::<i16>();
106        test_real::<i32>();
107        test_real::<i64>();
108        test_real::<i128>();
109        test_real::<f32>();
110        test_real::<f64>();
111    }
112}