stdsimd bindings work!
[vector-math.git] / src / stdsimd.rs
1 #[cfg(not(feature = "f16"))]
2 use crate::f16::panic_f16_feature_disabled;
3 use crate::{
4 f16::F16,
5 traits::{Bool, Compare, Context, ConvertTo, Float, Int, Make, SInt, Select, UInt},
6 };
7 use core::{
8 marker::PhantomData,
9 ops::{
10 Add, AddAssign, BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Div,
11 DivAssign, Mul, MulAssign, Neg, Not, Rem, RemAssign, Shl, ShlAssign, Shr, ShrAssign, Sub,
12 SubAssign,
13 },
14 };
15 use core_simd::{
16 LanesAtMost32, Mask, Mask16, Mask32, Mask64, Mask8, SimdF32, SimdF64, SimdI16, SimdI32,
17 SimdI64, SimdI8, SimdU16, SimdU32, SimdU64, SimdU8,
18 };
19
20 #[cfg(not(feature = "f16"))]
21 mod f16 {
22 use super::*;
23
24 #[derive(Copy, Clone, Debug)]
25 #[repr(transparent)]
26 pub struct SimdF16<const LANES: usize>(pub(crate) SimdU16<LANES>)
27 where
28 SimdU16<LANES>: LanesAtMost32;
29
30 impl<const LANES: usize> SimdF16<LANES>
31 where
32 SimdU16<LANES>: LanesAtMost32,
33 SimdI16<LANES>: LanesAtMost32,
34 Mask16<LANES>: Mask,
35 {
36 pub(crate) fn splat(_v: F16) -> Self {
37 panic_f16_feature_disabled()
38 }
39 pub(crate) fn abs(self) -> Self {
40 panic_f16_feature_disabled()
41 }
42 pub(crate) fn trunc(self) -> Self {
43 panic_f16_feature_disabled()
44 }
45 pub(crate) fn floor(self) -> Self {
46 panic_f16_feature_disabled()
47 }
48 pub(crate) fn ceil(self) -> Self {
49 panic_f16_feature_disabled()
50 }
51 pub(crate) fn round(self) -> Self {
52 panic_f16_feature_disabled()
53 }
54 pub(crate) fn from_bits(_v: SimdU16<LANES>) -> Self {
55 panic_f16_feature_disabled()
56 }
57 pub(crate) fn to_bits(self) -> SimdU16<LANES> {
58 panic_f16_feature_disabled()
59 }
60 pub(crate) fn is_finite(self) -> Mask16<LANES> {
61 panic_f16_feature_disabled()
62 }
63 pub(crate) fn lanes_eq(self, _rhs: Self) -> Mask16<LANES> {
64 panic_f16_feature_disabled()
65 }
66 pub(crate) fn lanes_ne(self, _rhs: Self) -> Mask16<LANES> {
67 panic_f16_feature_disabled()
68 }
69 pub(crate) fn lanes_gt(self, _rhs: Self) -> Mask16<LANES> {
70 panic_f16_feature_disabled()
71 }
72 pub(crate) fn lanes_ge(self, _rhs: Self) -> Mask16<LANES> {
73 panic_f16_feature_disabled()
74 }
75 pub(crate) fn lanes_lt(self, _rhs: Self) -> Mask16<LANES> {
76 panic_f16_feature_disabled()
77 }
78 pub(crate) fn lanes_le(self, _rhs: Self) -> Mask16<LANES> {
79 panic_f16_feature_disabled()
80 }
81 }
82
83 impl<const LANES: usize> From<[F16; LANES]> for SimdF16<LANES>
84 where
85 SimdU16<LANES>: LanesAtMost32,
86 {
87 fn from(_v: [F16; LANES]) -> Self {
88 panic_f16_feature_disabled()
89 }
90 }
91
92 impl<const LANES: usize> From<SimdF16<LANES>> for [F16; LANES]
93 where
94 SimdU16<LANES>: LanesAtMost32,
95 {
96 fn from(_v: SimdF16<LANES>) -> Self {
97 panic_f16_feature_disabled()
98 }
99 }
100
101 macro_rules! impl_f16_bin_op {
102 ($trait:ident, $fn:ident) => {
103 impl<const LANES: usize> $trait for SimdF16<LANES>
104 where
105 SimdU16<LANES>: LanesAtMost32,
106 {
107 type Output = Self;
108
109 fn $fn(self, _rhs: Self) -> Self::Output {
110 panic_f16_feature_disabled()
111 }
112 }
113 };
114 }
115
116 impl_f16_bin_op!(Add, add);
117 impl_f16_bin_op!(Sub, sub);
118 impl_f16_bin_op!(Mul, mul);
119 impl_f16_bin_op!(Div, div);
120 impl_f16_bin_op!(Rem, rem);
121
122 macro_rules! impl_f16_bin_assign_op {
123 ($trait:ident, $fn:ident) => {
124 impl<const LANES: usize> $trait for SimdF16<LANES>
125 where
126 SimdU16<LANES>: LanesAtMost32,
127 {
128 fn $fn(&mut self, _rhs: Self) {
129 panic_f16_feature_disabled()
130 }
131 }
132 };
133 }
134
135 impl_f16_bin_assign_op!(AddAssign, add_assign);
136 impl_f16_bin_assign_op!(SubAssign, sub_assign);
137 impl_f16_bin_assign_op!(MulAssign, mul_assign);
138 impl_f16_bin_assign_op!(DivAssign, div_assign);
139 impl_f16_bin_assign_op!(RemAssign, rem_assign);
140
141 impl<const LANES: usize> Neg for SimdF16<LANES>
142 where
143 SimdU16<LANES>: LanesAtMost32,
144 {
145 type Output = Self;
146
147 fn neg(self) -> Self::Output {
148 panic_f16_feature_disabled()
149 }
150 }
151 }
152
153 #[cfg(not(feature = "f16"))]
154 use f16::SimdF16;
155
156 #[cfg(feature = "f16")]
157 compile_error!("core_simd doesn't yet support f16");
158
159 #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Default)]
160 pub struct StdSimd<const LANES: usize>(PhantomData<[(); LANES]>);
161
162 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Default)]
163 #[repr(transparent)]
164 pub struct Wrapper<T, const LANES: usize>(pub T, PhantomData<[(); LANES]>);
165
166 impl<T, const LANES: usize> From<T> for Wrapper<T, LANES> {
167 fn from(v: T) -> Self {
168 Wrapper(v, PhantomData)
169 }
170 }
171
172 macro_rules! impl_bin_op_for_wrapper {
173 ($trait:ident, $fn:ident) => {
174 impl<T: $trait<Output = T>, const LANES: usize> $trait for Wrapper<T, LANES> {
175 type Output = Self;
176
177 fn $fn(self, rhs: Self) -> Self::Output {
178 self.0.$fn(rhs.0).into()
179 }
180 }
181 };
182 }
183
184 impl_bin_op_for_wrapper!(Add, add);
185 impl_bin_op_for_wrapper!(Sub, sub);
186 impl_bin_op_for_wrapper!(Mul, mul);
187 impl_bin_op_for_wrapper!(Div, div);
188 impl_bin_op_for_wrapper!(Rem, rem);
189 impl_bin_op_for_wrapper!(Shl, shl);
190 impl_bin_op_for_wrapper!(Shr, shr);
191 impl_bin_op_for_wrapper!(BitAnd, bitand);
192 impl_bin_op_for_wrapper!(BitOr, bitor);
193 impl_bin_op_for_wrapper!(BitXor, bitxor);
194
195 macro_rules! impl_bin_op_assign_for_wrapper {
196 ($trait:ident, $fn:ident) => {
197 impl<T: $trait, const LANES: usize> $trait for Wrapper<T, LANES> {
198 fn $fn(&mut self, rhs: Self) {
199 self.0.$fn(rhs.0);
200 }
201 }
202 };
203 }
204
205 impl_bin_op_assign_for_wrapper!(AddAssign, add_assign);
206 impl_bin_op_assign_for_wrapper!(SubAssign, sub_assign);
207 impl_bin_op_assign_for_wrapper!(MulAssign, mul_assign);
208 impl_bin_op_assign_for_wrapper!(DivAssign, div_assign);
209 impl_bin_op_assign_for_wrapper!(RemAssign, rem_assign);
210 impl_bin_op_assign_for_wrapper!(ShlAssign, shl_assign);
211 impl_bin_op_assign_for_wrapper!(ShrAssign, shr_assign);
212 impl_bin_op_assign_for_wrapper!(BitAndAssign, bitand_assign);
213 impl_bin_op_assign_for_wrapper!(BitOrAssign, bitor_assign);
214 impl_bin_op_assign_for_wrapper!(BitXorAssign, bitxor_assign);
215
216 macro_rules! impl_un_op_for_wrapper {
217 ($trait:ident, $fn:ident) => {
218 impl<T: $trait<Output = T>, const LANES: usize> $trait for Wrapper<T, LANES> {
219 type Output = Self;
220
221 fn $fn(self) -> Self::Output {
222 self.0.$fn().into()
223 }
224 }
225 };
226 }
227
228 impl_un_op_for_wrapper!(Not, not);
229 impl_un_op_for_wrapper!(Neg, neg);
230
231 macro_rules! impl_make_for_scalar {
232 ($ty:ident) => {
233 impl<const LANES: usize> Make for Wrapper<$ty, LANES>
234 where
235 SimdI8<LANES>: LanesAtMost32,
236 SimdU8<LANES>: LanesAtMost32,
237 Mask8<LANES>: Mask,
238 SimdI16<LANES>: LanesAtMost32,
239 SimdU16<LANES>: LanesAtMost32,
240 Mask16<LANES>: Mask,
241 SimdI32<LANES>: LanesAtMost32,
242 SimdU32<LANES>: LanesAtMost32,
243 SimdF32<LANES>: LanesAtMost32,
244 Mask32<LANES>: Mask,
245 SimdI64<LANES>: LanesAtMost32,
246 SimdU64<LANES>: LanesAtMost32,
247 SimdF64<LANES>: LanesAtMost32,
248 Mask64<LANES>: Mask,
249 {
250 type Prim = $ty;
251
252 type Context = StdSimd<LANES>;
253
254 fn ctx(self) -> Self::Context {
255 StdSimd::default()
256 }
257
258 fn make(_ctx: Self::Context, v: Self::Prim) -> Self {
259 v.into()
260 }
261 }
262 };
263 }
264
265 impl_make_for_scalar!(bool);
266 impl_make_for_scalar!(i8);
267 impl_make_for_scalar!(u8);
268 impl_make_for_scalar!(i16);
269 impl_make_for_scalar!(u16);
270 impl_make_for_scalar!(F16);
271 impl_make_for_scalar!(i32);
272 impl_make_for_scalar!(u32);
273 impl_make_for_scalar!(f32);
274 impl_make_for_scalar!(i64);
275 impl_make_for_scalar!(u64);
276 impl_make_for_scalar!(f64);
277
278 impl<V, const LANES: usize> Select<V> for Wrapper<bool, LANES>
279 where
280 SimdI8<LANES>: LanesAtMost32,
281 SimdU8<LANES>: LanesAtMost32,
282 Mask8<LANES>: Mask,
283 SimdI16<LANES>: LanesAtMost32,
284 SimdU16<LANES>: LanesAtMost32,
285 Mask16<LANES>: Mask,
286 SimdI32<LANES>: LanesAtMost32,
287 SimdU32<LANES>: LanesAtMost32,
288 SimdF32<LANES>: LanesAtMost32,
289 Mask32<LANES>: Mask,
290 SimdI64<LANES>: LanesAtMost32,
291 SimdU64<LANES>: LanesAtMost32,
292 SimdF64<LANES>: LanesAtMost32,
293 Mask64<LANES>: Mask,
294 {
295 fn select(self, true_v: V, false_v: V) -> V {
296 self.0.select(true_v, false_v)
297 }
298 }
299
300 macro_rules! impl_scalar_compare {
301 ($ty:ident) => {
302 impl<const LANES: usize> Compare for Wrapper<$ty, LANES>
303 where
304 SimdI8<LANES>: LanesAtMost32,
305 SimdU8<LANES>: LanesAtMost32,
306 Mask8<LANES>: Mask,
307 SimdI16<LANES>: LanesAtMost32,
308 SimdU16<LANES>: LanesAtMost32,
309 Mask16<LANES>: Mask,
310 SimdI32<LANES>: LanesAtMost32,
311 SimdU32<LANES>: LanesAtMost32,
312 SimdF32<LANES>: LanesAtMost32,
313 Mask32<LANES>: Mask,
314 SimdI64<LANES>: LanesAtMost32,
315 SimdU64<LANES>: LanesAtMost32,
316 SimdF64<LANES>: LanesAtMost32,
317 Mask64<LANES>: Mask,
318 {
319 type Bool = Wrapper<bool, LANES>;
320
321 fn eq(self, rhs: Self) -> Self::Bool {
322 self.0.eq(rhs.0).into()
323 }
324
325 fn ne(self, rhs: Self) -> Self::Bool {
326 self.0.ne(rhs.0).into()
327 }
328
329 fn lt(self, rhs: Self) -> Self::Bool {
330 self.0.lt(rhs.0).into()
331 }
332
333 fn gt(self, rhs: Self) -> Self::Bool {
334 self.0.gt(rhs.0).into()
335 }
336
337 fn le(self, rhs: Self) -> Self::Bool {
338 self.0.le(rhs.0).into()
339 }
340
341 fn ge(self, rhs: Self) -> Self::Bool {
342 self.0.ge(rhs.0).into()
343 }
344 }
345 };
346 }
347
348 impl_scalar_compare!(bool);
349 impl_scalar_compare!(i8);
350 impl_scalar_compare!(u8);
351 impl_scalar_compare!(i16);
352 impl_scalar_compare!(u16);
353 impl_scalar_compare!(F16);
354 impl_scalar_compare!(i32);
355 impl_scalar_compare!(u32);
356 impl_scalar_compare!(f32);
357 impl_scalar_compare!(i64);
358 impl_scalar_compare!(u64);
359 impl_scalar_compare!(f64);
360
361 macro_rules! impl_vector_compare {
362 ($ty:ident, $mask:ident) => {
363 impl<const LANES: usize> Compare for Wrapper<$ty<LANES>, LANES>
364 where
365 SimdI8<LANES>: LanesAtMost32,
366 SimdU8<LANES>: LanesAtMost32,
367 Mask8<LANES>: Mask,
368 SimdI16<LANES>: LanesAtMost32,
369 SimdU16<LANES>: LanesAtMost32,
370 Mask16<LANES>: Mask,
371 SimdI32<LANES>: LanesAtMost32,
372 SimdU32<LANES>: LanesAtMost32,
373 SimdF32<LANES>: LanesAtMost32,
374 Mask32<LANES>: Mask,
375 SimdI64<LANES>: LanesAtMost32,
376 SimdU64<LANES>: LanesAtMost32,
377 SimdF64<LANES>: LanesAtMost32,
378 Mask64<LANES>: Mask,
379 {
380 type Bool = Wrapper<$mask<LANES>, LANES>;
381
382 fn eq(self, rhs: Self) -> Self::Bool {
383 self.0.lanes_eq(rhs.0).into()
384 }
385
386 fn ne(self, rhs: Self) -> Self::Bool {
387 self.0.lanes_ne(rhs.0).into()
388 }
389
390 fn lt(self, rhs: Self) -> Self::Bool {
391 self.0.lanes_lt(rhs.0).into()
392 }
393
394 fn gt(self, rhs: Self) -> Self::Bool {
395 self.0.lanes_gt(rhs.0).into()
396 }
397
398 fn le(self, rhs: Self) -> Self::Bool {
399 self.0.lanes_le(rhs.0).into()
400 }
401
402 fn ge(self, rhs: Self) -> Self::Bool {
403 self.0.lanes_ge(rhs.0).into()
404 }
405 }
406 };
407 }
408
409 impl_vector_compare!(SimdI8, Mask8);
410 impl_vector_compare!(SimdU8, Mask8);
411 impl_vector_compare!(SimdI16, Mask16);
412 impl_vector_compare!(SimdU16, Mask16);
413 impl_vector_compare!(SimdF16, Mask16);
414 impl_vector_compare!(SimdI32, Mask32);
415 impl_vector_compare!(SimdU32, Mask32);
416 impl_vector_compare!(SimdF32, Mask32);
417 impl_vector_compare!(SimdI64, Mask64);
418 impl_vector_compare!(SimdU64, Mask64);
419 impl_vector_compare!(SimdF64, Mask64);
420
421 macro_rules! impl_vector_mask_compare {
422 ($ty:ident) => {
423 impl<const LANES: usize> Compare for Wrapper<$ty<LANES>, LANES>
424 where
425 SimdI8<LANES>: LanesAtMost32,
426 SimdU8<LANES>: LanesAtMost32,
427 Mask8<LANES>: Mask,
428 SimdI16<LANES>: LanesAtMost32,
429 SimdU16<LANES>: LanesAtMost32,
430 Mask16<LANES>: Mask,
431 SimdI32<LANES>: LanesAtMost32,
432 SimdU32<LANES>: LanesAtMost32,
433 SimdF32<LANES>: LanesAtMost32,
434 Mask32<LANES>: Mask,
435 SimdI64<LANES>: LanesAtMost32,
436 SimdU64<LANES>: LanesAtMost32,
437 SimdF64<LANES>: LanesAtMost32,
438 Mask64<LANES>: Mask,
439 {
440 type Bool = Self;
441
442 fn eq(self, rhs: Self) -> Self::Bool {
443 !(self ^ rhs)
444 }
445 fn ne(self, rhs: Self) -> Self::Bool {
446 self ^ rhs
447 }
448 fn lt(self, rhs: Self) -> Self::Bool {
449 !self & rhs
450 }
451 fn gt(self, rhs: Self) -> Self::Bool {
452 self & !rhs
453 }
454 fn le(self, rhs: Self) -> Self::Bool {
455 !self | rhs
456 }
457 fn ge(self, rhs: Self) -> Self::Bool {
458 self | !rhs
459 }
460 }
461 };
462 }
463
464 impl_vector_mask_compare!(Mask8);
465 impl_vector_mask_compare!(Mask16);
466 impl_vector_mask_compare!(Mask32);
467 impl_vector_mask_compare!(Mask64);
468
469 macro_rules! impl_int_scalar {
470 ($ty:ident) => {
471 impl<const LANES: usize> Int for Wrapper<$ty, LANES>
472 where
473 SimdI8<LANES>: LanesAtMost32,
474 SimdU8<LANES>: LanesAtMost32,
475 Mask8<LANES>: Mask,
476 SimdI16<LANES>: LanesAtMost32,
477 SimdU16<LANES>: LanesAtMost32,
478 Mask16<LANES>: Mask,
479 SimdI32<LANES>: LanesAtMost32,
480 SimdU32<LANES>: LanesAtMost32,
481 SimdF32<LANES>: LanesAtMost32,
482 Mask32<LANES>: Mask,
483 SimdI64<LANES>: LanesAtMost32,
484 SimdU64<LANES>: LanesAtMost32,
485 SimdF64<LANES>: LanesAtMost32,
486 Mask64<LANES>: Mask,
487 {
488 fn leading_zeros(self) -> Self {
489 (self.0.leading_zeros() as $ty).into()
490 }
491
492 fn trailing_zeros(self) -> Self {
493 (self.0.trailing_zeros() as $ty).into()
494 }
495
496 fn count_ones(self) -> Self {
497 (self.0.count_ones() as $ty).into()
498 }
499
500 fn leading_ones(self) -> Self {
501 (self.0.leading_ones() as $ty).into()
502 }
503
504 fn trailing_ones(self) -> Self {
505 (self.0.trailing_ones() as $ty).into()
506 }
507
508 fn count_zeros(self) -> Self {
509 (self.0.count_zeros() as $ty).into()
510 }
511 }
512 };
513 }
514
515 macro_rules! impl_int_vector {
516 ($ty:ident) => {
517 impl<const LANES: usize> Int for Wrapper<$ty<LANES>, LANES>
518 where
519 SimdI8<LANES>: LanesAtMost32,
520 SimdU8<LANES>: LanesAtMost32,
521 Mask8<LANES>: Mask,
522 SimdI16<LANES>: LanesAtMost32,
523 SimdU16<LANES>: LanesAtMost32,
524 Mask16<LANES>: Mask,
525 SimdI32<LANES>: LanesAtMost32,
526 SimdU32<LANES>: LanesAtMost32,
527 SimdF32<LANES>: LanesAtMost32,
528 Mask32<LANES>: Mask,
529 SimdI64<LANES>: LanesAtMost32,
530 SimdU64<LANES>: LanesAtMost32,
531 SimdF64<LANES>: LanesAtMost32,
532 Mask64<LANES>: Mask,
533 {
534 fn leading_zeros(self) -> Self {
535 todo!()
536 }
537
538 fn trailing_zeros(self) -> Self {
539 todo!()
540 }
541
542 fn count_ones(self) -> Self {
543 todo!()
544 }
545
546 fn leading_ones(self) -> Self {
547 todo!()
548 }
549
550 fn trailing_ones(self) -> Self {
551 todo!()
552 }
553
554 fn count_zeros(self) -> Self {
555 todo!()
556 }
557 }
558 };
559 }
560
561 macro_rules! impl_uint_vector {
562 ($ty:ident) => {
563 impl_int_vector!($ty);
564 impl<const LANES: usize> UInt for Wrapper<$ty<LANES>, LANES>
565 where
566 SimdI8<LANES>: LanesAtMost32,
567 SimdU8<LANES>: LanesAtMost32,
568 Mask8<LANES>: Mask,
569 SimdI16<LANES>: LanesAtMost32,
570 SimdU16<LANES>: LanesAtMost32,
571 Mask16<LANES>: Mask,
572 SimdI32<LANES>: LanesAtMost32,
573 SimdU32<LANES>: LanesAtMost32,
574 SimdF32<LANES>: LanesAtMost32,
575 Mask32<LANES>: Mask,
576 SimdI64<LANES>: LanesAtMost32,
577 SimdU64<LANES>: LanesAtMost32,
578 SimdF64<LANES>: LanesAtMost32,
579 Mask64<LANES>: Mask,
580 {
581 }
582 };
583 }
584
585 impl_uint_vector!(SimdU8);
586 impl_uint_vector!(SimdU16);
587 impl_uint_vector!(SimdU32);
588 impl_uint_vector!(SimdU64);
589
590 macro_rules! impl_uint_scalar {
591 ($ty:ident) => {
592 impl_int_scalar!($ty);
593 impl<const LANES: usize> UInt for Wrapper<$ty, LANES>
594 where
595 SimdI8<LANES>: LanesAtMost32,
596 SimdU8<LANES>: LanesAtMost32,
597 Mask8<LANES>: Mask,
598 SimdI16<LANES>: LanesAtMost32,
599 SimdU16<LANES>: LanesAtMost32,
600 Mask16<LANES>: Mask,
601 SimdI32<LANES>: LanesAtMost32,
602 SimdU32<LANES>: LanesAtMost32,
603 SimdF32<LANES>: LanesAtMost32,
604 Mask32<LANES>: Mask,
605 SimdI64<LANES>: LanesAtMost32,
606 SimdU64<LANES>: LanesAtMost32,
607 SimdF64<LANES>: LanesAtMost32,
608 Mask64<LANES>: Mask,
609 {
610 }
611 };
612 }
613
614 impl_uint_scalar!(u8);
615 impl_uint_scalar!(u16);
616 impl_uint_scalar!(u32);
617 impl_uint_scalar!(u64);
618
619 macro_rules! impl_sint_vector {
620 ($ty:ident) => {
621 impl_int_vector!($ty);
622 impl<const LANES: usize> SInt for Wrapper<$ty<LANES>, LANES>
623 where
624 SimdI8<LANES>: LanesAtMost32,
625 SimdU8<LANES>: LanesAtMost32,
626 Mask8<LANES>: Mask,
627 SimdI16<LANES>: LanesAtMost32,
628 SimdU16<LANES>: LanesAtMost32,
629 Mask16<LANES>: Mask,
630 SimdI32<LANES>: LanesAtMost32,
631 SimdU32<LANES>: LanesAtMost32,
632 SimdF32<LANES>: LanesAtMost32,
633 Mask32<LANES>: Mask,
634 SimdI64<LANES>: LanesAtMost32,
635 SimdU64<LANES>: LanesAtMost32,
636 SimdF64<LANES>: LanesAtMost32,
637 Mask64<LANES>: Mask,
638 {
639 }
640 };
641 }
642
643 impl_sint_vector!(SimdI8);
644 impl_sint_vector!(SimdI16);
645 impl_sint_vector!(SimdI32);
646 impl_sint_vector!(SimdI64);
647
648 macro_rules! impl_sint_scalar {
649 ($ty:ident) => {
650 impl_int_scalar!($ty);
651 impl<const LANES: usize> SInt for Wrapper<$ty, LANES>
652 where
653 SimdI8<LANES>: LanesAtMost32,
654 SimdU8<LANES>: LanesAtMost32,
655 Mask8<LANES>: Mask,
656 SimdI16<LANES>: LanesAtMost32,
657 SimdU16<LANES>: LanesAtMost32,
658 Mask16<LANES>: Mask,
659 SimdI32<LANES>: LanesAtMost32,
660 SimdU32<LANES>: LanesAtMost32,
661 SimdF32<LANES>: LanesAtMost32,
662 Mask32<LANES>: Mask,
663 SimdI64<LANES>: LanesAtMost32,
664 SimdU64<LANES>: LanesAtMost32,
665 SimdF64<LANES>: LanesAtMost32,
666 Mask64<LANES>: Mask,
667 {
668 }
669 };
670 }
671
672 impl_sint_scalar!(i8);
673 impl_sint_scalar!(i16);
674 impl_sint_scalar!(i32);
675 impl_sint_scalar!(i64);
676
677 macro_rules! impl_float {
678 ($ty:ident, $prim:ident, $uint:ident, $sint:ident) => {
679 impl<const LANES: usize> Float for Wrapper<$prim, LANES>
680 where
681 SimdI8<LANES>: LanesAtMost32,
682 SimdU8<LANES>: LanesAtMost32,
683 Mask8<LANES>: Mask,
684 SimdI16<LANES>: LanesAtMost32,
685 SimdU16<LANES>: LanesAtMost32,
686 Mask16<LANES>: Mask,
687 SimdI32<LANES>: LanesAtMost32,
688 SimdU32<LANES>: LanesAtMost32,
689 SimdF32<LANES>: LanesAtMost32,
690 Mask32<LANES>: Mask,
691 SimdI64<LANES>: LanesAtMost32,
692 SimdU64<LANES>: LanesAtMost32,
693 SimdF64<LANES>: LanesAtMost32,
694 Mask64<LANES>: Mask,
695 {
696 type FloatEncoding = $prim;
697
698 type BitsType = Wrapper<<$prim as Float>::BitsType, LANES>;
699
700 type SignedBitsType = Wrapper<<$prim as Float>::SignedBitsType, LANES>;
701
702 fn abs(self) -> Self {
703 self.0.abs().into()
704 }
705
706 fn trunc(self) -> Self {
707 self.0.trunc().into()
708 }
709
710 fn ceil(self) -> Self {
711 self.0.ceil().into()
712 }
713
714 fn floor(self) -> Self {
715 self.0.floor().into()
716 }
717
718 fn round(self) -> Self {
719 self.0.round().into()
720 }
721
722 fn fma(self, a: Self, b: Self) -> Self {
723 self.0.fma(a.0, b.0).into()
724 }
725
726 fn is_finite(self) -> Self::Bool {
727 self.0.is_finite().into()
728 }
729
730 fn from_bits(v: Self::BitsType) -> Self {
731 $prim::from_bits(v.0).into()
732 }
733
734 fn to_bits(self) -> Self::BitsType {
735 self.0.to_bits().into()
736 }
737 }
738
739 impl<const LANES: usize> Float for Wrapper<$ty<LANES>, LANES>
740 where
741 SimdI8<LANES>: LanesAtMost32,
742 SimdU8<LANES>: LanesAtMost32,
743 Mask8<LANES>: Mask,
744 SimdI16<LANES>: LanesAtMost32,
745 SimdU16<LANES>: LanesAtMost32,
746 Mask16<LANES>: Mask,
747 SimdI32<LANES>: LanesAtMost32,
748 SimdU32<LANES>: LanesAtMost32,
749 SimdF32<LANES>: LanesAtMost32,
750 Mask32<LANES>: Mask,
751 SimdI64<LANES>: LanesAtMost32,
752 SimdU64<LANES>: LanesAtMost32,
753 SimdF64<LANES>: LanesAtMost32,
754 Mask64<LANES>: Mask,
755 {
756 type FloatEncoding = $prim;
757
758 type BitsType = Wrapper<$uint<LANES>, LANES>;
759
760 type SignedBitsType = Wrapper<$sint<LANES>, LANES>;
761
762 fn abs(self) -> Self {
763 self.0.abs().into()
764 }
765
766 fn trunc(self) -> Self {
767 self.0.trunc().into()
768 }
769
770 fn ceil(self) -> Self {
771 self.0.ceil().into()
772 }
773
774 fn floor(self) -> Self {
775 self.0.floor().into()
776 }
777
778 fn round(self) -> Self {
779 self.0.round().into()
780 }
781
782 fn fma(self, _a: Self, _b: Self) -> Self {
783 // FIXME(programmerjake): implement once core_simd gains support:
784 // https://github.com/rust-lang/stdsimd/issues/102
785 todo!()
786 }
787
788 fn is_finite(self) -> Self::Bool {
789 self.0.is_finite().into()
790 }
791
792 fn from_bits(v: Self::BitsType) -> Self {
793 $ty::<LANES>::from_bits(v.0).into()
794 }
795
796 fn to_bits(self) -> Self::BitsType {
797 self.0.to_bits().into()
798 }
799 }
800 };
801 }
802
803 impl_float!(SimdF16, F16, SimdU16, SimdI16);
804 impl_float!(SimdF32, f32, SimdU32, SimdI32);
805 impl_float!(SimdF64, f64, SimdU64, SimdI64);
806
807 macro_rules! impl_scalar_convert_to_helper {
808 ($src:ty => $dest:ty) => {
809 impl<const LANES: usize> ConvertTo<Wrapper<$dest, LANES>> for Wrapper<$src, LANES>
810 where
811 SimdI8<LANES>: LanesAtMost32,
812 SimdU8<LANES>: LanesAtMost32,
813 Mask8<LANES>: Mask,
814 SimdI16<LANES>: LanesAtMost32,
815 SimdU16<LANES>: LanesAtMost32,
816 Mask16<LANES>: Mask,
817 SimdI32<LANES>: LanesAtMost32,
818 SimdU32<LANES>: LanesAtMost32,
819 SimdF32<LANES>: LanesAtMost32,
820 Mask32<LANES>: Mask,
821 SimdI64<LANES>: LanesAtMost32,
822 SimdU64<LANES>: LanesAtMost32,
823 SimdF64<LANES>: LanesAtMost32,
824 Mask64<LANES>: Mask,
825 {
826 fn to(self) -> Wrapper<$dest, LANES> {
827 let v: $dest = self.0.to();
828 v.into()
829 }
830 }
831 };
832 }
833
834 macro_rules! impl_scalar_convert_to {
835 ($first:ty $(, $ty:ty)*) => {
836 $(
837 impl_scalar_convert_to_helper!($first => $ty);
838 impl_scalar_convert_to_helper!($ty => $first);
839 )*
840 impl_scalar_convert_to![$($ty),*];
841 };
842 () => {};
843 }
844
845 impl_scalar_convert_to![u8, i8, u16, i16, F16, u32, i32, u64, i64, f32, f64];
846
847 macro_rules! impl_vector_convert_to_helper {
848 (($(#[From = $From:ident])? $src:ident, $src_prim:ident) => ($(#[From = $From2:ident])? $dest:ident, $dest_prim:ident)) => {
849 impl<const LANES: usize> ConvertTo<Wrapper<$dest<LANES>, LANES>>
850 for Wrapper<$src<LANES>, LANES>
851 where
852 SimdI8<LANES>: LanesAtMost32,
853 SimdU8<LANES>: LanesAtMost32,
854 Mask8<LANES>: Mask,
855 SimdI16<LANES>: LanesAtMost32,
856 SimdU16<LANES>: LanesAtMost32,
857 Mask16<LANES>: Mask,
858 SimdI32<LANES>: LanesAtMost32,
859 SimdU32<LANES>: LanesAtMost32,
860 SimdF32<LANES>: LanesAtMost32,
861 Mask32<LANES>: Mask,
862 SimdI64<LANES>: LanesAtMost32,
863 SimdU64<LANES>: LanesAtMost32,
864 SimdF64<LANES>: LanesAtMost32,
865 Mask64<LANES>: Mask,
866 {
867 fn to(self) -> Wrapper<$dest<LANES>, LANES> {
868 // FIXME(programmerjake): workaround https://github.com/rust-lang/stdsimd/issues/116
869 let src: [$src_prim; LANES] = self.0.into();
870 let mut dest: [$dest_prim; LANES] = [Default::default(); LANES];
871 for i in 0..LANES {
872 dest[i] = src[i].to();
873 }
874 $dest::<LANES>::from(dest).into()
875 }
876 }
877
878 $(impl<const LANES: usize> $From<Wrapper<$src<LANES>, LANES>> for Wrapper<$dest<LANES>, LANES>
879 where
880 SimdI8<LANES>: LanesAtMost32,
881 SimdU8<LANES>: LanesAtMost32,
882 Mask8<LANES>: Mask,
883 SimdI16<LANES>: LanesAtMost32,
884 SimdU16<LANES>: LanesAtMost32,
885 Mask16<LANES>: Mask,
886 SimdI32<LANES>: LanesAtMost32,
887 SimdU32<LANES>: LanesAtMost32,
888 SimdF32<LANES>: LanesAtMost32,
889 Mask32<LANES>: Mask,
890 SimdI64<LANES>: LanesAtMost32,
891 SimdU64<LANES>: LanesAtMost32,
892 SimdF64<LANES>: LanesAtMost32,
893 Mask64<LANES>: Mask,
894 {
895 fn from(v: Wrapper<$src<LANES>, LANES>) -> Self {
896 v.to()
897 }
898 })?
899 };
900 }
901
902 macro_rules! impl_vector_convert_to {
903 ($first:tt $(, $ty:tt)*) => {
904 $(
905 impl_vector_convert_to_helper!($first => $ty);
906 impl_vector_convert_to_helper!($ty => $first);
907 )*
908 impl_vector_convert_to![$($ty),*];
909 };
910 () => {};
911 }
912
913 impl_vector_convert_to![
914 (SimdU8, u8),
915 (SimdI8, i8),
916 (SimdU16, u16),
917 (SimdI16, i16),
918 (SimdF16, F16),
919 (SimdU32, u32),
920 (SimdI32, i32),
921 (SimdU64, u64),
922 (SimdI64, i64),
923 (SimdF32, f32),
924 (SimdF64, f64)
925 ];
926
927 impl_vector_convert_to![
928 (
929 #[From = From]
930 Mask8,
931 bool
932 ),
933 (
934 #[From = From]
935 Mask16,
936 bool
937 ),
938 (
939 #[From = From]
940 Mask32,
941 bool
942 ),
943 (
944 #[From = From]
945 Mask64,
946 bool
947 )
948 ];
949
950 macro_rules! impl_from_helper {
951 (#[lanes = $LANES:ident] $src:ty => $dest:ty) => {
952 impl<const $LANES: usize> From<$src> for $dest
953 where
954 SimdI8<LANES>: LanesAtMost32,
955 SimdU8<LANES>: LanesAtMost32,
956 Mask8<LANES>: Mask,
957 SimdI16<LANES>: LanesAtMost32,
958 SimdU16<LANES>: LanesAtMost32,
959 Mask16<LANES>: Mask,
960 SimdI32<LANES>: LanesAtMost32,
961 SimdU32<LANES>: LanesAtMost32,
962 SimdF32<LANES>: LanesAtMost32,
963 Mask32<LANES>: Mask,
964 SimdI64<LANES>: LanesAtMost32,
965 SimdU64<LANES>: LanesAtMost32,
966 SimdF64<LANES>: LanesAtMost32,
967 Mask64<LANES>: Mask,
968 {
969 fn from(v: $src) -> Self {
970 <$src as ConvertTo<$dest>>::to(v)
971 }
972 }
973 };
974 }
975
976 macro_rules! impl_from {
977 (#[lanes = $LANES:ident] $src:ty => [$($dest:ty),*]) => {
978 $(impl_from_helper!(#[lanes = $LANES] $src => $dest);)*
979 };
980 }
981
982 macro_rules! impl_froms {
983 (
984 #[lanes = $LANES:ident]
985 #[u8] $u8:ty;
986 #[i8] $i8:ty;
987 #[u16] $u16:ty;
988 #[i16] $i16:ty;
989 #[f16] $f16:ty;
990 #[u32] $u32:ty;
991 #[i32] $i32:ty;
992 #[f32] $f32:ty;
993 #[u64] $u64:ty;
994 #[i64] $i64:ty;
995 #[f64] $f64:ty;
996 ) => {
997 impl_from!(#[lanes = $LANES] $u8 => [$u16, $i16, $f16, $u32, $i32, $f32, $u64, $i64, $f64]);
998 impl_from!(#[lanes = $LANES] $u16 => [$u32, $i32, $f32, $u64, $i64, $f64]);
999 impl_from!(#[lanes = $LANES] $u32 => [$u64, $i64, $f64]);
1000 impl_from!(#[lanes = $LANES] $i8 => [$i16, $f16, $i32, $f32, $i64, $f64]);
1001 impl_from!(#[lanes = $LANES] $i16 => [$i32, $f32, $i64, $f64]);
1002 impl_from!(#[lanes = $LANES] $i32 => [$i64, $f64]);
1003 impl_from!(#[lanes = $LANES] $f16 => [$f32, $f64]);
1004 impl_from!(#[lanes = $LANES] $f32 => [$f64]);
1005 };
1006 }
1007
1008 impl_froms! {
1009 #[lanes = LANES]
1010 #[u8] Wrapper<u8, LANES>;
1011 #[i8] Wrapper<i8, LANES>;
1012 #[u16] Wrapper<u16, LANES>;
1013 #[i16] Wrapper<i16, LANES>;
1014 #[f16] Wrapper<F16, LANES>;
1015 #[u32] Wrapper<u32, LANES>;
1016 #[i32] Wrapper<i32, LANES>;
1017 #[f32] Wrapper<f32, LANES>;
1018 #[u64] Wrapper<u64, LANES>;
1019 #[i64] Wrapper<i64, LANES>;
1020 #[f64] Wrapper<f64, LANES>;
1021 }
1022
1023 impl_froms! {
1024 #[lanes = LANES]
1025 #[u8] Wrapper<SimdU8<LANES>, LANES>;
1026 #[i8] Wrapper<SimdI8<LANES>, LANES>;
1027 #[u16] Wrapper<SimdU16<LANES>, LANES>;
1028 #[i16] Wrapper<SimdI16<LANES>, LANES>;
1029 #[f16] Wrapper<SimdF16<LANES>, LANES>;
1030 #[u32] Wrapper<SimdU32<LANES>, LANES>;
1031 #[i32] Wrapper<SimdI32<LANES>, LANES>;
1032 #[f32] Wrapper<SimdF32<LANES>, LANES>;
1033 #[u64] Wrapper<SimdU64<LANES>, LANES>;
1034 #[i64] Wrapper<SimdI64<LANES>, LANES>;
1035 #[f64] Wrapper<SimdF64<LANES>, LANES>;
1036 }
1037
1038 macro_rules! impl_select {
1039 ($mask:ident, $ty:ident) => {
1040 impl<const LANES: usize> Select<Wrapper<$ty<LANES>, LANES>> for Wrapper<$mask<LANES>, LANES>
1041 where
1042 SimdI8<LANES>: LanesAtMost32,
1043 SimdU8<LANES>: LanesAtMost32,
1044 Mask8<LANES>: Mask,
1045 SimdI16<LANES>: LanesAtMost32,
1046 SimdU16<LANES>: LanesAtMost32,
1047 Mask16<LANES>: Mask,
1048 SimdI32<LANES>: LanesAtMost32,
1049 SimdU32<LANES>: LanesAtMost32,
1050 SimdF32<LANES>: LanesAtMost32,
1051 Mask32<LANES>: Mask,
1052 SimdI64<LANES>: LanesAtMost32,
1053 SimdU64<LANES>: LanesAtMost32,
1054 SimdF64<LANES>: LanesAtMost32,
1055 Mask64<LANES>: Mask,
1056 {
1057 fn select(
1058 self,
1059 true_v: Wrapper<$ty<LANES>, LANES>,
1060 false_v: Wrapper<$ty<LANES>, LANES>,
1061 ) -> Wrapper<$ty<LANES>, LANES> {
1062 self.0.select(true_v.0, false_v.0).into()
1063 }
1064 }
1065 };
1066 }
1067
1068 impl_select!(Mask8, SimdU8);
1069 impl_select!(Mask8, SimdI8);
1070 impl_select!(Mask16, SimdU16);
1071 impl_select!(Mask16, SimdI16);
1072 impl_select!(Mask32, SimdU32);
1073 impl_select!(Mask32, SimdI32);
1074 impl_select!(Mask32, SimdF32);
1075 impl_select!(Mask64, SimdU64);
1076 impl_select!(Mask64, SimdI64);
1077 impl_select!(Mask64, SimdF64);
1078
1079 #[cfg(not(feature = "f16"))]
1080 impl<const LANES: usize> Select<Wrapper<SimdF16<LANES>, LANES>> for Wrapper<Mask16<LANES>, LANES>
1081 where
1082 SimdI8<LANES>: LanesAtMost32,
1083 SimdU8<LANES>: LanesAtMost32,
1084 Mask8<LANES>: Mask,
1085 SimdI16<LANES>: LanesAtMost32,
1086 SimdU16<LANES>: LanesAtMost32,
1087 Mask16<LANES>: Mask,
1088 SimdI32<LANES>: LanesAtMost32,
1089 SimdU32<LANES>: LanesAtMost32,
1090 SimdF32<LANES>: LanesAtMost32,
1091 Mask32<LANES>: Mask,
1092 SimdI64<LANES>: LanesAtMost32,
1093 SimdU64<LANES>: LanesAtMost32,
1094 SimdF64<LANES>: LanesAtMost32,
1095 Mask64<LANES>: Mask,
1096 {
1097 fn select(
1098 self,
1099 _true_v: Wrapper<SimdF16<LANES>, LANES>,
1100 _false_v: Wrapper<SimdF16<LANES>, LANES>,
1101 ) -> Wrapper<SimdF16<LANES>, LANES> {
1102 panic_f16_feature_disabled()
1103 }
1104 }
1105
1106 macro_rules! impl_select_mask {
1107 ($ty:ident) => {
1108 impl<const LANES: usize> Select<Self> for Wrapper<$ty<LANES>, LANES>
1109 where
1110 SimdI8<LANES>: LanesAtMost32,
1111 SimdU8<LANES>: LanesAtMost32,
1112 Mask8<LANES>: Mask,
1113 SimdI16<LANES>: LanesAtMost32,
1114 SimdU16<LANES>: LanesAtMost32,
1115 Mask16<LANES>: Mask,
1116 SimdI32<LANES>: LanesAtMost32,
1117 SimdU32<LANES>: LanesAtMost32,
1118 SimdF32<LANES>: LanesAtMost32,
1119 Mask32<LANES>: Mask,
1120 SimdI64<LANES>: LanesAtMost32,
1121 SimdU64<LANES>: LanesAtMost32,
1122 SimdF64<LANES>: LanesAtMost32,
1123 Mask64<LANES>: Mask,
1124 {
1125 fn select(self, true_v: Self, false_v: Self) -> Self {
1126 // FIXME(programmerjake): work around https://github.com/rust-lang/stdsimd/issues/114
1127 (self & true_v) | (!self & false_v)
1128 }
1129 }
1130 };
1131 }
1132
1133 impl_select_mask!(Mask8);
1134 impl_select_mask!(Mask16);
1135 impl_select_mask!(Mask32);
1136 impl_select_mask!(Mask64);
1137
1138 macro_rules! impl_mask {
1139 ($mask:ident) => {
1140 impl<const LANES: usize> Bool for Wrapper<$mask<LANES>, LANES>
1141 where
1142 SimdI8<LANES>: LanesAtMost32,
1143 SimdU8<LANES>: LanesAtMost32,
1144 Mask8<LANES>: Mask,
1145 SimdI16<LANES>: LanesAtMost32,
1146 SimdU16<LANES>: LanesAtMost32,
1147 Mask16<LANES>: Mask,
1148 SimdI32<LANES>: LanesAtMost32,
1149 SimdU32<LANES>: LanesAtMost32,
1150 SimdF32<LANES>: LanesAtMost32,
1151 Mask32<LANES>: Mask,
1152 SimdI64<LANES>: LanesAtMost32,
1153 SimdU64<LANES>: LanesAtMost32,
1154 SimdF64<LANES>: LanesAtMost32,
1155 Mask64<LANES>: Mask,
1156 {
1157 }
1158 };
1159 }
1160
1161 impl_mask!(Mask8);
1162 impl_mask!(Mask16);
1163 impl_mask!(Mask32);
1164 impl_mask!(Mask64);
1165
1166 impl<const LANES: usize> Bool for Wrapper<bool, LANES>
1167 where
1168 SimdI8<LANES>: LanesAtMost32,
1169 SimdU8<LANES>: LanesAtMost32,
1170 Mask8<LANES>: Mask,
1171 SimdI16<LANES>: LanesAtMost32,
1172 SimdU16<LANES>: LanesAtMost32,
1173 Mask16<LANES>: Mask,
1174 SimdI32<LANES>: LanesAtMost32,
1175 SimdU32<LANES>: LanesAtMost32,
1176 SimdF32<LANES>: LanesAtMost32,
1177 Mask32<LANES>: Mask,
1178 SimdI64<LANES>: LanesAtMost32,
1179 SimdU64<LANES>: LanesAtMost32,
1180 SimdF64<LANES>: LanesAtMost32,
1181 Mask64<LANES>: Mask,
1182 {
1183 }
1184
1185 macro_rules! impl_make {
1186 ($ty:ident, $prim:ident) => {
1187 impl<const LANES: usize> Make for Wrapper<$ty<LANES>, LANES>
1188 where
1189 SimdI8<LANES>: LanesAtMost32,
1190 SimdU8<LANES>: LanesAtMost32,
1191 Mask8<LANES>: Mask,
1192 SimdI16<LANES>: LanesAtMost32,
1193 SimdU16<LANES>: LanesAtMost32,
1194 Mask16<LANES>: Mask,
1195 SimdI32<LANES>: LanesAtMost32,
1196 SimdU32<LANES>: LanesAtMost32,
1197 SimdF32<LANES>: LanesAtMost32,
1198 Mask32<LANES>: Mask,
1199 SimdI64<LANES>: LanesAtMost32,
1200 SimdU64<LANES>: LanesAtMost32,
1201 SimdF64<LANES>: LanesAtMost32,
1202 Mask64<LANES>: Mask,
1203 {
1204 type Prim = $prim;
1205
1206 type Context = StdSimd<LANES>;
1207
1208 fn ctx(self) -> Self::Context {
1209 StdSimd::default()
1210 }
1211
1212 fn make(_ctx: Self::Context, v: Self::Prim) -> Self {
1213 $ty::splat(v).into()
1214 }
1215 }
1216
1217 impl<const LANES: usize> From<Wrapper<$prim, LANES>> for Wrapper<$ty<LANES>, LANES>
1218 where
1219 SimdI8<LANES>: LanesAtMost32,
1220 SimdU8<LANES>: LanesAtMost32,
1221 Mask8<LANES>: Mask,
1222 SimdI16<LANES>: LanesAtMost32,
1223 SimdU16<LANES>: LanesAtMost32,
1224 Mask16<LANES>: Mask,
1225 SimdI32<LANES>: LanesAtMost32,
1226 SimdU32<LANES>: LanesAtMost32,
1227 SimdF32<LANES>: LanesAtMost32,
1228 Mask32<LANES>: Mask,
1229 SimdI64<LANES>: LanesAtMost32,
1230 SimdU64<LANES>: LanesAtMost32,
1231 SimdF64<LANES>: LanesAtMost32,
1232 Mask64<LANES>: Mask,
1233 {
1234 fn from(v: Wrapper<$prim, LANES>) -> Self {
1235 $ty::splat(v.0).into()
1236 }
1237 }
1238 };
1239 }
1240
1241 impl_make!(Mask8, bool);
1242 impl_make!(Mask16, bool);
1243 impl_make!(Mask32, bool);
1244 impl_make!(Mask64, bool);
1245 impl_make!(SimdI8, i8);
1246 impl_make!(SimdI16, i16);
1247 impl_make!(SimdI32, i32);
1248 impl_make!(SimdI64, i64);
1249 impl_make!(SimdU8, u8);
1250 impl_make!(SimdU16, u16);
1251 impl_make!(SimdU32, u32);
1252 impl_make!(SimdU64, u64);
1253 impl_make!(SimdF16, F16);
1254 impl_make!(SimdF32, f32);
1255 impl_make!(SimdF64, f64);
1256
1257 impl<const LANES: usize> Context for StdSimd<LANES>
1258 where
1259 SimdI8<LANES>: LanesAtMost32,
1260 SimdU8<LANES>: LanesAtMost32,
1261 Mask8<LANES>: Mask,
1262 SimdI16<LANES>: LanesAtMost32,
1263 SimdU16<LANES>: LanesAtMost32,
1264 Mask16<LANES>: Mask,
1265 SimdI32<LANES>: LanesAtMost32,
1266 SimdU32<LANES>: LanesAtMost32,
1267 SimdF32<LANES>: LanesAtMost32,
1268 Mask32<LANES>: Mask,
1269 SimdI64<LANES>: LanesAtMost32,
1270 SimdU64<LANES>: LanesAtMost32,
1271 SimdF64<LANES>: LanesAtMost32,
1272 Mask64<LANES>: Mask,
1273 {
1274 type Bool = Wrapper<bool, LANES>;
1275 type U8 = Wrapper<u8, LANES>;
1276 type I8 = Wrapper<i8, LANES>;
1277 type U16 = Wrapper<u16, LANES>;
1278 type I16 = Wrapper<i16, LANES>;
1279 type F16 = Wrapper<F16, LANES>;
1280 type U32 = Wrapper<u32, LANES>;
1281 type I32 = Wrapper<i32, LANES>;
1282 type F32 = Wrapper<f32, LANES>;
1283 type U64 = Wrapper<u64, LANES>;
1284 type I64 = Wrapper<i64, LANES>;
1285 type F64 = Wrapper<f64, LANES>;
1286 type VecBool8 = Wrapper<Mask8<LANES>, LANES>;
1287 type VecU8 = Wrapper<SimdU8<LANES>, LANES>;
1288 type VecI8 = Wrapper<SimdI8<LANES>, LANES>;
1289 type VecBool16 = Wrapper<Mask16<LANES>, LANES>;
1290 type VecU16 = Wrapper<SimdU16<LANES>, LANES>;
1291 type VecI16 = Wrapper<SimdI16<LANES>, LANES>;
1292 type VecF16 = Wrapper<SimdF16<LANES>, LANES>;
1293 type VecBool32 = Wrapper<Mask32<LANES>, LANES>;
1294 type VecU32 = Wrapper<SimdU32<LANES>, LANES>;
1295 type VecI32 = Wrapper<SimdI32<LANES>, LANES>;
1296 type VecF32 = Wrapper<SimdF32<LANES>, LANES>;
1297 type VecBool64 = Wrapper<Mask64<LANES>, LANES>;
1298 type VecU64 = Wrapper<SimdU64<LANES>, LANES>;
1299 type VecI64 = Wrapper<SimdI64<LANES>, LANES>;
1300 type VecF64 = Wrapper<SimdF64<LANES>, LANES>;
1301 }
1302
1303 pub type ScalarBool<const LANES: usize> = Wrapper<bool, LANES>;
1304 pub type ScalarU8<const LANES: usize> = Wrapper<u8, LANES>;
1305 pub type ScalarI8<const LANES: usize> = Wrapper<i8, LANES>;
1306 pub type ScalarU16<const LANES: usize> = Wrapper<u16, LANES>;
1307 pub type ScalarI16<const LANES: usize> = Wrapper<i16, LANES>;
1308 pub type ScalarF16<const LANES: usize> = Wrapper<F16, LANES>;
1309 pub type ScalarU32<const LANES: usize> = Wrapper<u32, LANES>;
1310 pub type ScalarI32<const LANES: usize> = Wrapper<i32, LANES>;
1311 pub type ScalarF32<const LANES: usize> = Wrapper<f32, LANES>;
1312 pub type ScalarU64<const LANES: usize> = Wrapper<u64, LANES>;
1313 pub type ScalarI64<const LANES: usize> = Wrapper<i64, LANES>;
1314 pub type ScalarF64<const LANES: usize> = Wrapper<f64, LANES>;
1315 pub type VecBool8<const LANES: usize> = Wrapper<Mask8<LANES>, LANES>;
1316 pub type VecU8<const LANES: usize> = Wrapper<SimdU8<LANES>, LANES>;
1317 pub type VecI8<const LANES: usize> = Wrapper<SimdI8<LANES>, LANES>;
1318 pub type VecBool16<const LANES: usize> = Wrapper<Mask16<LANES>, LANES>;
1319 pub type VecU16<const LANES: usize> = Wrapper<SimdU16<LANES>, LANES>;
1320 pub type VecI16<const LANES: usize> = Wrapper<SimdI16<LANES>, LANES>;
1321 pub type VecF16<const LANES: usize> = Wrapper<SimdF16<LANES>, LANES>;
1322 pub type VecBool32<const LANES: usize> = Wrapper<Mask32<LANES>, LANES>;
1323 pub type VecU32<const LANES: usize> = Wrapper<SimdU32<LANES>, LANES>;
1324 pub type VecI32<const LANES: usize> = Wrapper<SimdI32<LANES>, LANES>;
1325 pub type VecF32<const LANES: usize> = Wrapper<SimdF32<LANES>, LANES>;
1326 pub type VecBool64<const LANES: usize> = Wrapper<Mask64<LANES>, LANES>;
1327 pub type VecU64<const LANES: usize> = Wrapper<SimdU64<LANES>, LANES>;
1328 pub type VecI64<const LANES: usize> = Wrapper<SimdI64<LANES>, LANES>;
1329 pub type VecF64<const LANES: usize> = Wrapper<SimdF64<LANES>, LANES>;
1330
1331 #[cfg(test)]
1332 mod tests {
1333 use super::*;
1334 use crate::algorithms::ilogb::{
1335 ilogb_f32, ILOGB_NAN_RESULT_F32, ILOGB_OVERFLOW_RESULT_F32, ILOGB_UNDERFLOW_RESULT_F32,
1336 };
1337
1338 #[inline(never)]
1339 fn do_ilogb_f32x4(arg: VecF32<4>) -> VecI32<4> {
1340 ilogb_f32(StdSimd::default(), arg)
1341 }
1342
1343 #[test]
1344 fn test_ilogb_f32x4() {
1345 let ctx = StdSimd::<4>::default();
1346 assert_eq!(
1347 do_ilogb_f32x4(ctx.make(0f32)),
1348 ctx.make(ILOGB_UNDERFLOW_RESULT_F32)
1349 );
1350 assert_eq!(do_ilogb_f32x4(ctx.make(1f32)), ctx.make(0));
1351 assert_eq!(do_ilogb_f32x4(ctx.make(2f32)), ctx.make(1));
1352 assert_eq!(do_ilogb_f32x4(ctx.make(3f32)), ctx.make(1));
1353 assert_eq!(do_ilogb_f32x4(ctx.make(3.99999f32)), ctx.make(1));
1354 assert_eq!(do_ilogb_f32x4(ctx.make(0.5f32)), ctx.make(-1));
1355 assert_eq!(do_ilogb_f32x4(ctx.make(0.5f32.powi(130))), ctx.make(-130));
1356 assert_eq!(
1357 do_ilogb_f32x4(ctx.make(f32::INFINITY)),
1358 ctx.make(ILOGB_OVERFLOW_RESULT_F32)
1359 );
1360 assert_eq!(
1361 do_ilogb_f32x4(ctx.make(f32::NAN)),
1362 ctx.make(ILOGB_NAN_RESULT_F32)
1363 );
1364 }
1365 }