bigdecimal_rs/
macros.rs

1// \file src/macros.rs
2//! macros for
3/*
4macro_rules! forward_val_val_binop {
5    (impl $imp:ident for $res:ty, $method:ident) => {
6        impl $imp<$res> for $res {
7            type Output = $res;
8
9            #[inline]
10            fn $method(self, other: $res) -> $res {
11                // forward to val-ref
12                $imp::$method(self, &other)
13            }
14        }
15    };
16}
17
18*/
19macro_rules! forward_ref_val_binop {
20    (impl $imp:ident for $res:ty, $method:ident) => {
21        impl<'a> $imp<$res> for &'a $res {
22            type Output = $res;
23
24            #[inline]
25            fn $method(self, other: $res) -> $res {
26                // forward to ref-ref
27                $imp::$method(self, &other)
28            }
29        }
30    };
31}
32
33/*
34macro_rules! forward_val_ref_binop {
35    (impl $imp:ident for $res:ty, $method:ident) => {
36        impl<'a> $imp<&'a $res> for $res {
37            type Output = $res;
38
39            #[inline]
40            fn $method(self, other: &$res) -> $res {
41                // forward to ref-ref
42                $imp::$method(&self, other)
43            }
44        }
45    };
46}
47
48// Forward everything to ref-ref, when reusing storage is not helpful
49macro_rules! forward_all_binop_to_ref_ref {
50    (impl $imp:ident for $res:ty, $method:ident) => {
51        forward_val_val_binop!(impl $imp for $res, $method);
52        forward_val_ref_binop!(impl $imp for $res, $method);
53        forward_ref_val_binop!(impl $imp for $res, $method);
54    };
55}
56*/
57
58macro_rules! forward_val_assignop {
59    (impl $imp:ident for $res:ty, $method:ident) => {
60        impl $imp<$res> for $res {
61            #[inline]
62            fn $method(&mut self, other: $res) {
63                // forward to mutref-ref
64                $imp::$method(self, &other)
65            }
66        }
67    };
68}
69
70macro_rules! impl_div_for_uint_primitive {
71    // (impl $imp:ident for $res:ty, $method:ident) => {
72    ($res:ty) => {
73        impl<'a> Div<$res> for &'a BigDecimal {
74            type Output = BigDecimal;
75
76            #[inline]
77            fn div(self, den: $res) -> Self::Output {
78                if den == 1 {
79                    self.clone()
80                } else if den == 2 {
81                    self.half()
82                } else {
83                    self / BigDecimal::from(den)
84                }
85            }
86        }
87
88        impl<'a> Div<&'a BigDecimal> for $res {
89            type Output = BigDecimal;
90
91            #[inline(always)]
92            fn div(self, den: &'a BigDecimal) -> Self::Output {
93                BigDecimal::from(self) / den
94            }
95        }
96
97        impl Div<BigDecimal> for $res {
98            type Output = BigDecimal;
99
100            #[inline(always)]
101            fn div(self, den: BigDecimal) -> Self::Output {
102                BigDecimal::from(self) / den
103            }
104        }
105    };
106}
107
108macro_rules! impl_div_for_int_primitive {
109    // (impl $imp:ident for $res:ty, $method:ident) => {
110    ($res:ty) => {
111        impl<'a> Div<$res> for BigDecimal {
112            type Output = BigDecimal;
113
114            #[inline(always)]
115            fn div(self, den: $res) -> Self::Output {
116                if den < 0 {
117                    -Div::div(self, -den)
118                } else if den == 1 {
119                    self
120                } else if den == 2 {
121                    self.half()
122                } else {
123                    self / BigDecimal::from(den)
124                }
125            }
126        }
127
128        impl<'a> Div<$res> for &'a BigDecimal {
129            type Output = BigDecimal;
130
131            #[inline(always)]
132            fn div(self, den: $res) -> Self::Output {
133                if den < 0 {
134                    -Div::div(self, -den)
135                } else if den == 1 {
136                    self.clone()
137                } else if den == 2 {
138                    self.half()
139                } else {
140                    self / BigDecimal::from(den)
141                }
142            }
143        }
144
145        impl<'a> Div<&'a BigDecimal> for $res {
146            type Output = BigDecimal;
147
148            #[inline(always)]
149            fn div(self, den: &'a BigDecimal) -> Self::Output {
150                match (self < 0, den.is_negative()) {
151                    (true, true) => -self / -den,
152                    (true, false) => (-self / den).neg(),
153                    (false, true) => (-self / den.abs()),
154                    (false, false) => BigDecimal::from(self) / den,
155                }
156            }
157        }
158
159        impl Div<BigDecimal> for $res {
160            type Output = BigDecimal;
161
162            #[inline(always)]
163            fn div(self, den: BigDecimal) -> Self::Output {
164                match (self < 0, den.is_negative()) {
165                    (true, true) => -self / -den,
166                    (true, false) => (-self / den).neg(),
167                    (false, true) => (-self / den.abs()),
168                    (false, false) => BigDecimal::from(self) / den,
169                }
170            }
171        }
172    };
173}
174
175macro_rules! impl_div_for_float_primitive {
176    // (impl $imp:ident for $res:ty, $method:ident) => {
177    ($res:ty) => {
178        impl<'a> Div<$res> for &'a BigDecimal {
179            type Output = BigDecimal;
180
181            #[inline]
182            fn div(self, den: $res) -> Self::Output {
183                if den.is_nan() {
184                    BigDecimal::zero()
185                } else if den == 1.0 {
186                    self.clone()
187                } else if den == 0.5 {
188                    self.double()
189                } else if den == 2.0 {
190                    self.half()
191                } else if den == -1.0 {
192                    -self
193                } else if den < 0.0 && self.is_positive() {
194                    -(self / -den)
195                } else {
196                    // Unwrap is safe, because `is_nan` checked above
197                    self / BigDecimal::try_from(den).unwrap()
198                }
199            }
200        }
201
202        impl<'a> Div<&'a BigDecimal> for $res {
203            type Output = BigDecimal;
204            #[inline(always)]
205            fn div(self, den: &'a BigDecimal) -> Self::Output {
206                if self.is_nan() {
207                    BigDecimal::zero()
208                } else {
209                    BigDecimal::try_from(self).unwrap() / den
210                }
211            }
212        }
213
214        impl Div<BigDecimal> for $res {
215            type Output = BigDecimal;
216            #[inline(always)]
217            fn div(self, den: BigDecimal) -> Self::Output {
218                if self.is_nan() {
219                    BigDecimal::zero()
220                } else {
221                    BigDecimal::try_from(self).unwrap() / den
222                }
223            }
224        }
225    };
226}
227
228macro_rules! forward_primitive_types {
229    (floats => $macro_name:ident) => {
230        $macro_name!(f32);
231        $macro_name!(f64);
232    };
233    (ints => $macro_name:ident) => {
234        $macro_name!(i8);
235        $macro_name!(i16);
236        $macro_name!(i32);
237        $macro_name!(i64);
238    };
239    (uints => $macro_name:ident) => {
240        $macro_name!(u8);
241        $macro_name!(u16);
242        $macro_name!(u32);
243        $macro_name!(u64);
244    };
245}
246
247macro_rules! impl_div_for_primitives {
248    () => {
249        forward_primitive_types!(floats => impl_div_for_float_primitive);
250        forward_primitive_types!(ints => impl_div_for_int_primitive);
251        forward_primitive_types!(uints => impl_div_for_uint_primitive);
252    };
253}