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