ospf_rust_math/algebra/operator/algorithmic/
int_div.rs1use 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}