1 #![allow(unknown_lints)] // older rustc doesn't know `unused_macros`
2 #![allow(unused_macros)]
3 
4 macro_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 macro_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 
36 macro_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 
50 macro_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 
64 macro_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 
78 macro_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 
92 macro_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 
110 macro_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 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 macro_rules! forward_scalar_val_val_binop_commutative {
132     (impl $imp:ident < $scalar:ty > for $res:ty, $method:ident) => {
133         impl $imp<$res> for $scalar {
134             type Output = $res;
135 
136             #[inline]
137             fn $method(self, other: $res) -> $res {
138                 $imp::$method(other, self)
139             }
140         }
141     };
142 }
143 
144 macro_rules! forward_scalar_val_ref_binop {
145     (impl $imp:ident < $scalar:ty > for $res:ty, $method:ident) => {
146         impl<'a> $imp<&'a $scalar> for $res {
147             type Output = $res;
148 
149             #[inline]
150             fn $method(self, other: &$scalar) -> $res {
151                 $imp::$method(self, *other)
152             }
153         }
154 
155         impl<'a> $imp<$res> for &'a $scalar {
156             type Output = $res;
157 
158             #[inline]
159             fn $method(self, other: $res) -> $res {
160                 $imp::$method(*self, other)
161             }
162         }
163     };
164 }
165 
166 macro_rules! forward_scalar_ref_val_binop {
167     (impl $imp:ident < $scalar:ty > for $res:ty, $method:ident) => {
168         impl<'a> $imp<$scalar> for &'a $res {
169             type Output = $res;
170 
171             #[inline]
172             fn $method(self, other: $scalar) -> $res {
173                 $imp::$method(self.clone(), other)
174             }
175         }
176 
177         impl<'a> $imp<&'a $res> for $scalar {
178             type Output = $res;
179 
180             #[inline]
181             fn $method(self, other: &$res) -> $res {
182                 $imp::$method(self, other.clone())
183             }
184         }
185     };
186 }
187 
188 macro_rules! forward_scalar_ref_ref_binop {
189     (impl $imp:ident < $scalar:ty > for $res:ty, $method:ident) => {
190         impl<'a, 'b> $imp<&'b $scalar> for &'a $res {
191             type Output = $res;
192 
193             #[inline]
194             fn $method(self, other: &$scalar) -> $res {
195                 $imp::$method(self.clone(), *other)
196             }
197         }
198 
199         impl<'a, 'b> $imp<&'a $res> for &'b $scalar {
200             type Output = $res;
201 
202             #[inline]
203             fn $method(self, other: &$res) -> $res {
204                 $imp::$method(*self, other.clone())
205             }
206         }
207     };
208 }
209 
210 macro_rules! promote_scalars {
211     (impl $imp:ident<$promo:ty> for $res:ty, $method:ident, $( $scalar:ty ),*) => {
212         $(
213             forward_all_scalar_binop_to_val_val!(impl $imp<$scalar> for $res, $method);
214 
215             impl $imp<$scalar> for $res {
216                 type Output = $res;
217 
218                 #[inline]
219                 fn $method(self, other: $scalar) -> $res {
220                     $imp::$method(self, other as $promo)
221                 }
222             }
223 
224             impl $imp<$res> for $scalar {
225                 type Output = $res;
226 
227                 #[inline]
228                 fn $method(self, other: $res) -> $res {
229                     $imp::$method(self as $promo, other)
230                 }
231             }
232         )*
233     }
234 }
235 macro_rules! promote_scalars_assign {
236     (impl $imp:ident<$promo:ty> for $res:ty, $method:ident, $( $scalar:ty ),*) => {
237         $(
238             impl $imp<$scalar> for $res {
239                 #[inline]
240                 fn $method(&mut self, other: $scalar) {
241                     self.$method(other as $promo);
242                 }
243             }
244         )*
245     }
246 }
247 
248 macro_rules! promote_unsigned_scalars {
249     (impl $imp:ident for $res:ty, $method:ident) => {
250         promote_scalars!(impl $imp<u32> for $res, $method, u8, u16);
251         promote_scalars!(impl $imp<UsizePromotion> for $res, $method, usize);
252     }
253 }
254 
255 macro_rules! promote_unsigned_scalars_assign {
256     (impl $imp:ident for $res:ty, $method:ident) => {
257         promote_scalars_assign!(impl $imp<u32> for $res, $method, u8, u16);
258         promote_scalars_assign!(impl $imp<UsizePromotion> for $res, $method, usize);
259     }
260 }
261 
262 macro_rules! promote_signed_scalars {
263     (impl $imp:ident for $res:ty, $method:ident) => {
264         promote_scalars!(impl $imp<i32> for $res, $method, i8, i16);
265         promote_scalars!(impl $imp<IsizePromotion> for $res, $method, isize);
266     }
267 }
268 
269 macro_rules! promote_signed_scalars_assign {
270     (impl $imp:ident for $res:ty, $method:ident) => {
271         promote_scalars_assign!(impl $imp<i32> for $res, $method, i8, i16);
272         promote_scalars_assign!(impl $imp<UsizePromotion> for $res, $method, isize);
273     }
274 }
275 
276 // Forward everything to ref-ref, when reusing storage is not helpful
277 macro_rules! forward_all_binop_to_ref_ref {
278     (impl $imp:ident for $res:ty, $method:ident) => {
279         forward_val_val_binop!(impl $imp for $res, $method);
280         forward_val_ref_binop!(impl $imp for $res, $method);
281         forward_ref_val_binop!(impl $imp for $res, $method);
282     };
283 }
284 
285 // Forward everything to val-ref, so LHS storage can be reused
286 macro_rules! forward_all_binop_to_val_ref {
287     (impl $imp:ident for $res:ty, $method:ident) => {
288         forward_val_val_binop!(impl $imp for $res, $method);
289         forward_ref_val_binop!(impl $imp for $res, $method);
290         forward_ref_ref_binop!(impl $imp for $res, $method);
291     };
292 }
293 
294 // Forward everything to val-ref, commutatively, so either LHS or RHS storage can be reused
295 macro_rules! forward_all_binop_to_val_ref_commutative {
296     (impl $imp:ident for $res:ty, $method:ident) => {
297         forward_val_val_binop_commutative!(impl $imp for $res, $method);
298         forward_ref_val_binop_commutative!(impl $imp for $res, $method);
299         forward_ref_ref_binop_commutative!(impl $imp for $res, $method);
300     };
301 }
302 
303 macro_rules! forward_all_scalar_binop_to_val_val {
304     (impl $imp:ident<$scalar:ty> for $res:ty, $method:ident) => {
305         forward_scalar_val_ref_binop!(impl $imp<$scalar> for $res, $method);
306         forward_scalar_ref_val_binop!(impl $imp<$scalar> for $res, $method);
307         forward_scalar_ref_ref_binop!(impl $imp<$scalar> for $res, $method);
308     }
309 }
310 
311 macro_rules! forward_all_scalar_binop_to_val_val_commutative {
312     (impl $imp:ident<$scalar:ty> for $res:ty, $method:ident) => {
313         forward_scalar_val_val_binop_commutative!(impl $imp<$scalar> for $res, $method);
314         forward_all_scalar_binop_to_val_val!(impl $imp<$scalar> for $res, $method);
315     }
316 }
317 
318 macro_rules! promote_all_scalars {
319     (impl $imp:ident for $res:ty, $method:ident) => {
320         promote_unsigned_scalars!(impl $imp for $res, $method);
321         promote_signed_scalars!(impl $imp for $res, $method);
322     }
323 }
324 
325 macro_rules! promote_all_scalars_assign {
326     (impl $imp:ident for $res:ty, $method:ident) => {
327         promote_unsigned_scalars_assign!(impl $imp for $res, $method);
328         promote_signed_scalars_assign!(impl $imp for $res, $method);
329     }
330 }
331 
332 macro_rules! impl_sum_iter_type {
333     ($res:ty) => {
334         impl<T> Sum<T> for $res
335         where
336             $res: Add<T, Output = $res>,
337         {
338             fn sum<I>(iter: I) -> Self
339             where
340                 I: Iterator<Item = T>,
341             {
342                 iter.fold(Zero::zero(), <$res>::add)
343             }
344         }
345     };
346 }
347 
348 macro_rules! impl_product_iter_type {
349     ($res:ty) => {
350         impl<T> Product<T> for $res
351         where
352             $res: Mul<T, Output = $res>,
353         {
354             fn product<I>(iter: I) -> Self
355             where
356                 I: Iterator<Item = T>,
357             {
358                 iter.fold(One::one(), <$res>::mul)
359             }
360         }
361     };
362 }
363