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 | |
11 | use std::f32; |
12 | use std::fmt::{self, Debug, Formatter}; |
13 | use std::ops::{Add, BitAnd, BitOr, Div, Index, IndexMut, Mul, Shr, Sub, Not}; |
14 | |
15 | mod swizzle_f32x4; |
16 | mod swizzle_i32x4; |
17 | |
18 | // Two 32-bit floats |
19 | |
20 | #[derive (Clone, Copy, Debug, Default, PartialEq)] |
21 | pub struct F32x2(pub [f32; 2]); |
22 | |
23 | impl 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 | |
146 | impl Index<usize> for F32x2 { |
147 | type Output = f32; |
148 | #[inline ] |
149 | fn index(&self, index: usize) -> &f32 { |
150 | &self.0[index] |
151 | } |
152 | } |
153 | |
154 | impl IndexMut<usize> for F32x2 { |
155 | #[inline ] |
156 | fn index_mut(&mut self, index: usize) -> &mut f32 { |
157 | &mut self.0[index] |
158 | } |
159 | } |
160 | |
161 | impl 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 | |
169 | impl 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 | |
177 | impl 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 | |
185 | impl 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)] |
196 | pub struct F32x4(pub [f32; 4]); |
197 | |
198 | impl 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 | |
379 | impl Index<usize> for F32x4 { |
380 | type Output = f32; |
381 | #[inline ] |
382 | fn index(&self, index: usize) -> &f32 { |
383 | &self.0[index] |
384 | } |
385 | } |
386 | |
387 | impl IndexMut<usize> for F32x4 { |
388 | #[inline ] |
389 | fn index_mut(&mut self, index: usize) -> &mut f32 { |
390 | &mut self.0[index] |
391 | } |
392 | } |
393 | |
394 | impl 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 | |
401 | impl 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 | |
414 | impl 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 | |
427 | impl 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 | |
440 | impl 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)] |
456 | pub struct I32x2([i32; 2]); |
457 | |
458 | impl 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 | |
545 | impl Index<usize> for I32x2 { |
546 | type Output = i32; |
547 | #[inline ] |
548 | fn index(&self, index: usize) -> &i32 { |
549 | &self.0[index] |
550 | } |
551 | } |
552 | |
553 | impl IndexMut<usize> for I32x2 { |
554 | #[inline ] |
555 | fn index_mut(&mut self, index: usize) -> &mut i32 { |
556 | &mut self.0[index] |
557 | } |
558 | } |
559 | |
560 | impl 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 | |
568 | impl 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 | |
576 | impl 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)] |
587 | pub struct I32x4([i32; 4]); |
588 | |
589 | impl 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 | |
722 | impl Index<usize> for I32x4 { |
723 | type Output = i32; |
724 | #[inline ] |
725 | fn index(&self, index: usize) -> &i32 { |
726 | &self.0[index] |
727 | } |
728 | } |
729 | |
730 | impl IndexMut<usize> for I32x4 { |
731 | #[inline ] |
732 | fn index_mut(&mut self, index: usize) -> &mut i32 { |
733 | &mut self.0[index] |
734 | } |
735 | } |
736 | |
737 | impl 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 | |
750 | impl 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 | |
763 | impl 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 | |
776 | impl 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 | |
784 | impl 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 | |
792 | impl 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)] |
808 | pub struct U32x2(pub [u32; 2]); |
809 | |
810 | impl 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 | |
846 | impl 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 | |
854 | impl 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 | |
862 | impl Not for U32x2 { |
863 | type Output = U32x2; |
864 | #[inline ] |
865 | fn not(self) -> U32x2 { |
866 | U32x2([!self[0], !self[1]]) |
867 | } |
868 | } |
869 | |
870 | impl 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)] |
881 | pub struct U32x4(pub [u32; 4]); |
882 | |
883 | impl 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 | |
921 | impl Index<usize> for U32x4 { |
922 | type Output = u32; |
923 | #[inline ] |
924 | fn index(&self, index: usize) -> &u32 { |
925 | &self.0[index] |
926 | } |
927 | } |
928 | |
929 | impl 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 | |