num_bigint/
macros.rs

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