pathfinder_simd/scalar/
mod.rs

1// pathfinder/simd/src/scalar.rs
2//
3// Copyright © 2019 The Pathfinder Project Developers.
4//
5// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8// option. This file may not be copied, modified, or distributed
9// except according to those terms.
10
11use std::f32;
12use std::fmt::{self, Debug, Formatter};
13use std::ops::{Add, BitAnd, BitOr, Div, Index, IndexMut, Mul, Shr, Sub, Not};
14
15mod swizzle_f32x4;
16mod swizzle_i32x4;
17
18// Two 32-bit floats
19
20#[derive(Clone, Copy, Debug, Default, PartialEq)]
21pub struct F32x2(pub [f32; 2]);
22
23impl F32x2 {
24    // Constructors
25
26    #[inline]
27    pub fn new(a: f32, b: f32) -> F32x2 {
28        F32x2([a, b])
29    }
30
31    #[inline]
32    pub fn splat(x: f32) -> F32x2 {
33        F32x2([x, x])
34    }
35
36    // Basic operations
37
38    #[inline]
39    pub fn approx_recip(self) -> F32x2 {
40        F32x2([1.0 / self[0], 1.0 / self[1]])
41    }
42
43    #[inline]
44    pub fn min(self, other: F32x2) -> F32x2 {
45        F32x2([f32::min(self[0], other[0]), f32::min(self[1], other[1])])
46    }
47
48    #[inline]
49    pub fn max(self, other: F32x2) -> F32x2 {
50        F32x2([f32::max(self[0], other[0]), f32::max(self[1], other[1])])
51    }
52
53    #[inline]
54    pub fn clamp(self, min: F32x2, max: F32x2) -> F32x2 {
55        self.max(min).min(max)
56    }
57
58    #[inline]
59    pub fn abs(self) -> F32x2 {
60        F32x2([self[0].abs(), self[1].abs()])
61    }
62
63    #[inline]
64    pub fn floor(self) -> F32x2 {
65        F32x2([self[0].floor(), self[1].floor()])
66    }
67
68    #[inline]
69    pub fn ceil(self) -> F32x2 {
70        F32x2([self[0].ceil(), self[1].ceil()])
71    }
72
73    #[inline]
74    pub fn sqrt(self) -> F32x2 {
75        F32x2([self[0].sqrt(), self[1].sqrt()])
76    }
77
78    // Packed comparisons
79
80    #[inline]
81    pub fn packed_eq(self, other: F32x2) -> U32x2 {
82        U32x2([
83            if self[0] == other[0] { !0 } else { 0 },
84            if self[1] == other[1] { !0 } else { 0 },
85        ])
86    }
87
88    #[inline]
89    pub fn packed_gt(self, other: F32x2) -> U32x2 {
90        U32x2([
91            if self[0] > other[0] { !0 } else { 0 },
92            if self[1] > other[1] { !0 } else { 0 },
93        ])
94    }
95
96    #[inline]
97    pub fn packed_lt(self, other: F32x2) -> U32x2 {
98        U32x2([
99            if self[0] < other[0] { !0 } else { 0 },
100            if self[1] < other[1] { !0 } else { 0 },
101        ])
102    }
103
104    #[inline]
105    pub fn packed_le(self, other: F32x2) -> U32x2 {
106        U32x2([
107            if self[0] <= other[0] { !0 } else { 0 },
108            if self[1] <= other[1] { !0 } else { 0 },
109        ])
110    }
111
112    // Conversions
113
114    #[inline]
115    pub fn to_f32x4(self) -> F32x4 {
116        F32x4([self[0] as f32, self[1] as f32, 0.0, 0.0])
117    }
118
119    /// Converts these packed floats to integers via rounding.
120    #[inline]
121    pub fn to_i32x2(self) -> I32x2 {
122        I32x2([self[0].round() as i32, self[1].round() as i32])
123    }
124
125    /// Converts these packed floats to integers via rounding.
126    #[inline]
127    pub fn to_i32x4(self) -> I32x4 {
128        I32x4([self[0].round() as i32, self[1].round() as i32, 0, 0])
129    }
130
131    // Swizzle
132
133    #[inline]
134    pub fn yx(self) -> F32x2 {
135        F32x2([self[1], self[0]])
136    }
137
138    // Concatenations
139
140    #[inline]
141    pub fn concat_xy_xy(self, other: F32x2) -> F32x4 {
142        F32x4([self[0], self[1], other[0], other[1]])
143    }
144}
145
146impl Index<usize> for F32x2 {
147    type Output = f32;
148    #[inline]
149    fn index(&self, index: usize) -> &f32 {
150        &self.0[index]
151    }
152}
153
154impl IndexMut<usize> for F32x2 {
155    #[inline]
156    fn index_mut(&mut self, index: usize) -> &mut f32 {
157        &mut self.0[index]
158    }
159}
160
161impl Add<F32x2> for F32x2 {
162    type Output = F32x2;
163    #[inline]
164    fn add(self, other: F32x2) -> F32x2 {
165        F32x2([self[0] + other[0], self[1] + other[1]])
166    }
167}
168
169impl Div<F32x2> for F32x2 {
170    type Output = F32x2;
171    #[inline]
172    fn div(self, other: F32x2) -> F32x2 {
173        F32x2([self[0] / other[0], self[1] / other[1]])
174    }
175}
176
177impl Mul<F32x2> for F32x2 {
178    type Output = F32x2;
179    #[inline]
180    fn mul(self, other: F32x2) -> F32x2 {
181        F32x2([self[0] * other[0], self[1] * other[1]])
182    }
183}
184
185impl Sub<F32x2> for F32x2 {
186    type Output = F32x2;
187    #[inline]
188    fn sub(self, other: F32x2) -> F32x2 {
189        F32x2([self[0] - other[0], self[1] - other[1]])
190    }
191}
192
193// Four 32-bit floats
194
195#[derive(Clone, Copy, Default, PartialEq)]
196pub struct F32x4(pub [f32; 4]);
197
198impl F32x4 {
199    #[inline]
200    pub fn new(a: f32, b: f32, c: f32, d: f32) -> F32x4 {
201        F32x4([a, b, c, d])
202    }
203
204    #[inline]
205    pub fn splat(x: f32) -> F32x4 {
206        F32x4([x; 4])
207    }
208
209    // Basic operations
210
211    #[inline]
212    pub fn approx_recip(self) -> F32x4 {
213        F32x4([1.0 / self[0], 1.0 / self[1], 1.0 / self[2], 1.0 / self[3]])
214    }
215
216    #[inline]
217    pub fn min(self, other: F32x4) -> F32x4 {
218        F32x4([
219            self[0].min(other[0]),
220            self[1].min(other[1]),
221            self[2].min(other[2]),
222            self[3].min(other[3]),
223        ])
224    }
225
226    #[inline]
227    pub fn max(self, other: F32x4) -> F32x4 {
228        F32x4([
229            self[0].max(other[0]),
230            self[1].max(other[1]),
231            self[2].max(other[2]),
232            self[3].max(other[3]),
233        ])
234    }
235
236    #[inline]
237    pub fn clamp(self, min: F32x4, max: F32x4) -> F32x4 {
238        self.max(min).min(max)
239    }
240
241    #[inline]
242    pub fn abs(self) -> F32x4 {
243        F32x4([self[0].abs(), self[1].abs(), self[2].abs(), self[3].abs()])
244    }
245
246    #[inline]
247    pub fn floor(self) -> F32x4 {
248        F32x4([
249            self[0].floor(),
250            self[1].floor(),
251            self[2].floor(),
252            self[3].floor(),
253        ])
254    }
255
256    #[inline]
257    pub fn ceil(self) -> F32x4 {
258        F32x4([
259            self[0].ceil(),
260            self[1].ceil(),
261            self[2].ceil(),
262            self[3].ceil(),
263        ])
264    }
265
266    #[inline]
267    pub fn sqrt(self) -> F32x4 {
268        F32x4([
269            self[0].sqrt(),
270            self[1].sqrt(),
271            self[2].sqrt(),
272            self[3].sqrt(),
273        ])
274    }
275
276    // Packed comparisons
277
278    #[inline]
279    pub fn packed_eq(self, other: F32x4) -> U32x4 {
280        U32x4([
281            if self[0] == other[0] { !0 } else { 0 },
282            if self[1] == other[1] { !0 } else { 0 },
283            if self[2] == other[2] { !0 } else { 0 },
284            if self[3] == other[3] { !0 } else { 0 },
285        ])
286    }
287
288    #[inline]
289    pub fn packed_gt(self, other: F32x4) -> U32x4 {
290        U32x4([
291            if self[0] > other[0] { !0 } else { 0 },
292            if self[1] > other[1] { !0 } else { 0 },
293            if self[2] > other[2] { !0 } else { 0 },
294            if self[3] > other[3] { !0 } else { 0 },
295        ])
296    }
297
298    #[inline]
299    pub fn packed_le(self, other: F32x4) -> U32x4 {
300        U32x4([
301            if self[0] <= other[0] { !0 } else { 0 },
302            if self[1] <= other[1] { !0 } else { 0 },
303            if self[2] <= other[2] { !0 } else { 0 },
304            if self[3] <= other[3] { !0 } else { 0 },
305        ])
306    }
307
308    #[inline]
309    pub fn packed_lt(self, other: F32x4) -> U32x4 {
310        U32x4([
311            if self[0] < other[0] { !0 } else { 0 },
312            if self[1] < other[1] { !0 } else { 0 },
313            if self[2] < other[2] { !0 } else { 0 },
314            if self[3] < other[3] { !0 } else { 0 },
315        ])
316    }
317
318    /// Converts these packed floats to integers via rounding.
319    #[inline]
320    pub fn to_i32x4(self) -> I32x4 {
321        I32x4([
322            self[0].round() as i32,
323            self[1].round() as i32,
324            self[2].round() as i32,
325            self[3].round() as i32,
326        ])
327    }
328
329    // Swizzle conversions
330
331    #[inline]
332    pub fn xy(self) -> F32x2 {
333        F32x2([self[0], self[1]])
334    }
335
336    #[inline]
337    pub fn xw(self) -> F32x2 {
338        F32x2([self[0], self[3]])
339    }
340
341    #[inline]
342    pub fn yx(self) -> F32x2 {
343        F32x2([self[1], self[0]])
344    }
345
346    #[inline]
347    pub fn zy(self) -> F32x2 {
348        F32x2([self[2], self[1]])
349    }
350
351    #[inline]
352    pub fn zw(self) -> F32x2 {
353        F32x2([self[2], self[3]])
354    }
355
356    // Concatenations
357
358    #[inline]
359    pub fn concat_xy_xy(self, other: F32x4) -> F32x4 {
360        F32x4([self[0], self[1], other[0], other[1]])
361    }
362
363    #[inline]
364    pub fn concat_xy_zw(self, other: F32x4) -> F32x4 {
365        F32x4([self[0], self[1], other[2], other[3]])
366    }
367
368    #[inline]
369    pub fn concat_zw_zw(self, other: F32x4) -> F32x4 {
370        F32x4([self[2], self[3], other[2], other[3]])
371    }
372
373    #[inline]
374    pub fn concat_wz_yx(self, other: F32x4) -> F32x4 {
375        F32x4([self[3], self[2], other[1], other[0]])
376    }
377}
378
379impl Index<usize> for F32x4 {
380    type Output = f32;
381    #[inline]
382    fn index(&self, index: usize) -> &f32 {
383        &self.0[index]
384    }
385}
386
387impl IndexMut<usize> for F32x4 {
388    #[inline]
389    fn index_mut(&mut self, index: usize) -> &mut f32 {
390        &mut self.0[index]
391    }
392}
393
394impl Debug for F32x4 {
395    #[inline]
396    fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
397        write!(f, "<{}, {}, {}, {}>", self[0], self[1], self[2], self[3])
398    }
399}
400
401impl Add<F32x4> for F32x4 {
402    type Output = F32x4;
403    #[inline]
404    fn add(self, other: F32x4) -> F32x4 {
405        F32x4([
406            self[0] + other[0],
407            self[1] + other[1],
408            self[2] + other[2],
409            self[3] + other[3],
410        ])
411    }
412}
413
414impl Div<F32x4> for F32x4 {
415    type Output = F32x4;
416    #[inline]
417    fn div(self, other: F32x4) -> F32x4 {
418        F32x4([
419            self[0] / other[0],
420            self[1] / other[1],
421            self[2] / other[2],
422            self[3] / other[3],
423        ])
424    }
425}
426
427impl Mul<F32x4> for F32x4 {
428    type Output = F32x4;
429    #[inline]
430    fn mul(self, other: F32x4) -> F32x4 {
431        F32x4([
432            self[0] * other[0],
433            self[1] * other[1],
434            self[2] * other[2],
435            self[3] * other[3],
436        ])
437    }
438}
439
440impl Sub<F32x4> for F32x4 {
441    type Output = F32x4;
442    #[inline]
443    fn sub(self, other: F32x4) -> F32x4 {
444        F32x4([
445            self[0] - other[0],
446            self[1] - other[1],
447            self[2] - other[2],
448            self[3] - other[3],
449        ])
450    }
451}
452
453// Two 32-bit signed integers
454
455#[derive(Clone, Copy, Default, Debug, PartialEq)]
456pub struct I32x2([i32; 2]);
457
458impl I32x2 {
459    #[inline]
460    pub fn new(x: i32, y: i32) -> I32x2 {
461        I32x2([x, y])
462    }
463
464    #[inline]
465    pub fn splat(x: i32) -> I32x2 {
466        I32x2([x, x])
467    }
468
469    // Accessors
470
471    #[inline]
472    pub fn x(self) -> i32 {
473        self[0]
474    }
475
476    #[inline]
477    pub fn y(self) -> i32 {
478        self[1]
479    }
480
481    #[inline]
482    pub fn concat_xy_xy(self, other: I32x2) -> I32x4 {
483        I32x4([self[0], self[1], other[0], other[1]])
484    }
485
486    #[inline]
487    pub fn min(self, other: I32x2) -> I32x2 {
488        I32x2([
489            self[0].min(other[0]),
490            self[1].min(other[1]),
491        ])
492    }
493
494    #[inline]
495    pub fn max(self, other: I32x2) -> I32x2 {
496        I32x2([
497            self[0].max(other[0]),
498            self[1].max(other[1]),
499        ])
500    }
501
502    // Packed comparisons
503
504    #[inline]
505    pub fn packed_eq(self, other: I32x2) -> U32x2 {
506        U32x2([
507            if self[0] == other[0] { !0 } else { 0 },
508            if self[1] == other[1] { !0 } else { 0 },
509        ])
510    }
511
512    #[inline]
513    pub fn packed_gt(self, other: I32x2) -> U32x2 {
514        U32x2([
515            if self[0] > other[0] { !0 } else { 0 },
516            if self[1] > other[1] { !0 } else { 0 },
517        ])
518    }
519
520    #[inline]
521    pub fn packed_le(self, other: I32x2) -> U32x2 {
522        U32x2([
523            if self[0] <= other[0] { !0 } else { 0 },
524            if self[1] <= other[1] { !0 } else { 0 },
525        ])
526    }
527
528    #[inline]
529    pub fn packed_lt(self, other: I32x2) -> U32x2 {
530        U32x2([
531            if self[0] < other[0] { !0 } else { 0 },
532            if self[1] < other[1] { !0 } else { 0 },
533        ])
534    } 
535
536    // Conversions
537
538    /// Converts these packed integers to floats.
539    #[inline]
540    pub fn to_f32x2(self) -> F32x2 {
541        F32x2([self[0] as f32, self[1] as f32])
542    }
543}
544
545impl Index<usize> for I32x2 {
546    type Output = i32;
547    #[inline]
548    fn index(&self, index: usize) -> &i32 {
549        &self.0[index]
550    }
551}
552
553impl IndexMut<usize> for I32x2 {
554    #[inline]
555    fn index_mut(&mut self, index: usize) -> &mut i32 {
556        &mut self.0[index]
557    }
558}
559
560impl Add<I32x2> for I32x2 {
561    type Output = I32x2;
562    #[inline]
563    fn add(self, other: I32x2) -> I32x2 {
564        I32x2([self[0] + other[0], self[1] + other[1]])
565    }
566}
567
568impl Sub<I32x2> for I32x2 {
569    type Output = I32x2;
570    #[inline]
571    fn sub(self, other: I32x2) -> I32x2 {
572        I32x2([self[0] - other[0], self[1] - other[1]])
573    }
574}
575
576impl Mul<I32x2> for I32x2 {
577    type Output = I32x2;
578    #[inline]
579    fn mul(self, other: I32x2) -> I32x2 {
580        I32x2([self[0] * other[0], self[1] * other[1]])
581    }
582}
583
584// Four 32-bit signed integers
585
586#[derive(Clone, Copy, Default, Debug, PartialEq)]
587pub struct I32x4([i32; 4]);
588
589impl I32x4 {
590    #[inline]
591    pub fn new(a: i32, b: i32, c: i32, d: i32) -> I32x4 {
592        I32x4([a, b, c, d])
593    }
594
595    #[inline]
596    pub fn splat(x: i32) -> I32x4 {
597        I32x4([x; 4])
598    }
599
600    // Basic operations
601
602    #[inline]
603    pub fn min(self, other: I32x4) -> I32x4 {
604        I32x4([
605            self[0].min(other[0]),
606            self[1].min(other[1]),
607            self[2].min(other[2]),
608            self[3].min(other[3]),
609        ])
610    }
611
612    #[inline]
613    pub fn max(self, other: I32x4) -> I32x4 {
614        I32x4([
615            self[0].max(other[0]),
616            self[1].max(other[1]),
617            self[2].max(other[2]),
618            self[3].max(other[3]),
619        ])
620    }
621
622    // Packed comparisons
623
624    #[inline]
625    pub fn packed_eq(self, other: I32x4) -> U32x4 {
626        U32x4([
627            if self[0] == other[0] { !0 } else { 0 },
628            if self[1] == other[1] { !0 } else { 0 },
629            if self[2] == other[2] { !0 } else { 0 },
630            if self[3] == other[3] { !0 } else { 0 },
631        ])
632    }
633
634    #[inline]
635    pub fn packed_gt(self, other: I32x4) -> U32x4 {
636        U32x4([
637            if self[0] > other[0] { !0 } else { 0 },
638            if self[1] > other[1] { !0 } else { 0 },
639            if self[2] > other[2] { !0 } else { 0 },
640            if self[3] > other[3] { !0 } else { 0 },
641        ])
642    }
643
644    #[inline]
645    pub fn packed_le(self, other: I32x4) -> U32x4 {
646        U32x4([
647            if self[0] <= other[0] { !0 } else { 0 },
648            if self[1] <= other[1] { !0 } else { 0 },
649            if self[2] <= other[2] { !0 } else { 0 },
650            if self[3] <= other[3] { !0 } else { 0 },
651        ])
652    }
653
654    #[inline]
655    pub fn packed_lt(self, other: I32x4) -> U32x4 {
656        U32x4([
657            if self[0] < other[0] { !0 } else { 0 },
658            if self[1] < other[1] { !0 } else { 0 },
659            if self[2] < other[2] { !0 } else { 0 },
660            if self[3] < other[3] { !0 } else { 0 },
661        ])
662    }
663
664    // Concatenations
665
666    #[inline]
667    pub fn concat_xy_xy(self, other: I32x4) -> I32x4 {
668        I32x4([self[0], self[1], other[0], other[1]])
669    }
670
671    #[inline]
672    pub fn concat_zw_zw(self, other: I32x4) -> I32x4 {
673        I32x4([self[2], self[3], other[2], other[3]])
674    }
675
676    // Swizzle conversions
677
678    #[inline]
679    pub fn xy(self) -> I32x2 {
680        I32x2([self[0], self[1]])
681    }
682
683    #[inline]
684    pub fn xw(self) -> I32x2 {
685        I32x2([self[0], self[3]])
686    }
687
688    #[inline]
689    pub fn zy(self) -> I32x2 {
690        I32x2([self[2], self[1]])
691    }
692
693    #[inline]
694    pub fn zw(self) -> I32x2 {
695        I32x2([self[2], self[3]])
696    }
697
698    // Conversions
699
700    /// Converts these packed integers to floats.
701    #[inline]
702    pub fn to_f32x4(self) -> F32x4 {
703        F32x4([
704            self[0] as f32,
705            self[1] as f32,
706            self[2] as f32,
707            self[3] as f32,
708        ])
709    }
710
711    /// Converts these packed signed integers to unsigned integers.
712    ///
713    /// Overflowing values will wrap around.
714    ///
715    /// FIXME(pcwalton): Should they? This will assert on overflow in debug.
716    #[inline]
717    pub fn to_u32x4(self) -> U32x4 {
718        U32x4([self[0] as u32, self[1] as u32, self[2] as u32, self[3] as u32])
719    }
720}
721
722impl Index<usize> for I32x4 {
723    type Output = i32;
724    #[inline]
725    fn index(&self, index: usize) -> &i32 {
726        &self.0[index]
727    }
728}
729
730impl IndexMut<usize> for I32x4 {
731    #[inline]
732    fn index_mut(&mut self, index: usize) -> &mut i32 {
733        &mut self.0[index]
734    }
735}
736
737impl Add<I32x4> for I32x4 {
738    type Output = I32x4;
739    #[inline]
740    fn add(self, other: I32x4) -> I32x4 {
741        I32x4([
742            self[0] + other[0],
743            self[1] + other[1],
744            self[2] + other[2],
745            self[3] + other[3],
746        ])
747    }
748}
749
750impl Sub<I32x4> for I32x4 {
751    type Output = I32x4;
752    #[inline]
753    fn sub(self, other: I32x4) -> I32x4 {
754        I32x4([
755            self[0] - other[0],
756            self[1] - other[1],
757            self[2] - other[2],
758            self[3] - other[3],
759        ])
760    }
761}
762
763impl Mul<I32x4> for I32x4 {
764    type Output = I32x4;
765    #[inline]
766    fn mul(self, other: I32x4) -> I32x4 {
767        I32x4([
768            self[0] * other[0],
769            self[1] * other[1],
770            self[2] * other[2],
771            self[3] * other[3],
772        ])
773    }
774}
775
776impl BitAnd<I32x4> for I32x4 {
777    type Output = I32x4;
778    #[inline]
779    fn bitand(self, other: I32x4) -> I32x4 {
780        I32x4([self[0] & other[0], self[1] & other[1], self[2] & other[2], self[3] & other[3]])
781    }
782}
783
784impl BitOr<I32x4> for I32x4 {
785    type Output = I32x4;
786    #[inline]
787    fn bitor(self, other: I32x4) -> I32x4 {
788        I32x4([self[0] | other[0], self[1] | other[1], self[2] | other[2], self[3] | other[3]])
789    }
790}
791
792impl Shr<I32x4> for I32x4 {
793    type Output = I32x4;
794    #[inline]
795    fn shr(self, other: I32x4) -> I32x4 {
796        I32x4([
797            self[0] >> other[0],
798            self[1] >> other[1],
799            self[2] >> other[2],
800            self[3] >> other[3],
801        ])
802    }
803}
804
805// Two 32-bit unsigned integers
806
807#[derive(Clone, Copy)]
808pub struct U32x2(pub [u32; 2]);
809
810impl U32x2 {
811    #[inline]
812    pub fn new(x: u32, y: u32) -> U32x2 {
813        U32x2([x, y])
814    }
815
816    #[inline]
817    pub fn splat(x: u32) -> U32x2 {
818        U32x2::new(x, x)
819    }
820
821    /// Returns true if both booleans in this vector are true.
822    ///
823    /// The result is *undefined* if both values in this vector are not booleans. A boolean is a
824    /// value with all bits set or all bits clear (i.e. !0 or 0).
825    #[inline]
826    pub fn all_true(&self) -> bool {
827        self[0] == !0 && self[1] == !0
828    }
829
830    /// Returns true if both booleans in this vector are false.
831    ///
832    /// The result is *undefined* if both values in this vector are not booleans. A boolean is a
833    /// value with all bits set or all bits clear (i.e. !0 or 0).
834    #[inline]
835    pub fn all_false(&self) -> bool {
836        self[0] == 0 && self[1] == 0
837    }
838
839    #[inline]
840    pub fn to_i32x2(self) -> I32x2 {
841        I32x2::new(self[0] as i32, self[1] as i32)
842    }
843
844}
845
846impl BitAnd<U32x2> for U32x2 {
847    type Output = U32x2;
848    #[inline]
849    fn bitand(self, other: U32x2) -> U32x2 {
850        U32x2([self[0] & other[0], self[1] & other[1]])
851    }
852}
853
854impl BitOr<U32x2> for U32x2 {
855    type Output = U32x2;
856    #[inline]
857    fn bitor(self, other: U32x2) -> U32x2 {
858        U32x2([self[0] | other[0], self[1] | other[1]])
859    }
860}
861
862impl Not for U32x2 {
863    type Output = U32x2;
864    #[inline]
865    fn not(self) -> U32x2 {
866        U32x2([!self[0], !self[1]])
867    }
868}
869
870impl Index<usize> for U32x2 {
871    type Output = u32;
872    #[inline]
873    fn index(&self, index: usize) -> &u32 {
874        &self.0[index]
875    }
876}
877
878// Four 32-bit unsigned integers
879
880#[derive(Clone, Copy, PartialEq, Eq, Debug)]
881pub struct U32x4(pub [u32; 4]);
882
883impl U32x4 {
884    pub fn new(a: u32, b: u32, c: u32, d: u32) -> U32x4 {
885        U32x4([a, b, c, d])
886    }
887
888    // Conversions
889
890    /// Converts these packed unsigned integers to signed integers.
891    ///
892    /// Overflowing values will wrap around.
893    ///
894    /// FIXME(pcwalton): Should they? This will assert on overflow in debug.
895    #[inline]
896    pub fn to_i32x4(self) -> I32x4 {
897        I32x4([self[0] as i32, self[1] as i32, self[2] as i32, self[3] as i32])
898    }
899
900    // Basic operations
901
902    /// Returns true if all four booleans in this vector are true.
903    ///
904    /// The result is *undefined* if all four values in this vector are not booleans. A boolean is
905    /// a value with all bits set or all bits clear (i.e. !0 or 0).
906    #[inline]
907    pub fn all_true(&self) -> bool {
908        self[0] == !0 && self[1] == !0 && self[2] == !0 && self[3] == !0
909    }
910
911    /// Returns true if all four booleans in this vector are false.
912    ///
913    /// The result is *undefined* if all four values in this vector are not booleans. A boolean is
914    /// a value with all bits set or all bits clear (i.e. !0 or 0).
915    #[inline]
916    pub fn all_false(&self) -> bool {
917        self[0] == 0 && self[1] == 0 && self[2] == 0 && self[3] == 0
918    }
919}
920
921impl Index<usize> for U32x4 {
922    type Output = u32;
923    #[inline]
924    fn index(&self, index: usize) -> &u32 {
925        &self.0[index]
926    }
927}
928
929impl Shr<u32> for U32x4 {
930    type Output = U32x4;
931    #[inline]
932    fn shr(self, amount: u32) -> U32x4 {
933        U32x4([self[0] >> amount, self[1] >> amount, self[2] >> amount, self[3] >> amount])
934    }
935}