1 #![allow(unused_macros)]
2 
3 macro_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 
17 macro_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 
35 macro_rules! forward_ref_val_binop {
36     (impl $imp:ident for $res:ty, $method:ident) => {
37         impl $imp<$res> for &$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 
49 macro_rules! forward_ref_val_binop_commutative {
50     (impl $imp:ident for $res:ty, $method:ident) => {
51         impl $imp<$res> for &$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 
63 macro_rules! forward_val_ref_binop {
64     (impl $imp:ident for $res:ty, $method:ident) => {
65         impl $imp<&$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 
77 macro_rules! forward_ref_ref_binop {
78     (impl $imp:ident for $res:ty, $method:ident) => {
79         impl $imp<&$res> for &$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 
91 macro_rules! forward_ref_ref_binop_commutative {
92     (impl $imp:ident for $res:ty, $method:ident) => {
93         impl $imp<&$res> for &$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 
109 macro_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 
120 macro_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
132 macro_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
146 macro_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 
168 macro_rules! forward_scalar_ref_ref_binop_to_ref_val {
169     (impl $imp:ident<$scalar:ty> for $res:ty, $method:ident) => {
170         impl $imp<&$scalar> for &$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 $imp<&$res> for &$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 
190 macro_rules! forward_scalar_val_ref_binop_to_ref_val {
191     (impl $imp:ident<$scalar:ty> for $res:ty, $method:ident) => {
192         impl $imp<&$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 $imp<$res> for &$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 
212 macro_rules! forward_scalar_val_ref_binop_to_val_val {
213     (impl $imp:ident<$scalar:ty> for $res:ty, $method:ident) => {
214         impl $imp<&$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 $imp<$res> for &$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 
234 macro_rules! forward_scalar_ref_val_binop_to_val_val {
235     (impl $imp:ident < $scalar:ty > for $res:ty, $method:ident) => {
236         impl $imp<$scalar> for &$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 $imp<&$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 
256 macro_rules! forward_scalar_ref_ref_binop_to_val_val {
257     (impl $imp:ident<$scalar:ty> for $res:ty, $method:ident) => {
258         impl $imp<&$scalar> for &$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 $imp<&$res> for &$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 
278 macro_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 }
305 macro_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 
319 macro_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 
326 macro_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 
333 macro_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 
340 macro_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
348 macro_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
357 macro_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
366 macro_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 
374 macro_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 
382 macro_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 
390 macro_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 
397 macro_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 
404 macro_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 
411 macro_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 
427 macro_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 }
442