surpass/simd/
auto.rs

1// Copyright 2021 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use std::ops::{
6    Add, AddAssign, BitAnd, BitOr, BitOrAssign, BitXor, Div, Mul, MulAssign, Neg, Not, Sub,
7};
8
9#[derive(Clone, Copy, Debug, Default)]
10pub struct m8x16([u8; 16]);
11
12impl m8x16 {
13    pub fn all(self) -> bool {
14        self.0.iter().all(|&val| val == u8::MAX)
15    }
16}
17
18#[derive(Clone, Copy, Debug, Default)]
19pub struct m32x4([u32; 4]);
20
21#[derive(Clone, Copy, Debug, Default)]
22pub struct m32x8([u32; 8]);
23
24impl m32x8 {
25    pub fn all(self) -> bool {
26        self.0.iter().all(|&val| val == u32::MAX)
27    }
28
29    pub fn any(self) -> bool {
30        self.0.contains(&u32::MAX)
31    }
32}
33
34impl Not for m32x8 {
35    type Output = Self;
36
37    fn not(mut self) -> Self::Output {
38        self.0.iter_mut().for_each(|t| *t = !*t);
39        self
40    }
41}
42
43impl BitOr for m32x8 {
44    type Output = Self;
45
46    fn bitor(mut self, rhs: Self) -> Self::Output {
47        self.0.iter_mut().zip(rhs.0.iter()).for_each(|(t, &o)| *t |= o);
48        self
49    }
50}
51
52impl BitOrAssign for m32x8 {
53    fn bitor_assign(&mut self, rhs: Self) {
54        *self = *self | rhs;
55    }
56}
57
58impl BitXor for m32x8 {
59    type Output = Self;
60
61    fn bitxor(mut self, rhs: Self) -> Self::Output {
62        self.0.iter_mut().zip(rhs.0.iter()).for_each(|(t, &o)| *t ^= o);
63        self
64    }
65}
66
67#[derive(Clone, Copy, Debug, Default)]
68// Tuple member is never used
69#[allow(dead_code)]
70pub struct u8x8([u8; 8]);
71
72impl From<f32x8> for u8x8 {
73    fn from(val: f32x8) -> Self {
74        Self([
75            val.0[0].round() as u8,
76            val.0[1].round() as u8,
77            val.0[2].round() as u8,
78            val.0[3].round() as u8,
79            val.0[4].round() as u8,
80            val.0[5].round() as u8,
81            val.0[6].round() as u8,
82            val.0[7].round() as u8,
83        ])
84    }
85}
86
87#[derive(Clone, Copy, Debug, Default)]
88// Tuple member is never used
89#[allow(dead_code)]
90pub struct u8x32([u8; 32]);
91
92impl u8x32 {
93    pub fn splat(val: u8) -> Self {
94        Self([
95            val, val, val, val, val, val, val, val, val, val, val, val, val, val, val, val, val,
96            val, val, val, val, val, val, val, val, val, val, val, val, val, val, val,
97        ])
98    }
99
100    pub fn from_u32_interleaved(vals: [u32x8; 4]) -> Self {
101        Self([
102            vals[0].0[0] as u8,
103            vals[1].0[0] as u8,
104            vals[2].0[0] as u8,
105            vals[3].0[0] as u8,
106            vals[0].0[1] as u8,
107            vals[1].0[1] as u8,
108            vals[2].0[1] as u8,
109            vals[3].0[1] as u8,
110            vals[0].0[2] as u8,
111            vals[1].0[2] as u8,
112            vals[2].0[2] as u8,
113            vals[3].0[2] as u8,
114            vals[0].0[3] as u8,
115            vals[1].0[3] as u8,
116            vals[2].0[3] as u8,
117            vals[3].0[3] as u8,
118            vals[0].0[4] as u8,
119            vals[1].0[4] as u8,
120            vals[2].0[4] as u8,
121            vals[3].0[4] as u8,
122            vals[0].0[5] as u8,
123            vals[1].0[5] as u8,
124            vals[2].0[5] as u8,
125            vals[3].0[5] as u8,
126            vals[0].0[6] as u8,
127            vals[1].0[6] as u8,
128            vals[2].0[6] as u8,
129            vals[3].0[6] as u8,
130            vals[0].0[7] as u8,
131            vals[1].0[7] as u8,
132            vals[2].0[7] as u8,
133            vals[3].0[7] as u8,
134        ])
135    }
136}
137
138#[derive(Clone, Copy, Debug, Default)]
139pub struct i8x16([i8; 16]);
140
141impl i8x16 {
142    pub fn splat(val: i8) -> Self {
143        Self([val, val, val, val, val, val, val, val, val, val, val, val, val, val, val, val])
144    }
145
146    #[cfg(test)]
147    pub fn as_mut_array(&mut self) -> &mut [i8; 16] {
148        &mut self.0
149    }
150
151    pub fn eq(self, other: Self) -> m8x16 {
152        m8x16([
153            if self.0[0] == other.0[0] { u8::MAX } else { 0 },
154            if self.0[1] == other.0[1] { u8::MAX } else { 0 },
155            if self.0[2] == other.0[2] { u8::MAX } else { 0 },
156            if self.0[3] == other.0[3] { u8::MAX } else { 0 },
157            if self.0[4] == other.0[4] { u8::MAX } else { 0 },
158            if self.0[5] == other.0[5] { u8::MAX } else { 0 },
159            if self.0[6] == other.0[6] { u8::MAX } else { 0 },
160            if self.0[7] == other.0[7] { u8::MAX } else { 0 },
161            if self.0[8] == other.0[8] { u8::MAX } else { 0 },
162            if self.0[9] == other.0[9] { u8::MAX } else { 0 },
163            if self.0[10] == other.0[10] { u8::MAX } else { 0 },
164            if self.0[11] == other.0[11] { u8::MAX } else { 0 },
165            if self.0[12] == other.0[12] { u8::MAX } else { 0 },
166            if self.0[13] == other.0[13] { u8::MAX } else { 0 },
167            if self.0[14] == other.0[14] { u8::MAX } else { 0 },
168            if self.0[15] == other.0[15] { u8::MAX } else { 0 },
169        ])
170    }
171
172    pub fn abs(mut self) -> Self {
173        self.0.iter_mut().for_each(|val| *val = val.abs());
174        self
175    }
176}
177
178impl Add for i8x16 {
179    type Output = Self;
180
181    fn add(mut self, rhs: Self) -> Self::Output {
182        self.0.iter_mut().zip(rhs.0.iter()).for_each(|(t, &o)| *t += o);
183        self
184    }
185}
186
187impl AddAssign for i8x16 {
188    fn add_assign(&mut self, rhs: Self) {
189        *self = *self + rhs;
190    }
191}
192
193impl BitAnd for i8x16 {
194    type Output = Self;
195
196    fn bitand(mut self, rhs: Self) -> Self::Output {
197        self.0.iter_mut().zip(rhs.0.iter()).for_each(|(t, &o)| *t &= o);
198        self
199    }
200}
201
202impl From<i8x16> for [i32x8; 2] {
203    fn from(val: i8x16) -> Self {
204        [
205            i32x8([
206                val.0[0] as i32,
207                val.0[1] as i32,
208                val.0[2] as i32,
209                val.0[3] as i32,
210                val.0[4] as i32,
211                val.0[5] as i32,
212                val.0[6] as i32,
213                val.0[7] as i32,
214            ]),
215            i32x8([
216                val.0[8] as i32,
217                val.0[9] as i32,
218                val.0[10] as i32,
219                val.0[11] as i32,
220                val.0[12] as i32,
221                val.0[13] as i32,
222                val.0[14] as i32,
223                val.0[15] as i32,
224            ]),
225        ]
226    }
227}
228
229#[derive(Clone, Copy, Debug, Default)]
230pub struct i16x16([i16; 16]);
231
232impl i16x16 {
233    pub fn splat(val: i16) -> Self {
234        Self([val, val, val, val, val, val, val, val, val, val, val, val, val, val, val, val])
235    }
236}
237
238impl From<i16x16> for [i32x8; 2] {
239    fn from(val: i16x16) -> Self {
240        [
241            i32x8([
242                val.0[0] as i32,
243                val.0[1] as i32,
244                val.0[2] as i32,
245                val.0[3] as i32,
246                val.0[4] as i32,
247                val.0[5] as i32,
248                val.0[6] as i32,
249                val.0[7] as i32,
250            ]),
251            i32x8([
252                val.0[8] as i32,
253                val.0[9] as i32,
254                val.0[10] as i32,
255                val.0[11] as i32,
256                val.0[12] as i32,
257                val.0[13] as i32,
258                val.0[14] as i32,
259                val.0[15] as i32,
260            ]),
261        ]
262    }
263}
264
265#[derive(Clone, Copy, Debug, Default)]
266pub struct i32x8([i32; 8]);
267
268impl i32x8 {
269    pub fn splat(val: i32) -> Self {
270        Self([val, val, val, val, val, val, val, val])
271    }
272
273    pub fn eq(self, other: Self) -> m32x8 {
274        m32x8([
275            if self.0[0] == other.0[0] { u32::MAX } else { 0 },
276            if self.0[1] == other.0[1] { u32::MAX } else { 0 },
277            if self.0[2] == other.0[2] { u32::MAX } else { 0 },
278            if self.0[3] == other.0[3] { u32::MAX } else { 0 },
279            if self.0[4] == other.0[4] { u32::MAX } else { 0 },
280            if self.0[5] == other.0[5] { u32::MAX } else { 0 },
281            if self.0[6] == other.0[6] { u32::MAX } else { 0 },
282            if self.0[7] == other.0[7] { u32::MAX } else { 0 },
283        ])
284    }
285
286    pub fn shr<const N: i32>(mut self) -> Self {
287        self.0.iter_mut().for_each(|t| *t >>= N);
288        self
289    }
290
291    pub fn abs(mut self) -> Self {
292        self.0.iter_mut().for_each(|t| *t = t.abs());
293        self
294    }
295}
296
297impl Add for i32x8 {
298    type Output = Self;
299
300    fn add(mut self, rhs: Self) -> Self::Output {
301        self.0.iter_mut().zip(rhs.0.iter()).for_each(|(t, &o)| *t += o);
302        self
303    }
304}
305
306impl Sub for i32x8 {
307    type Output = Self;
308
309    fn sub(mut self, rhs: Self) -> Self::Output {
310        self.0.iter_mut().zip(rhs.0.iter()).for_each(|(t, &o)| *t -= o);
311        self
312    }
313}
314
315impl Mul for i32x8 {
316    type Output = Self;
317
318    fn mul(mut self, rhs: Self) -> Self::Output {
319        self.0.iter_mut().zip(rhs.0.iter()).for_each(|(t, &o)| *t *= o);
320        self
321    }
322}
323
324impl BitAnd for i32x8 {
325    type Output = Self;
326
327    fn bitand(mut self, rhs: Self) -> Self::Output {
328        self.0.iter_mut().zip(rhs.0.iter()).for_each(|(t, &o)| *t &= o);
329        self
330    }
331}
332
333#[derive(Clone, Copy, Debug, Default)]
334pub struct u32x4([u32; 4]);
335
336impl u32x4 {
337    pub fn splat(val: u32) -> Self {
338        Self([val, val, val, val])
339    }
340}
341
342impl From<u32x4> for [u8; 4] {
343    fn from(val: u32x4) -> Self {
344        [val.0[0] as u8, val.0[1] as u8, val.0[2] as u8, val.0[3] as u8]
345    }
346}
347
348#[derive(Clone, Copy, Debug, Default)]
349pub struct u32x8([u32; 8]);
350
351impl u32x8 {
352    pub fn splat(val: u32) -> Self {
353        Self([val, val, val, val, val, val, val, val])
354    }
355
356    pub fn to_array(self) -> [u32; 8] {
357        self.0
358    }
359
360    pub fn mul_add(mut self, a: Self, b: Self) -> Self {
361        self.0.iter_mut().zip(a.0.iter().zip(b.0.iter())).for_each(|(t, (&a, &b))| *t = *t * a + b);
362        self
363    }
364}
365
366impl From<f32x8> for u32x8 {
367    fn from(val: f32x8) -> Self {
368        Self([
369            val.0[0] as u32,
370            val.0[1] as u32,
371            val.0[2] as u32,
372            val.0[3] as u32,
373            val.0[4] as u32,
374            val.0[5] as u32,
375            val.0[6] as u32,
376            val.0[7] as u32,
377        ])
378    }
379}
380
381#[derive(Clone, Copy, Debug, Default)]
382pub struct f32x4([f32; 4]);
383
384impl f32x4 {
385    pub fn new(vals: [f32; 4]) -> Self {
386        Self(vals)
387    }
388
389    pub fn splat(val: f32) -> Self {
390        Self([val, val, val, val])
391    }
392
393    pub fn from_bits(val: u32x4) -> Self {
394        Self([
395            f32::from_bits(val.0[0]),
396            f32::from_bits(val.0[1]),
397            f32::from_bits(val.0[2]),
398            f32::from_bits(val.0[3]),
399        ])
400    }
401
402    pub fn to_bits(self) -> u32x4 {
403        u32x4([self.0[0].to_bits(), self.0[1].to_bits(), self.0[2].to_bits(), self.0[3].to_bits()])
404    }
405
406    pub fn set<const INDEX: i32>(mut self, val: f32) -> Self {
407        self.0[INDEX as usize] = val;
408        self
409    }
410
411    pub fn le(self, other: Self) -> m32x4 {
412        m32x4([
413            if self.0[0] <= other.0[0] { u32::MAX } else { 0 },
414            if self.0[1] <= other.0[1] { u32::MAX } else { 0 },
415            if self.0[2] <= other.0[2] { u32::MAX } else { 0 },
416            if self.0[3] <= other.0[3] { u32::MAX } else { 0 },
417        ])
418    }
419
420    pub fn select(self, other: Self, mask: m32x4) -> Self {
421        Self([
422            if mask.0[0] == u32::MAX { self.0[0] } else { other.0[0] },
423            if mask.0[1] == u32::MAX { self.0[1] } else { other.0[1] },
424            if mask.0[2] == u32::MAX { self.0[2] } else { other.0[2] },
425            if mask.0[3] == u32::MAX { self.0[3] } else { other.0[3] },
426        ])
427    }
428
429    pub fn clamp(mut self, min: Self, max: Self) -> Self {
430        self.0
431            .iter_mut()
432            .zip(min.0.iter().zip(max.0.iter()))
433            .for_each(|(t, (&min, &max))| *t = t.clamp(min, max));
434        self
435    }
436
437    pub fn sqrt(mut self) -> Self {
438        self.0.iter_mut().for_each(|val| *val = val.sqrt());
439        self
440    }
441
442    pub fn mul_add(mut self, a: Self, b: Self) -> Self {
443        self.0
444            .iter_mut()
445            .zip(a.0.iter().zip(b.0.iter()))
446            .for_each(|(t, (&a, &b))| *t = t.mul_add(a, b));
447        self
448    }
449}
450
451impl Add for f32x4 {
452    type Output = Self;
453
454    fn add(mut self, rhs: Self) -> Self::Output {
455        self.0.iter_mut().zip(rhs.0.iter()).for_each(|(t, &o)| *t += o);
456        self
457    }
458}
459
460impl Mul for f32x4 {
461    type Output = Self;
462
463    fn mul(mut self, rhs: Self) -> Self::Output {
464        self.0.iter_mut().zip(rhs.0.iter()).for_each(|(t, &o)| *t *= o);
465        self
466    }
467}
468
469#[derive(Clone, Copy, Debug, Default)]
470pub struct f32x8([f32; 8]);
471
472impl f32x8 {
473    pub fn splat(val: f32) -> Self {
474        Self([val, val, val, val, val, val, val, val])
475    }
476
477    pub fn indexed() -> Self {
478        Self::from_array([0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0])
479    }
480
481    pub fn from_array(val: [f32; 8]) -> Self {
482        Self(val)
483    }
484
485    pub fn from_bits(val: u32x8) -> Self {
486        Self([
487            f32::from_bits(val.0[0]),
488            f32::from_bits(val.0[1]),
489            f32::from_bits(val.0[2]),
490            f32::from_bits(val.0[3]),
491            f32::from_bits(val.0[4]),
492            f32::from_bits(val.0[5]),
493            f32::from_bits(val.0[6]),
494            f32::from_bits(val.0[7]),
495        ])
496    }
497
498    pub fn to_bits(self) -> u32x8 {
499        u32x8([
500            self.0[0].to_bits(),
501            self.0[1].to_bits(),
502            self.0[2].to_bits(),
503            self.0[3].to_bits(),
504            self.0[4].to_bits(),
505            self.0[5].to_bits(),
506            self.0[6].to_bits(),
507            self.0[7].to_bits(),
508        ])
509    }
510
511    #[cfg(test)]
512    pub fn to_array(self) -> [f32; 8] {
513        self.0
514    }
515
516    pub fn eq(self, other: Self) -> m32x8 {
517        m32x8([
518            if self.0[0] == other.0[0] { u32::MAX } else { 0 },
519            if self.0[1] == other.0[1] { u32::MAX } else { 0 },
520            if self.0[2] == other.0[2] { u32::MAX } else { 0 },
521            if self.0[3] == other.0[3] { u32::MAX } else { 0 },
522            if self.0[4] == other.0[4] { u32::MAX } else { 0 },
523            if self.0[5] == other.0[5] { u32::MAX } else { 0 },
524            if self.0[6] == other.0[6] { u32::MAX } else { 0 },
525            if self.0[7] == other.0[7] { u32::MAX } else { 0 },
526        ])
527    }
528
529    pub fn lt(self, other: Self) -> m32x8 {
530        m32x8([
531            if self.0[0] < other.0[0] { u32::MAX } else { 0 },
532            if self.0[1] < other.0[1] { u32::MAX } else { 0 },
533            if self.0[2] < other.0[2] { u32::MAX } else { 0 },
534            if self.0[3] < other.0[3] { u32::MAX } else { 0 },
535            if self.0[4] < other.0[4] { u32::MAX } else { 0 },
536            if self.0[5] < other.0[5] { u32::MAX } else { 0 },
537            if self.0[6] < other.0[6] { u32::MAX } else { 0 },
538            if self.0[7] < other.0[7] { u32::MAX } else { 0 },
539        ])
540    }
541
542    pub fn le(self, other: Self) -> m32x8 {
543        m32x8([
544            if self.0[0] <= other.0[0] { u32::MAX } else { 0 },
545            if self.0[1] <= other.0[1] { u32::MAX } else { 0 },
546            if self.0[2] <= other.0[2] { u32::MAX } else { 0 },
547            if self.0[3] <= other.0[3] { u32::MAX } else { 0 },
548            if self.0[4] <= other.0[4] { u32::MAX } else { 0 },
549            if self.0[5] <= other.0[5] { u32::MAX } else { 0 },
550            if self.0[6] <= other.0[6] { u32::MAX } else { 0 },
551            if self.0[7] <= other.0[7] { u32::MAX } else { 0 },
552        ])
553    }
554
555    pub fn select(self, other: Self, mask: m32x8) -> Self {
556        Self([
557            if mask.0[0] == u32::MAX { self.0[0] } else { other.0[0] },
558            if mask.0[1] == u32::MAX { self.0[1] } else { other.0[1] },
559            if mask.0[2] == u32::MAX { self.0[2] } else { other.0[2] },
560            if mask.0[3] == u32::MAX { self.0[3] } else { other.0[3] },
561            if mask.0[4] == u32::MAX { self.0[4] } else { other.0[4] },
562            if mask.0[5] == u32::MAX { self.0[5] } else { other.0[5] },
563            if mask.0[6] == u32::MAX { self.0[6] } else { other.0[6] },
564            if mask.0[7] == u32::MAX { self.0[7] } else { other.0[7] },
565        ])
566    }
567
568    pub fn abs(mut self) -> Self {
569        self.0.iter_mut().for_each(|val| *val = val.abs());
570        self
571    }
572
573    pub fn min(mut self, other: Self) -> Self {
574        self.0.iter_mut().zip(other.0.iter()).for_each(|(t, &o)| *t = t.min(o));
575        self
576    }
577
578    pub fn max(mut self, other: Self) -> Self {
579        self.0.iter_mut().zip(other.0.iter()).for_each(|(t, &o)| *t = t.max(o));
580        self
581    }
582
583    pub fn clamp(mut self, min: Self, max: Self) -> Self {
584        self.0
585            .iter_mut()
586            .zip(min.0.iter().zip(max.0.iter()))
587            .for_each(|(t, (&min, &max))| *t = t.clamp(min, max));
588        self
589    }
590
591    pub fn sqrt(mut self) -> Self {
592        self.0.iter_mut().for_each(|val| *val = val.sqrt());
593        self
594    }
595
596    pub fn recip(mut self) -> Self {
597        self.0.iter_mut().for_each(|val| *val = val.recip());
598        self
599    }
600
601    pub fn mul_add(mut self, a: Self, b: Self) -> Self {
602        self.0
603            .iter_mut()
604            .zip(a.0.iter().zip(b.0.iter()))
605            .for_each(|(t, (&a, &b))| *t = t.mul_add(a, b));
606        self
607    }
608}
609
610impl Add for f32x8 {
611    type Output = Self;
612
613    fn add(mut self, rhs: Self) -> Self::Output {
614        self.0.iter_mut().zip(rhs.0.iter()).for_each(|(t, &o)| *t += o);
615        self
616    }
617}
618
619impl AddAssign for f32x8 {
620    fn add_assign(&mut self, rhs: Self) {
621        *self = *self + rhs;
622    }
623}
624
625impl Sub for f32x8 {
626    type Output = Self;
627
628    fn sub(mut self, rhs: Self) -> Self::Output {
629        self.0.iter_mut().zip(rhs.0.iter()).for_each(|(t, &o)| *t -= o);
630        self
631    }
632}
633
634impl Mul for f32x8 {
635    type Output = Self;
636
637    fn mul(mut self, rhs: Self) -> Self::Output {
638        self.0.iter_mut().zip(rhs.0.iter()).for_each(|(t, &o)| *t *= o);
639        self
640    }
641}
642
643impl MulAssign for f32x8 {
644    fn mul_assign(&mut self, rhs: Self) {
645        *self = *self * rhs;
646    }
647}
648
649impl Div for f32x8 {
650    type Output = Self;
651
652    fn div(mut self, rhs: Self) -> Self::Output {
653        self.0.iter_mut().zip(rhs.0.iter()).for_each(|(t, &o)| *t /= o);
654        self
655    }
656}
657
658impl Neg for f32x8 {
659    type Output = Self;
660
661    fn neg(mut self) -> Self::Output {
662        self.0.iter_mut().for_each(|t| *t = -*t);
663        self
664    }
665}
666
667impl BitOr for f32x8 {
668    type Output = Self;
669
670    fn bitor(mut self, rhs: Self) -> Self::Output {
671        self.0.iter_mut().zip(rhs.0.iter()).for_each(|(t, &o)| {
672            let t_bytes = t.to_ne_bytes();
673            let o_bytes = o.to_ne_bytes();
674
675            *t = f32::from_ne_bytes([
676                t_bytes[0] | o_bytes[0],
677                t_bytes[1] | o_bytes[1],
678                t_bytes[2] | o_bytes[2],
679                t_bytes[3] | o_bytes[3],
680            ]);
681        });
682        self
683    }
684}
685
686impl BitOrAssign for f32x8 {
687    fn bitor_assign(&mut self, rhs: Self) {
688        *self = *self | rhs;
689    }
690}
691
692impl From<i32x8> for f32x8 {
693    fn from(val: i32x8) -> Self {
694        Self([
695            val.0[0] as f32,
696            val.0[1] as f32,
697            val.0[2] as f32,
698            val.0[3] as f32,
699            val.0[4] as f32,
700            val.0[5] as f32,
701            val.0[6] as f32,
702            val.0[7] as f32,
703        ])
704    }
705}