1 //! Utility macros 2 #![allow(unused)] 3 4 5 macro_rules! impl_unary_ { 6 // implementation mapping 1:1 7 (vec | $trait_id:ident, $trait_method:ident, $vec_id:ident, 8 $fun:ident) => { 9 impl $trait_id for $vec_id { 10 #[inline] 11 fn $trait_method(self) -> Self { 12 unsafe { 13 use crate::mem::transmute; 14 transmute($fun(transmute(self))) 15 } 16 } 17 } 18 }; 19 // implementation mapping 1:1 for when `$fun` is a generic function 20 // like some of the fp math rustc intrinsics (e.g. `fn fun<T>(x: T) -> T`). 21 (gen | $trait_id:ident, $trait_method:ident, $vec_id:ident, 22 $fun:ident) => { 23 impl $trait_id for $vec_id { 24 #[inline] 25 fn $trait_method(self) -> Self { 26 unsafe { 27 use crate::mem::transmute; 28 transmute($fun(self.0)) 29 } 30 } 31 } 32 }; 33 (scalar | $trait_id:ident, $trait_method:ident, 34 $vec_id:ident, [$sid:ident; $scount:expr], $fun:ident) => { 35 impl $trait_id for $vec_id { 36 #[inline] 37 fn $trait_method(self) -> Self { 38 unsafe { 39 union U { 40 vec: $vec_id, 41 scalars: [$sid; $scount], 42 } 43 let mut scalars = U { vec: self }.scalars; 44 for i in &mut scalars { 45 *i = $fun(*i); 46 } 47 U { scalars }.vec 48 } 49 } 50 } 51 }; 52 // implementation calling fun twice on each of the vector halves: 53 (halves | $trait_id:ident, $trait_method:ident, $vec_id:ident, 54 $vech_id:ident, $fun:ident) => { 55 impl $trait_id for $vec_id { 56 #[inline] 57 fn $trait_method(self) -> Self { 58 unsafe { 59 use crate::mem::transmute; 60 union U { 61 vec: $vec_id, 62 halves: [$vech_id; 2], 63 } 64 65 let mut halves = U { vec: self }.halves; 66 67 *halves.get_unchecked_mut(0) = 68 transmute($fun(transmute(*halves.get_unchecked(0)))); 69 *halves.get_unchecked_mut(1) = 70 transmute($fun(transmute(*halves.get_unchecked(1)))); 71 72 U { halves }.vec 73 } 74 } 75 } 76 }; 77 // implementation calling fun four times on each of the vector quarters: 78 (quarter | $trait_id:ident, $trait_method:ident, $vec_id:ident, 79 $vecq_id:ident, $fun:ident) => { 80 impl $trait_id for $vec_id { 81 #[inline] 82 fn $trait_method(self) -> Self { 83 unsafe { 84 use crate::mem::transmute; 85 union U { 86 vec: $vec_id, 87 quarters: [$vecq_id; 4], 88 } 89 90 let mut quarters = U { vec: self }.quarters; 91 92 *quarters.get_unchecked_mut(0) = 93 transmute($fun(transmute(*quarters.get_unchecked(0)))); 94 *quarters.get_unchecked_mut(1) = 95 transmute($fun(transmute(*quarters.get_unchecked(1)))); 96 *quarters.get_unchecked_mut(2) = 97 transmute($fun(transmute(*quarters.get_unchecked(2)))); 98 *quarters.get_unchecked_mut(3) = 99 transmute($fun(transmute(*quarters.get_unchecked(3)))); 100 101 U { quarters }.vec 102 } 103 } 104 } 105 }; 106 // implementation calling fun once on a vector twice as large: 107 (twice | $trait_id:ident, $trait_method:ident, $vec_id:ident, 108 $vect_id:ident, $fun:ident) => { 109 impl $trait_id for $vec_id { 110 #[inline] 111 fn $trait_method(self) -> Self { 112 unsafe { 113 use crate::mem::{transmute, uninitialized}; 114 115 union U { 116 vec: [$vec_id; 2], 117 twice: $vect_id, 118 } 119 120 let twice = U { vec: [self, uninitialized()] }.twice; 121 let twice = transmute($fun(transmute(twice))); 122 123 *(U { twice }.vec.get_unchecked(0)) 124 } 125 } 126 } 127 }; 128 } 129 130 macro_rules! gen_unary_impl_table { 131 ($trait_id:ident, $trait_method:ident) => { 132 macro_rules! impl_unary { 133 ($vid:ident: $fun:ident) => { 134 impl_unary_!(vec | $trait_id, $trait_method, $vid, $fun); 135 }; 136 ($vid:ident[g]: $fun:ident) => { 137 impl_unary_!(gen | $trait_id, $trait_method, $vid, $fun); 138 }; 139 ($vid:ident[$sid:ident; $sc:expr]: $fun:ident) => { 140 impl_unary_!( 141 scalar | $trait_id, 142 $trait_method, 143 $vid, 144 [$sid; $sc], 145 $fun 146 ); 147 }; 148 ($vid:ident[s]: $fun:ident) => { 149 impl_unary_!(scalar | $trait_id, $trait_method, $vid, $fun); 150 }; 151 ($vid:ident[h => $vid_h:ident]: $fun:ident) => { 152 impl_unary_!( 153 halves | $trait_id, 154 $trait_method, 155 $vid, 156 $vid_h, 157 $fun 158 ); 159 }; 160 ($vid:ident[q => $vid_q:ident]: $fun:ident) => { 161 impl_unary_!( 162 quarter | $trait_id, 163 $trait_method, 164 $vid, 165 $vid_q, 166 $fun 167 ); 168 }; 169 ($vid:ident[t => $vid_t:ident]: $fun:ident) => { 170 impl_unary_!( 171 twice | $trait_id, 172 $trait_method, 173 $vid, 174 $vid_t, 175 $fun 176 ); 177 }; 178 } 179 }; 180 } 181 182 macro_rules! impl_tertiary_ { 183 // implementation mapping 1:1 184 (vec | $trait_id:ident, $trait_method:ident, $vec_id:ident, 185 $fun:ident) => { 186 impl $trait_id for $vec_id { 187 #[inline] 188 fn $trait_method(self, y: Self, z: Self) -> Self { 189 unsafe { 190 use crate::mem::transmute; 191 transmute($fun( 192 transmute(self), 193 transmute(y), 194 transmute(z), 195 )) 196 } 197 } 198 } 199 }; 200 (scalar | $trait_id:ident, $trait_method:ident, 201 $vec_id:ident, [$sid:ident; $scount:expr], $fun:ident) => { 202 impl $trait_id for $vec_id { 203 #[inline] 204 fn $trait_method(self, y: Self, z: Self) -> Self { 205 unsafe { 206 union U { 207 vec: $vec_id, 208 scalars: [$sid; $scount], 209 } 210 let mut x = U { vec: self }.scalars; 211 let y = U { vec: y }.scalars; 212 let z = U { vec: z }.scalars; 213 for (x, (y, z)) in (&mut scalars).zip(&y).zip(&z) { 214 *i = $fun(*i, *y, *z); 215 } 216 U { vec: x }.vec 217 } 218 } 219 } 220 }; 221 // implementation calling fun twice on each of the vector halves: 222 (halves | $trait_id:ident, $trait_method:ident, $vec_id:ident, 223 $vech_id:ident, $fun:ident) => { 224 impl $trait_id for $vec_id { 225 #[inline] 226 fn $trait_method(self, y: Self, z: Self) -> Self { 227 unsafe { 228 use crate::mem::transmute; 229 union U { 230 vec: $vec_id, 231 halves: [$vech_id; 2], 232 } 233 234 let mut x_halves = U { vec: self }.halves; 235 let y_halves = U { vec: y }.halves; 236 let z_halves = U { vec: z }.halves; 237 238 *x_halves.get_unchecked_mut(0) = transmute($fun( 239 transmute(*x_halves.get_unchecked(0)), 240 transmute(*y_halves.get_unchecked(0)), 241 transmute(*z_halves.get_unchecked(0)), 242 )); 243 *x_halves.get_unchecked_mut(1) = transmute($fun( 244 transmute(*x_halves.get_unchecked(1)), 245 transmute(*y_halves.get_unchecked(1)), 246 transmute(*z_halves.get_unchecked(1)), 247 )); 248 249 U { halves: x_halves }.vec 250 } 251 } 252 } 253 }; 254 // implementation calling fun four times on each of the vector quarters: 255 (quarter | $trait_id:ident, $trait_method:ident, $vec_id:ident, 256 $vecq_id:ident, $fun:ident) => { 257 impl $trait_id for $vec_id { 258 #[inline] 259 fn $trait_method(self, y: Self, z: Self) -> Self { 260 unsafe { 261 use crate::mem::transmute; 262 union U { 263 vec: $vec_id, 264 quarters: [$vecq_id; 4], 265 } 266 267 let mut x_quarters = U { vec: self }.quarters; 268 let y_quarters = U { vec: y }.quarters; 269 let z_quarters = U { vec: z }.quarters; 270 271 *x_quarters.get_unchecked_mut(0) = transmute($fun( 272 transmute(*x_quarters.get_unchecked(0)), 273 transmute(*y_quarters.get_unchecked(0)), 274 transmute(*z_quarters.get_unchecked(0)), 275 )); 276 277 *x_quarters.get_unchecked_mut(1) = transmute($fun( 278 transmute(*x_quarters.get_unchecked(1)), 279 transmute(*y_quarters.get_unchecked(1)), 280 transmute(*z_quarters.get_unchecked(1)), 281 )); 282 283 *x_quarters.get_unchecked_mut(2) = transmute($fun( 284 transmute(*x_quarters.get_unchecked(2)), 285 transmute(*y_quarters.get_unchecked(2)), 286 transmute(*z_quarters.get_unchecked(2)), 287 )); 288 289 *x_quarters.get_unchecked_mut(3) = transmute($fun( 290 transmute(*x_quarters.get_unchecked(3)), 291 transmute(*y_quarters.get_unchecked(3)), 292 transmute(*z_quarters.get_unchecked(3)), 293 )); 294 295 U { quarters: x_quarters }.vec 296 } 297 } 298 } 299 }; 300 // implementation calling fun once on a vector twice as large: 301 (twice | $trait_id:ident, $trait_method:ident, $vec_id:ident, 302 $vect_id:ident, $fun:ident) => { 303 impl $trait_id for $vec_id { 304 #[inline] 305 fn $trait_method(self, y: Self, z: Self) -> Self { 306 unsafe { 307 use crate::mem::{transmute, uninitialized}; 308 309 union U { 310 vec: [$vec_id; 2], 311 twice: $vect_id, 312 } 313 314 let x_twice = U { vec: [self, uninitialized()] }.twice; 315 let y_twice = U { vec: [y, uninitialized()] }.twice; 316 let z_twice = U { vec: [z, uninitialized()] }.twice; 317 let twice: $vect_id = transmute($fun( 318 transmute(x_twice), 319 transmute(y_twice), 320 transmute(z_twice), 321 )); 322 323 *(U { twice }.vec.get_unchecked(0)) 324 } 325 } 326 } 327 }; 328 } 329 330 macro_rules! gen_tertiary_impl_table { 331 ($trait_id:ident, $trait_method:ident) => { 332 macro_rules! impl_tertiary { 333 ($vid:ident: $fun:ident) => { 334 impl_tertiary_!(vec | $trait_id, $trait_method, $vid, $fun); 335 }; 336 ($vid:ident[$sid:ident; $sc:expr]: $fun:ident) => { 337 impl_tertiary_!( 338 scalar | $trait_id, 339 $trait_method, 340 $vid, 341 [$sid; $sc], 342 $fun 343 ); 344 }; 345 ($vid:ident[s]: $fun:ident) => { 346 impl_tertiary_!(scalar | $trait_id, $trait_method, $vid, $fun); 347 }; 348 ($vid:ident[h => $vid_h:ident]: $fun:ident) => { 349 impl_tertiary_!( 350 halves | $trait_id, 351 $trait_method, 352 $vid, 353 $vid_h, 354 $fun 355 ); 356 }; 357 ($vid:ident[q => $vid_q:ident]: $fun:ident) => { 358 impl_tertiary_!( 359 quarter | $trait_id, 360 $trait_method, 361 $vid, 362 $vid_q, 363 $fun 364 ); 365 }; 366 ($vid:ident[t => $vid_t:ident]: $fun:ident) => { 367 impl_tertiary_!( 368 twice | $trait_id, 369 $trait_method, 370 $vid, 371 $vid_t, 372 $fun 373 ); 374 }; 375 } 376 }; 377 } 378 379 macro_rules! impl_binary_ { 380 // implementation mapping 1:1 381 (vec | $trait_id:ident, $trait_method:ident, $vec_id:ident, 382 $fun:ident) => { 383 impl $trait_id for $vec_id { 384 #[inline] 385 fn $trait_method(self, y: Self) -> Self { 386 unsafe { 387 use crate::mem::transmute; 388 transmute($fun(transmute(self), transmute(y))) 389 } 390 } 391 } 392 }; 393 (scalar | $trait_id:ident, $trait_method:ident, 394 $vec_id:ident, [$sid:ident; $scount:expr], $fun:ident) => { 395 impl $trait_id for $vec_id { 396 #[inline] 397 fn $trait_method(self, y: Self) -> Self { 398 unsafe { 399 union U { 400 vec: $vec_id, 401 scalars: [$sid; $scount], 402 } 403 let mut x = U { vec: self }.scalars; 404 let y = U { vec: y }.scalars; 405 for (x, y) in x.iter_mut().zip(&y) { 406 *x = $fun(*x, *y); 407 } 408 U { scalars: x }.vec 409 } 410 } 411 } 412 }; 413 // implementation calling fun twice on each of the vector halves: 414 (halves | $trait_id:ident, $trait_method:ident, $vec_id:ident, 415 $vech_id:ident, $fun:ident) => { 416 impl $trait_id for $vec_id { 417 #[inline] 418 fn $trait_method(self, y: Self) -> Self { 419 unsafe { 420 use crate::mem::transmute; 421 union U { 422 vec: $vec_id, 423 halves: [$vech_id; 2], 424 } 425 426 let mut x_halves = U { vec: self }.halves; 427 let y_halves = U { vec: y }.halves; 428 429 *x_halves.get_unchecked_mut(0) = transmute($fun( 430 transmute(*x_halves.get_unchecked(0)), 431 transmute(*y_halves.get_unchecked(0)), 432 )); 433 *x_halves.get_unchecked_mut(1) = transmute($fun( 434 transmute(*x_halves.get_unchecked(1)), 435 transmute(*y_halves.get_unchecked(1)), 436 )); 437 438 U { halves: x_halves }.vec 439 } 440 } 441 } 442 }; 443 // implementation calling fun four times on each of the vector quarters: 444 (quarter | $trait_id:ident, $trait_method:ident, $vec_id:ident, 445 $vecq_id:ident, $fun:ident) => { 446 impl $trait_id for $vec_id { 447 #[inline] 448 fn $trait_method(self, y: Self) -> Self { 449 unsafe { 450 use crate::mem::transmute; 451 union U { 452 vec: $vec_id, 453 quarters: [$vecq_id; 4], 454 } 455 456 let mut x_quarters = U { vec: self }.quarters; 457 let y_quarters = U { vec: y }.quarters; 458 459 *x_quarters.get_unchecked_mut(0) = transmute($fun( 460 transmute(*x_quarters.get_unchecked(0)), 461 transmute(*y_quarters.get_unchecked(0)), 462 )); 463 464 *x_quarters.get_unchecked_mut(1) = transmute($fun( 465 transmute(*x_quarters.get_unchecked(1)), 466 transmute(*y_quarters.get_unchecked(1)), 467 )); 468 469 *x_quarters.get_unchecked_mut(2) = transmute($fun( 470 transmute(*x_quarters.get_unchecked(2)), 471 transmute(*y_quarters.get_unchecked(2)), 472 )); 473 474 *x_quarters.get_unchecked_mut(3) = transmute($fun( 475 transmute(*x_quarters.get_unchecked(3)), 476 transmute(*y_quarters.get_unchecked(3)), 477 )); 478 479 U { quarters: x_quarters }.vec 480 } 481 } 482 } 483 }; 484 // implementation calling fun once on a vector twice as large: 485 (twice | $trait_id:ident, $trait_method:ident, $vec_id:ident, 486 $vect_id:ident, $fun:ident) => { 487 impl $trait_id for $vec_id { 488 #[inline] 489 fn $trait_method(self, y: Self) -> Self { 490 unsafe { 491 use crate::mem::{transmute, uninitialized}; 492 493 union U { 494 vec: [$vec_id; 2], 495 twice: $vect_id, 496 } 497 498 let x_twice = U { vec: [self, uninitialized()] }.twice; 499 let y_twice = U { vec: [y, uninitialized()] }.twice; 500 let twice: $vect_id = transmute($fun( 501 transmute(x_twice), 502 transmute(y_twice), 503 )); 504 505 *(U { twice }.vec.get_unchecked(0)) 506 } 507 } 508 } 509 }; 510 } 511 512 macro_rules! gen_binary_impl_table { 513 ($trait_id:ident, $trait_method:ident) => { 514 macro_rules! impl_binary { 515 ($vid:ident: $fun:ident) => { 516 impl_binary_!(vec | $trait_id, $trait_method, $vid, $fun); 517 }; 518 ($vid:ident[$sid:ident; $sc:expr]: $fun:ident) => { 519 impl_binary_!( 520 scalar | $trait_id, 521 $trait_method, 522 $vid, 523 [$sid; $sc], 524 $fun 525 ); 526 }; 527 ($vid:ident[s]: $fun:ident) => { 528 impl_binary_!(scalar | $trait_id, $trait_method, $vid, $fun); 529 }; 530 ($vid:ident[h => $vid_h:ident]: $fun:ident) => { 531 impl_binary_!( 532 halves | $trait_id, 533 $trait_method, 534 $vid, 535 $vid_h, 536 $fun 537 ); 538 }; 539 ($vid:ident[q => $vid_q:ident]: $fun:ident) => { 540 impl_binary_!( 541 quarter | $trait_id, 542 $trait_method, 543 $vid, 544 $vid_q, 545 $fun 546 ); 547 }; 548 ($vid:ident[t => $vid_t:ident]: $fun:ident) => { 549 impl_binary_!( 550 twice | $trait_id, 551 $trait_method, 552 $vid, 553 $vid_t, 554 $fun 555 ); 556 }; 557 } 558 }; 559 } 560