num_bigint/
macros.rs

1#![allow(unused_macros)]
2
3macro_rules! forward_val_val_binop {
4    (impl $imp:ident for $res:ty, $method:ident) => {
5        impl $imp<$res> for $res {
6            type Output = $res;
7
8            #[inline]
9            fn $method(self, other: $res) -> $res {
10                // forward to val-ref
11                $imp::$method(self, &other)
12            }
13        }
14    };
15}
16
17macro_rules! forward_val_val_binop_commutative {
18    (impl $imp:ident for $res:ty, $method:ident) => {
19        impl $imp<$res> for $res {
20            type Output = $res;
21
22            #[inline]
23            fn $method(self, other: $res) -> $res {
24                // forward to val-ref, with the larger capacity as val
25                if self.capacity() >= other.capacity() {
26                    $imp::$method(self, &other)
27                } else {
28                    $imp::$method(other, &self)
29                }
30            }
31        }
32    };
33}
34
35macro_rules! forward_ref_val_binop {
36    (impl $imp:ident for $res:ty, $method:ident) => {
37        impl<'a> $imp<$res> for &'a $res {
38            type Output = $res;
39
40            #[inline]
41            fn $method(self, other: $res) -> $res {
42                // forward to ref-ref
43                $imp::$method(self, &other)
44            }
45        }
46    };
47}
48
49macro_rules! forward_ref_val_binop_commutative {
50    (impl $imp:ident for $res:ty, $method:ident) => {
51        impl<'a> $imp<$res> for &'a $res {
52            type Output = $res;
53
54            #[inline]
55            fn $method(self, other: $res) -> $res {
56                // reverse, forward to val-ref
57                $imp::$method(other, self)
58            }
59        }
60    };
61}
62
63macro_rules! forward_val_ref_binop {
64    (impl $imp:ident for $res:ty, $method:ident) => {
65        impl<'a> $imp<&'a $res> for $res {
66            type Output = $res;
67
68            #[inline]
69            fn $method(self, other: &$res) -> $res {
70                // forward to ref-ref
71                $imp::$method(&self, other)
72            }
73        }
74    };
75}
76
77macro_rules! forward_ref_ref_binop {
78    (impl $imp:ident for $res:ty, $method:ident) => {
79        impl<'a, 'b> $imp<&'b $res> for &'a $res {
80            type Output = $res;
81
82            #[inline]
83            fn $method(self, other: &$res) -> $res {
84                // forward to val-ref
85                $imp::$method(self.clone(), other)
86            }
87        }
88    };
89}
90
91macro_rules! forward_ref_ref_binop_commutative {
92    (impl $imp:ident for $res:ty, $method:ident) => {
93        impl<'a, 'b> $imp<&'b $res> for &'a $res {
94            type Output = $res;
95
96            #[inline]
97            fn $method(self, other: &$res) -> $res {
98                // forward to val-ref, choosing the larger to clone
99                if self.len() >= other.len() {
100                    $imp::$method(self.clone(), other)
101                } else {
102                    $imp::$method(other.clone(), self)
103                }
104            }
105        }
106    };
107}
108
109macro_rules! forward_val_assign {
110    (impl $imp:ident for $res:ty, $method:ident) => {
111        impl $imp<$res> for $res {
112            #[inline]
113            fn $method(&mut self, other: $res) {
114                self.$method(&other);
115            }
116        }
117    };
118}
119
120macro_rules! forward_val_assign_scalar {
121    (impl $imp:ident for $res:ty, $scalar:ty, $method:ident) => {
122        impl $imp<$res> for $scalar {
123            #[inline]
124            fn $method(&mut self, other: $res) {
125                self.$method(&other);
126            }
127        }
128    };
129}
130
131/// use this if val_val_binop is already implemented and the reversed order is required
132macro_rules! forward_scalar_val_val_binop_commutative {
133    (impl $imp:ident < $scalar:ty > for $res:ty, $method:ident) => {
134        impl $imp<$res> for $scalar {
135            type Output = $res;
136
137            #[inline]
138            fn $method(self, other: $res) -> $res {
139                $imp::$method(other, self)
140            }
141        }
142    };
143}
144
145// Forward scalar to ref-val, when reusing storage is not helpful
146macro_rules! forward_scalar_val_val_binop_to_ref_val {
147    (impl $imp:ident<$scalar:ty> for $res:ty, $method:ident) => {
148        impl $imp<$scalar> for $res {
149            type Output = $res;
150
151            #[inline]
152            fn $method(self, other: $scalar) -> $res {
153                $imp::$method(&self, other)
154            }
155        }
156
157        impl $imp<$res> for $scalar {
158            type Output = $res;
159
160            #[inline]
161            fn $method(self, other: $res) -> $res {
162                $imp::$method(self, &other)
163            }
164        }
165    };
166}
167
168macro_rules! forward_scalar_ref_ref_binop_to_ref_val {
169    (impl $imp:ident<$scalar:ty> for $res:ty, $method:ident) => {
170        impl<'a, 'b> $imp<&'b $scalar> for &'a $res {
171            type Output = $res;
172
173            #[inline]
174            fn $method(self, other: &$scalar) -> $res {
175                $imp::$method(self, *other)
176            }
177        }
178
179        impl<'a, 'b> $imp<&'a $res> for &'b $scalar {
180            type Output = $res;
181
182            #[inline]
183            fn $method(self, other: &$res) -> $res {
184                $imp::$method(*self, other)
185            }
186        }
187    };
188}
189
190macro_rules! forward_scalar_val_ref_binop_to_ref_val {
191    (impl $imp:ident<$scalar:ty> for $res:ty, $method:ident) => {
192        impl<'a> $imp<&'a $scalar> for $res {
193            type Output = $res;
194
195            #[inline]
196            fn $method(self, other: &$scalar) -> $res {
197                $imp::$method(&self, *other)
198            }
199        }
200
201        impl<'a> $imp<$res> for &'a $scalar {
202            type Output = $res;
203
204            #[inline]
205            fn $method(self, other: $res) -> $res {
206                $imp::$method(*self, &other)
207            }
208        }
209    };
210}
211
212macro_rules! forward_scalar_val_ref_binop_to_val_val {
213    (impl $imp:ident<$scalar:ty> for $res:ty, $method:ident) => {
214        impl<'a> $imp<&'a $scalar> for $res {
215            type Output = $res;
216
217            #[inline]
218            fn $method(self, other: &$scalar) -> $res {
219                $imp::$method(self, *other)
220            }
221        }
222
223        impl<'a> $imp<$res> for &'a $scalar {
224            type Output = $res;
225
226            #[inline]
227            fn $method(self, other: $res) -> $res {
228                $imp::$method(*self, other)
229            }
230        }
231    };
232}
233
234macro_rules! forward_scalar_ref_val_binop_to_val_val {
235    (impl $imp:ident < $scalar:ty > for $res:ty, $method:ident) => {
236        impl<'a> $imp<$scalar> for &'a $res {
237            type Output = $res;
238
239            #[inline]
240            fn $method(self, other: $scalar) -> $res {
241                $imp::$method(self.clone(), other)
242            }
243        }
244
245        impl<'a> $imp<&'a $res> for $scalar {
246            type Output = $res;
247
248            #[inline]
249            fn $method(self, other: &$res) -> $res {
250                $imp::$method(self, other.clone())
251            }
252        }
253    };
254}
255
256macro_rules! forward_scalar_ref_ref_binop_to_val_val {
257    (impl $imp:ident<$scalar:ty> for $res:ty, $method:ident) => {
258        impl<'a, 'b> $imp<&'b $scalar> for &'a $res {
259            type Output = $res;
260
261            #[inline]
262            fn $method(self, other: &$scalar) -> $res {
263                $imp::$method(self.clone(), *other)
264            }
265        }
266
267        impl<'a, 'b> $imp<&'a $res> for &'b $scalar {
268            type Output = $res;
269
270            #[inline]
271            fn $method(self, other: &$res) -> $res {
272                $imp::$method(*self, other.clone())
273            }
274        }
275    };
276}
277
278macro_rules! promote_scalars {
279    (impl $imp:ident<$promo:ty> for $res:ty, $method:ident, $( $scalar:ty ),*) => {
280        $(
281            forward_all_scalar_binop_to_val_val!(impl $imp<$scalar> for $res, $method);
282
283            impl $imp<$scalar> for $res {
284                type Output = $res;
285
286                #[allow(clippy::cast_lossless)]
287                #[inline]
288                fn $method(self, other: $scalar) -> $res {
289                    $imp::$method(self, other as $promo)
290                }
291            }
292
293            impl $imp<$res> for $scalar {
294                type Output = $res;
295
296                #[allow(clippy::cast_lossless)]
297                #[inline]
298                fn $method(self, other: $res) -> $res {
299                    $imp::$method(self as $promo, other)
300                }
301            }
302        )*
303    }
304}
305macro_rules! promote_scalars_assign {
306    (impl $imp:ident<$promo:ty> for $res:ty, $method:ident, $( $scalar:ty ),*) => {
307        $(
308            impl $imp<$scalar> for $res {
309                #[allow(clippy::cast_lossless)]
310                #[inline]
311                fn $method(&mut self, other: $scalar) {
312                    self.$method(other as $promo);
313                }
314            }
315        )*
316    }
317}
318
319macro_rules! promote_unsigned_scalars {
320    (impl $imp:ident for $res:ty, $method:ident) => {
321        promote_scalars!(impl $imp<u32> for $res, $method, u8, u16);
322        promote_scalars!(impl $imp<UsizePromotion> for $res, $method, usize);
323    }
324}
325
326macro_rules! promote_unsigned_scalars_assign {
327    (impl $imp:ident for $res:ty, $method:ident) => {
328        promote_scalars_assign!(impl $imp<u32> for $res, $method, u8, u16);
329        promote_scalars_assign!(impl $imp<UsizePromotion> for $res, $method, usize);
330    }
331}
332
333macro_rules! promote_signed_scalars {
334    (impl $imp:ident for $res:ty, $method:ident) => {
335        promote_scalars!(impl $imp<i32> for $res, $method, i8, i16);
336        promote_scalars!(impl $imp<IsizePromotion> for $res, $method, isize);
337    }
338}
339
340macro_rules! promote_signed_scalars_assign {
341    (impl $imp:ident for $res:ty, $method:ident) => {
342        promote_scalars_assign!(impl $imp<i32> for $res, $method, i8, i16);
343        promote_scalars_assign!(impl $imp<IsizePromotion> for $res, $method, isize);
344    }
345}
346
347// Forward everything to ref-ref, when reusing storage is not helpful
348macro_rules! forward_all_binop_to_ref_ref {
349    (impl $imp:ident for $res:ty, $method:ident) => {
350        forward_val_val_binop!(impl $imp for $res, $method);
351        forward_val_ref_binop!(impl $imp for $res, $method);
352        forward_ref_val_binop!(impl $imp for $res, $method);
353    };
354}
355
356// Forward everything to val-ref, so LHS storage can be reused
357macro_rules! forward_all_binop_to_val_ref {
358    (impl $imp:ident for $res:ty, $method:ident) => {
359        forward_val_val_binop!(impl $imp for $res, $method);
360        forward_ref_val_binop!(impl $imp for $res, $method);
361        forward_ref_ref_binop!(impl $imp for $res, $method);
362    };
363}
364
365// Forward everything to val-ref, commutatively, so either LHS or RHS storage can be reused
366macro_rules! forward_all_binop_to_val_ref_commutative {
367    (impl $imp:ident for $res:ty, $method:ident) => {
368        forward_val_val_binop_commutative!(impl $imp for $res, $method);
369        forward_ref_val_binop_commutative!(impl $imp for $res, $method);
370        forward_ref_ref_binop_commutative!(impl $imp for $res, $method);
371    };
372}
373
374macro_rules! forward_all_scalar_binop_to_ref_val {
375    (impl $imp:ident<$scalar:ty> for $res:ty, $method:ident) => {
376        forward_scalar_val_val_binop_to_ref_val!(impl $imp<$scalar> for $res, $method);
377        forward_scalar_val_ref_binop_to_ref_val!(impl $imp<$scalar> for $res, $method);
378        forward_scalar_ref_ref_binop_to_ref_val!(impl $imp<$scalar> for $res, $method);
379    }
380}
381
382macro_rules! forward_all_scalar_binop_to_val_val {
383    (impl $imp:ident<$scalar:ty> for $res:ty, $method:ident) => {
384        forward_scalar_val_ref_binop_to_val_val!(impl $imp<$scalar> for $res, $method);
385        forward_scalar_ref_val_binop_to_val_val!(impl $imp<$scalar> for $res, $method);
386        forward_scalar_ref_ref_binop_to_val_val!(impl $imp<$scalar> for $res, $method);
387    }
388}
389
390macro_rules! forward_all_scalar_binop_to_val_val_commutative {
391    (impl $imp:ident<$scalar:ty> for $res:ty, $method:ident) => {
392        forward_scalar_val_val_binop_commutative!(impl $imp<$scalar> for $res, $method);
393        forward_all_scalar_binop_to_val_val!(impl $imp<$scalar> for $res, $method);
394    }
395}
396
397macro_rules! promote_all_scalars {
398    (impl $imp:ident for $res:ty, $method:ident) => {
399        promote_unsigned_scalars!(impl $imp for $res, $method);
400        promote_signed_scalars!(impl $imp for $res, $method);
401    }
402}
403
404macro_rules! promote_all_scalars_assign {
405    (impl $imp:ident for $res:ty, $method:ident) => {
406        promote_unsigned_scalars_assign!(impl $imp for $res, $method);
407        promote_signed_scalars_assign!(impl $imp for $res, $method);
408    }
409}
410
411macro_rules! impl_sum_iter_type {
412    ($res:ty) => {
413        impl<T> Sum<T> for $res
414        where
415            $res: Add<T, Output = $res>,
416        {
417            fn sum<I>(iter: I) -> Self
418            where
419                I: Iterator<Item = T>,
420            {
421                iter.fold(Zero::zero(), <$res>::add)
422            }
423        }
424    };
425}
426
427macro_rules! impl_product_iter_type {
428    ($res:ty) => {
429        impl<T> Product<T> for $res
430        where
431            $res: Mul<T, Output = $res>,
432        {
433            fn product<I>(iter: I) -> Self
434            where
435                I: Iterator<Item = T>,
436            {
437                iter.fold(One::one(), <$res>::mul)
438            }
439        }
440    };
441}