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