blob: a03cb6769c63503748d0c866f5c70612da3975fe [file] [log] [blame]
Yiming Jingcf21fc42021-07-16 13:23:26 -07001#![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}