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}
936