fix non-fma build
[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 #[cfg(feature = "fma")]
723 fn fma(self, a: Self, b: Self) -> Self {
724 self.0.fma(a.0, b.0).into()
725 }
726
727 fn is_finite(self) -> Self::Bool {
728 self.0.is_finite().into()
729 }
730
731 fn from_bits(v: Self::BitsType) -> Self {
732 $prim::from_bits(v.0).into()
733 }
734
735 fn to_bits(self) -> Self::BitsType {
736 self.0.to_bits().into()
737 }
738 }
739
740 impl<const LANES: usize> Float for Wrapper<$ty<LANES>, LANES>
741 where
742 SimdI8<LANES>: LanesAtMost32,
743 SimdU8<LANES>: LanesAtMost32,
744 Mask8<LANES>: Mask,
745 SimdI16<LANES>: LanesAtMost32,
746 SimdU16<LANES>: LanesAtMost32,
747 Mask16<LANES>: Mask,
748 SimdI32<LANES>: LanesAtMost32,
749 SimdU32<LANES>: LanesAtMost32,
750 SimdF32<LANES>: LanesAtMost32,
751 Mask32<LANES>: Mask,
752 SimdI64<LANES>: LanesAtMost32,
753 SimdU64<LANES>: LanesAtMost32,
754 SimdF64<LANES>: LanesAtMost32,
755 Mask64<LANES>: Mask,
756 {
757 type FloatEncoding = $prim;
758
759 type BitsType = Wrapper<$uint<LANES>, LANES>;
760
761 type SignedBitsType = Wrapper<$sint<LANES>, LANES>;
762
763 fn abs(self) -> Self {
764 self.0.abs().into()
765 }
766
767 fn trunc(self) -> Self {
768 self.0.trunc().into()
769 }
770
771 fn ceil(self) -> Self {
772 self.0.ceil().into()
773 }
774
775 fn floor(self) -> Self {
776 self.0.floor().into()
777 }
778
779 fn round(self) -> Self {
780 self.0.round().into()
781 }
782
783 #[cfg(feature = "fma")]
784 fn fma(self, _a: Self, _b: Self) -> Self {
785 // FIXME(programmerjake): implement once core_simd gains support:
786 // https://github.com/rust-lang/stdsimd/issues/102
787 todo!()
788 }
789
790 fn is_finite(self) -> Self::Bool {
791 self.0.is_finite().into()
792 }
793
794 fn from_bits(v: Self::BitsType) -> Self {
795 $ty::<LANES>::from_bits(v.0).into()
796 }
797
798 fn to_bits(self) -> Self::BitsType {
799 self.0.to_bits().into()
800 }
801 }
802 };
803 }
804
805 impl_float!(SimdF16, F16, SimdU16, SimdI16);
806 impl_float!(SimdF32, f32, SimdU32, SimdI32);
807 impl_float!(SimdF64, f64, SimdU64, SimdI64);
808
809 macro_rules! impl_scalar_convert_to_helper {
810 ($src:ty => $dest:ty) => {
811 impl<const LANES: usize> ConvertTo<Wrapper<$dest, LANES>> for Wrapper<$src, LANES>
812 where
813 SimdI8<LANES>: LanesAtMost32,
814 SimdU8<LANES>: LanesAtMost32,
815 Mask8<LANES>: Mask,
816 SimdI16<LANES>: LanesAtMost32,
817 SimdU16<LANES>: LanesAtMost32,
818 Mask16<LANES>: Mask,
819 SimdI32<LANES>: LanesAtMost32,
820 SimdU32<LANES>: LanesAtMost32,
821 SimdF32<LANES>: LanesAtMost32,
822 Mask32<LANES>: Mask,
823 SimdI64<LANES>: LanesAtMost32,
824 SimdU64<LANES>: LanesAtMost32,
825 SimdF64<LANES>: LanesAtMost32,
826 Mask64<LANES>: Mask,
827 {
828 fn to(self) -> Wrapper<$dest, LANES> {
829 let v: $dest = self.0.to();
830 v.into()
831 }
832 }
833 };
834 }
835
836 macro_rules! impl_scalar_convert_to {
837 ($first:ty $(, $ty:ty)*) => {
838 $(
839 impl_scalar_convert_to_helper!($first => $ty);
840 impl_scalar_convert_to_helper!($ty => $first);
841 )*
842 impl_scalar_convert_to![$($ty),*];
843 };
844 () => {};
845 }
846
847 impl_scalar_convert_to![u8, i8, u16, i16, F16, u32, i32, u64, i64, f32, f64];
848
849 macro_rules! impl_vector_convert_to_helper {
850 (($(#[From = $From:ident])? $src:ident, $src_prim:ident) => ($(#[From = $From2:ident])? $dest:ident, $dest_prim:ident)) => {
851 impl<const LANES: usize> ConvertTo<Wrapper<$dest<LANES>, LANES>>
852 for Wrapper<$src<LANES>, LANES>
853 where
854 SimdI8<LANES>: LanesAtMost32,
855 SimdU8<LANES>: LanesAtMost32,
856 Mask8<LANES>: Mask,
857 SimdI16<LANES>: LanesAtMost32,
858 SimdU16<LANES>: LanesAtMost32,
859 Mask16<LANES>: Mask,
860 SimdI32<LANES>: LanesAtMost32,
861 SimdU32<LANES>: LanesAtMost32,
862 SimdF32<LANES>: LanesAtMost32,
863 Mask32<LANES>: Mask,
864 SimdI64<LANES>: LanesAtMost32,
865 SimdU64<LANES>: LanesAtMost32,
866 SimdF64<LANES>: LanesAtMost32,
867 Mask64<LANES>: Mask,
868 {
869 fn to(self) -> Wrapper<$dest<LANES>, LANES> {
870 // FIXME(programmerjake): workaround https://github.com/rust-lang/stdsimd/issues/116
871 let src: [$src_prim; LANES] = self.0.into();
872 let mut dest: [$dest_prim; LANES] = [Default::default(); LANES];
873 for i in 0..LANES {
874 dest[i] = src[i].to();
875 }
876 $dest::<LANES>::from(dest).into()
877 }
878 }
879
880 $(impl<const LANES: usize> $From<Wrapper<$src<LANES>, LANES>> for Wrapper<$dest<LANES>, LANES>
881 where
882 SimdI8<LANES>: LanesAtMost32,
883 SimdU8<LANES>: LanesAtMost32,
884 Mask8<LANES>: Mask,
885 SimdI16<LANES>: LanesAtMost32,
886 SimdU16<LANES>: LanesAtMost32,
887 Mask16<LANES>: Mask,
888 SimdI32<LANES>: LanesAtMost32,
889 SimdU32<LANES>: LanesAtMost32,
890 SimdF32<LANES>: LanesAtMost32,
891 Mask32<LANES>: Mask,
892 SimdI64<LANES>: LanesAtMost32,
893 SimdU64<LANES>: LanesAtMost32,
894 SimdF64<LANES>: LanesAtMost32,
895 Mask64<LANES>: Mask,
896 {
897 fn from(v: Wrapper<$src<LANES>, LANES>) -> Self {
898 v.to()
899 }
900 })?
901 };
902 }
903
904 macro_rules! impl_vector_convert_to {
905 ($first:tt $(, $ty:tt)*) => {
906 $(
907 impl_vector_convert_to_helper!($first => $ty);
908 impl_vector_convert_to_helper!($ty => $first);
909 )*
910 impl_vector_convert_to![$($ty),*];
911 };
912 () => {};
913 }
914
915 impl_vector_convert_to![
916 (SimdU8, u8),
917 (SimdI8, i8),
918 (SimdU16, u16),
919 (SimdI16, i16),
920 (SimdF16, F16),
921 (SimdU32, u32),
922 (SimdI32, i32),
923 (SimdU64, u64),
924 (SimdI64, i64),
925 (SimdF32, f32),
926 (SimdF64, f64)
927 ];
928
929 impl_vector_convert_to![
930 (
931 #[From = From]
932 Mask8,
933 bool
934 ),
935 (
936 #[From = From]
937 Mask16,
938 bool
939 ),
940 (
941 #[From = From]
942 Mask32,
943 bool
944 ),
945 (
946 #[From = From]
947 Mask64,
948 bool
949 )
950 ];
951
952 macro_rules! impl_from_helper {
953 (#[lanes = $LANES:ident] $src:ty => $dest:ty) => {
954 impl<const $LANES: usize> From<$src> for $dest
955 where
956 SimdI8<LANES>: LanesAtMost32,
957 SimdU8<LANES>: LanesAtMost32,
958 Mask8<LANES>: Mask,
959 SimdI16<LANES>: LanesAtMost32,
960 SimdU16<LANES>: LanesAtMost32,
961 Mask16<LANES>: Mask,
962 SimdI32<LANES>: LanesAtMost32,
963 SimdU32<LANES>: LanesAtMost32,
964 SimdF32<LANES>: LanesAtMost32,
965 Mask32<LANES>: Mask,
966 SimdI64<LANES>: LanesAtMost32,
967 SimdU64<LANES>: LanesAtMost32,
968 SimdF64<LANES>: LanesAtMost32,
969 Mask64<LANES>: Mask,
970 {
971 fn from(v: $src) -> Self {
972 <$src as ConvertTo<$dest>>::to(v)
973 }
974 }
975 };
976 }
977
978 macro_rules! impl_from {
979 (#[lanes = $LANES:ident] $src:ty => [$($dest:ty),*]) => {
980 $(impl_from_helper!(#[lanes = $LANES] $src => $dest);)*
981 };
982 }
983
984 macro_rules! impl_froms {
985 (
986 #[lanes = $LANES:ident]
987 #[u8] $u8:ty;
988 #[i8] $i8:ty;
989 #[u16] $u16:ty;
990 #[i16] $i16:ty;
991 #[f16] $f16:ty;
992 #[u32] $u32:ty;
993 #[i32] $i32:ty;
994 #[f32] $f32:ty;
995 #[u64] $u64:ty;
996 #[i64] $i64:ty;
997 #[f64] $f64:ty;
998 ) => {
999 impl_from!(#[lanes = $LANES] $u8 => [$u16, $i16, $f16, $u32, $i32, $f32, $u64, $i64, $f64]);
1000 impl_from!(#[lanes = $LANES] $u16 => [$u32, $i32, $f32, $u64, $i64, $f64]);
1001 impl_from!(#[lanes = $LANES] $u32 => [$u64, $i64, $f64]);
1002 impl_from!(#[lanes = $LANES] $i8 => [$i16, $f16, $i32, $f32, $i64, $f64]);
1003 impl_from!(#[lanes = $LANES] $i16 => [$i32, $f32, $i64, $f64]);
1004 impl_from!(#[lanes = $LANES] $i32 => [$i64, $f64]);
1005 impl_from!(#[lanes = $LANES] $f16 => [$f32, $f64]);
1006 impl_from!(#[lanes = $LANES] $f32 => [$f64]);
1007 };
1008 }
1009
1010 impl_froms! {
1011 #[lanes = LANES]
1012 #[u8] Wrapper<u8, LANES>;
1013 #[i8] Wrapper<i8, LANES>;
1014 #[u16] Wrapper<u16, LANES>;
1015 #[i16] Wrapper<i16, LANES>;
1016 #[f16] Wrapper<F16, LANES>;
1017 #[u32] Wrapper<u32, LANES>;
1018 #[i32] Wrapper<i32, LANES>;
1019 #[f32] Wrapper<f32, LANES>;
1020 #[u64] Wrapper<u64, LANES>;
1021 #[i64] Wrapper<i64, LANES>;
1022 #[f64] Wrapper<f64, LANES>;
1023 }
1024
1025 impl_froms! {
1026 #[lanes = LANES]
1027 #[u8] Wrapper<SimdU8<LANES>, LANES>;
1028 #[i8] Wrapper<SimdI8<LANES>, LANES>;
1029 #[u16] Wrapper<SimdU16<LANES>, LANES>;
1030 #[i16] Wrapper<SimdI16<LANES>, LANES>;
1031 #[f16] Wrapper<SimdF16<LANES>, LANES>;
1032 #[u32] Wrapper<SimdU32<LANES>, LANES>;
1033 #[i32] Wrapper<SimdI32<LANES>, LANES>;
1034 #[f32] Wrapper<SimdF32<LANES>, LANES>;
1035 #[u64] Wrapper<SimdU64<LANES>, LANES>;
1036 #[i64] Wrapper<SimdI64<LANES>, LANES>;
1037 #[f64] Wrapper<SimdF64<LANES>, LANES>;
1038 }
1039
1040 macro_rules! impl_select {
1041 ($mask:ident, $ty:ident) => {
1042 impl<const LANES: usize> Select<Wrapper<$ty<LANES>, LANES>> for Wrapper<$mask<LANES>, LANES>
1043 where
1044 SimdI8<LANES>: LanesAtMost32,
1045 SimdU8<LANES>: LanesAtMost32,
1046 Mask8<LANES>: Mask,
1047 SimdI16<LANES>: LanesAtMost32,
1048 SimdU16<LANES>: LanesAtMost32,
1049 Mask16<LANES>: Mask,
1050 SimdI32<LANES>: LanesAtMost32,
1051 SimdU32<LANES>: LanesAtMost32,
1052 SimdF32<LANES>: LanesAtMost32,
1053 Mask32<LANES>: Mask,
1054 SimdI64<LANES>: LanesAtMost32,
1055 SimdU64<LANES>: LanesAtMost32,
1056 SimdF64<LANES>: LanesAtMost32,
1057 Mask64<LANES>: Mask,
1058 {
1059 fn select(
1060 self,
1061 true_v: Wrapper<$ty<LANES>, LANES>,
1062 false_v: Wrapper<$ty<LANES>, LANES>,
1063 ) -> Wrapper<$ty<LANES>, LANES> {
1064 self.0.select(true_v.0, false_v.0).into()
1065 }
1066 }
1067 };
1068 }
1069
1070 impl_select!(Mask8, SimdU8);
1071 impl_select!(Mask8, SimdI8);
1072 impl_select!(Mask16, SimdU16);
1073 impl_select!(Mask16, SimdI16);
1074 impl_select!(Mask32, SimdU32);
1075 impl_select!(Mask32, SimdI32);
1076 impl_select!(Mask32, SimdF32);
1077 impl_select!(Mask64, SimdU64);
1078 impl_select!(Mask64, SimdI64);
1079 impl_select!(Mask64, SimdF64);
1080
1081 #[cfg(not(feature = "f16"))]
1082 impl<const LANES: usize> Select<Wrapper<SimdF16<LANES>, LANES>> for Wrapper<Mask16<LANES>, LANES>
1083 where
1084 SimdI8<LANES>: LanesAtMost32,
1085 SimdU8<LANES>: LanesAtMost32,
1086 Mask8<LANES>: Mask,
1087 SimdI16<LANES>: LanesAtMost32,
1088 SimdU16<LANES>: LanesAtMost32,
1089 Mask16<LANES>: Mask,
1090 SimdI32<LANES>: LanesAtMost32,
1091 SimdU32<LANES>: LanesAtMost32,
1092 SimdF32<LANES>: LanesAtMost32,
1093 Mask32<LANES>: Mask,
1094 SimdI64<LANES>: LanesAtMost32,
1095 SimdU64<LANES>: LanesAtMost32,
1096 SimdF64<LANES>: LanesAtMost32,
1097 Mask64<LANES>: Mask,
1098 {
1099 fn select(
1100 self,
1101 _true_v: Wrapper<SimdF16<LANES>, LANES>,
1102 _false_v: Wrapper<SimdF16<LANES>, LANES>,
1103 ) -> Wrapper<SimdF16<LANES>, LANES> {
1104 panic_f16_feature_disabled()
1105 }
1106 }
1107
1108 macro_rules! impl_select_mask {
1109 ($ty:ident) => {
1110 impl<const LANES: usize> Select<Self> for Wrapper<$ty<LANES>, LANES>
1111 where
1112 SimdI8<LANES>: LanesAtMost32,
1113 SimdU8<LANES>: LanesAtMost32,
1114 Mask8<LANES>: Mask,
1115 SimdI16<LANES>: LanesAtMost32,
1116 SimdU16<LANES>: LanesAtMost32,
1117 Mask16<LANES>: Mask,
1118 SimdI32<LANES>: LanesAtMost32,
1119 SimdU32<LANES>: LanesAtMost32,
1120 SimdF32<LANES>: LanesAtMost32,
1121 Mask32<LANES>: Mask,
1122 SimdI64<LANES>: LanesAtMost32,
1123 SimdU64<LANES>: LanesAtMost32,
1124 SimdF64<LANES>: LanesAtMost32,
1125 Mask64<LANES>: Mask,
1126 {
1127 fn select(self, true_v: Self, false_v: Self) -> Self {
1128 // FIXME(programmerjake): work around https://github.com/rust-lang/stdsimd/issues/114
1129 (self & true_v) | (!self & false_v)
1130 }
1131 }
1132 };
1133 }
1134
1135 impl_select_mask!(Mask8);
1136 impl_select_mask!(Mask16);
1137 impl_select_mask!(Mask32);
1138 impl_select_mask!(Mask64);
1139
1140 macro_rules! impl_mask {
1141 ($mask:ident) => {
1142 impl<const LANES: usize> Bool for Wrapper<$mask<LANES>, LANES>
1143 where
1144 SimdI8<LANES>: LanesAtMost32,
1145 SimdU8<LANES>: LanesAtMost32,
1146 Mask8<LANES>: Mask,
1147 SimdI16<LANES>: LanesAtMost32,
1148 SimdU16<LANES>: LanesAtMost32,
1149 Mask16<LANES>: Mask,
1150 SimdI32<LANES>: LanesAtMost32,
1151 SimdU32<LANES>: LanesAtMost32,
1152 SimdF32<LANES>: LanesAtMost32,
1153 Mask32<LANES>: Mask,
1154 SimdI64<LANES>: LanesAtMost32,
1155 SimdU64<LANES>: LanesAtMost32,
1156 SimdF64<LANES>: LanesAtMost32,
1157 Mask64<LANES>: Mask,
1158 {
1159 }
1160 };
1161 }
1162
1163 impl_mask!(Mask8);
1164 impl_mask!(Mask16);
1165 impl_mask!(Mask32);
1166 impl_mask!(Mask64);
1167
1168 impl<const LANES: usize> Bool for Wrapper<bool, LANES>
1169 where
1170 SimdI8<LANES>: LanesAtMost32,
1171 SimdU8<LANES>: LanesAtMost32,
1172 Mask8<LANES>: Mask,
1173 SimdI16<LANES>: LanesAtMost32,
1174 SimdU16<LANES>: LanesAtMost32,
1175 Mask16<LANES>: Mask,
1176 SimdI32<LANES>: LanesAtMost32,
1177 SimdU32<LANES>: LanesAtMost32,
1178 SimdF32<LANES>: LanesAtMost32,
1179 Mask32<LANES>: Mask,
1180 SimdI64<LANES>: LanesAtMost32,
1181 SimdU64<LANES>: LanesAtMost32,
1182 SimdF64<LANES>: LanesAtMost32,
1183 Mask64<LANES>: Mask,
1184 {
1185 }
1186
1187 macro_rules! impl_make {
1188 ($ty:ident, $prim:ident) => {
1189 impl<const LANES: usize> Make for Wrapper<$ty<LANES>, LANES>
1190 where
1191 SimdI8<LANES>: LanesAtMost32,
1192 SimdU8<LANES>: LanesAtMost32,
1193 Mask8<LANES>: Mask,
1194 SimdI16<LANES>: LanesAtMost32,
1195 SimdU16<LANES>: LanesAtMost32,
1196 Mask16<LANES>: Mask,
1197 SimdI32<LANES>: LanesAtMost32,
1198 SimdU32<LANES>: LanesAtMost32,
1199 SimdF32<LANES>: LanesAtMost32,
1200 Mask32<LANES>: Mask,
1201 SimdI64<LANES>: LanesAtMost32,
1202 SimdU64<LANES>: LanesAtMost32,
1203 SimdF64<LANES>: LanesAtMost32,
1204 Mask64<LANES>: Mask,
1205 {
1206 type Prim = $prim;
1207
1208 type Context = StdSimd<LANES>;
1209
1210 fn ctx(self) -> Self::Context {
1211 StdSimd::default()
1212 }
1213
1214 fn make(_ctx: Self::Context, v: Self::Prim) -> Self {
1215 $ty::splat(v).into()
1216 }
1217 }
1218
1219 impl<const LANES: usize> From<Wrapper<$prim, LANES>> for Wrapper<$ty<LANES>, LANES>
1220 where
1221 SimdI8<LANES>: LanesAtMost32,
1222 SimdU8<LANES>: LanesAtMost32,
1223 Mask8<LANES>: Mask,
1224 SimdI16<LANES>: LanesAtMost32,
1225 SimdU16<LANES>: LanesAtMost32,
1226 Mask16<LANES>: Mask,
1227 SimdI32<LANES>: LanesAtMost32,
1228 SimdU32<LANES>: LanesAtMost32,
1229 SimdF32<LANES>: LanesAtMost32,
1230 Mask32<LANES>: Mask,
1231 SimdI64<LANES>: LanesAtMost32,
1232 SimdU64<LANES>: LanesAtMost32,
1233 SimdF64<LANES>: LanesAtMost32,
1234 Mask64<LANES>: Mask,
1235 {
1236 fn from(v: Wrapper<$prim, LANES>) -> Self {
1237 $ty::splat(v.0).into()
1238 }
1239 }
1240 };
1241 }
1242
1243 impl_make!(Mask8, bool);
1244 impl_make!(Mask16, bool);
1245 impl_make!(Mask32, bool);
1246 impl_make!(Mask64, bool);
1247 impl_make!(SimdI8, i8);
1248 impl_make!(SimdI16, i16);
1249 impl_make!(SimdI32, i32);
1250 impl_make!(SimdI64, i64);
1251 impl_make!(SimdU8, u8);
1252 impl_make!(SimdU16, u16);
1253 impl_make!(SimdU32, u32);
1254 impl_make!(SimdU64, u64);
1255 impl_make!(SimdF16, F16);
1256 impl_make!(SimdF32, f32);
1257 impl_make!(SimdF64, f64);
1258
1259 impl<const LANES: usize> Context for StdSimd<LANES>
1260 where
1261 SimdI8<LANES>: LanesAtMost32,
1262 SimdU8<LANES>: LanesAtMost32,
1263 Mask8<LANES>: Mask,
1264 SimdI16<LANES>: LanesAtMost32,
1265 SimdU16<LANES>: LanesAtMost32,
1266 Mask16<LANES>: Mask,
1267 SimdI32<LANES>: LanesAtMost32,
1268 SimdU32<LANES>: LanesAtMost32,
1269 SimdF32<LANES>: LanesAtMost32,
1270 Mask32<LANES>: Mask,
1271 SimdI64<LANES>: LanesAtMost32,
1272 SimdU64<LANES>: LanesAtMost32,
1273 SimdF64<LANES>: LanesAtMost32,
1274 Mask64<LANES>: Mask,
1275 {
1276 type Bool = Wrapper<bool, LANES>;
1277 type U8 = Wrapper<u8, LANES>;
1278 type I8 = Wrapper<i8, LANES>;
1279 type U16 = Wrapper<u16, LANES>;
1280 type I16 = Wrapper<i16, LANES>;
1281 type F16 = Wrapper<F16, LANES>;
1282 type U32 = Wrapper<u32, LANES>;
1283 type I32 = Wrapper<i32, LANES>;
1284 type F32 = Wrapper<f32, LANES>;
1285 type U64 = Wrapper<u64, LANES>;
1286 type I64 = Wrapper<i64, LANES>;
1287 type F64 = Wrapper<f64, LANES>;
1288 type VecBool8 = Wrapper<Mask8<LANES>, LANES>;
1289 type VecU8 = Wrapper<SimdU8<LANES>, LANES>;
1290 type VecI8 = Wrapper<SimdI8<LANES>, LANES>;
1291 type VecBool16 = Wrapper<Mask16<LANES>, LANES>;
1292 type VecU16 = Wrapper<SimdU16<LANES>, LANES>;
1293 type VecI16 = Wrapper<SimdI16<LANES>, LANES>;
1294 type VecF16 = Wrapper<SimdF16<LANES>, LANES>;
1295 type VecBool32 = Wrapper<Mask32<LANES>, LANES>;
1296 type VecU32 = Wrapper<SimdU32<LANES>, LANES>;
1297 type VecI32 = Wrapper<SimdI32<LANES>, LANES>;
1298 type VecF32 = Wrapper<SimdF32<LANES>, LANES>;
1299 type VecBool64 = Wrapper<Mask64<LANES>, LANES>;
1300 type VecU64 = Wrapper<SimdU64<LANES>, LANES>;
1301 type VecI64 = Wrapper<SimdI64<LANES>, LANES>;
1302 type VecF64 = Wrapper<SimdF64<LANES>, LANES>;
1303 }
1304
1305 pub type ScalarBool<const LANES: usize> = Wrapper<bool, LANES>;
1306 pub type ScalarU8<const LANES: usize> = Wrapper<u8, LANES>;
1307 pub type ScalarI8<const LANES: usize> = Wrapper<i8, LANES>;
1308 pub type ScalarU16<const LANES: usize> = Wrapper<u16, LANES>;
1309 pub type ScalarI16<const LANES: usize> = Wrapper<i16, LANES>;
1310 pub type ScalarF16<const LANES: usize> = Wrapper<F16, LANES>;
1311 pub type ScalarU32<const LANES: usize> = Wrapper<u32, LANES>;
1312 pub type ScalarI32<const LANES: usize> = Wrapper<i32, LANES>;
1313 pub type ScalarF32<const LANES: usize> = Wrapper<f32, LANES>;
1314 pub type ScalarU64<const LANES: usize> = Wrapper<u64, LANES>;
1315 pub type ScalarI64<const LANES: usize> = Wrapper<i64, LANES>;
1316 pub type ScalarF64<const LANES: usize> = Wrapper<f64, LANES>;
1317 pub type VecBool8<const LANES: usize> = Wrapper<Mask8<LANES>, LANES>;
1318 pub type VecU8<const LANES: usize> = Wrapper<SimdU8<LANES>, LANES>;
1319 pub type VecI8<const LANES: usize> = Wrapper<SimdI8<LANES>, LANES>;
1320 pub type VecBool16<const LANES: usize> = Wrapper<Mask16<LANES>, LANES>;
1321 pub type VecU16<const LANES: usize> = Wrapper<SimdU16<LANES>, LANES>;
1322 pub type VecI16<const LANES: usize> = Wrapper<SimdI16<LANES>, LANES>;
1323 pub type VecF16<const LANES: usize> = Wrapper<SimdF16<LANES>, LANES>;
1324 pub type VecBool32<const LANES: usize> = Wrapper<Mask32<LANES>, LANES>;
1325 pub type VecU32<const LANES: usize> = Wrapper<SimdU32<LANES>, LANES>;
1326 pub type VecI32<const LANES: usize> = Wrapper<SimdI32<LANES>, LANES>;
1327 pub type VecF32<const LANES: usize> = Wrapper<SimdF32<LANES>, LANES>;
1328 pub type VecBool64<const LANES: usize> = Wrapper<Mask64<LANES>, LANES>;
1329 pub type VecU64<const LANES: usize> = Wrapper<SimdU64<LANES>, LANES>;
1330 pub type VecI64<const LANES: usize> = Wrapper<SimdI64<LANES>, LANES>;
1331 pub type VecF64<const LANES: usize> = Wrapper<SimdF64<LANES>, LANES>;
1332
1333 #[cfg(test)]
1334 mod tests {
1335 use super::*;
1336 use crate::algorithms::ilogb::{
1337 ilogb_f32, ILOGB_NAN_RESULT_F32, ILOGB_OVERFLOW_RESULT_F32, ILOGB_UNDERFLOW_RESULT_F32,
1338 };
1339
1340 #[inline(never)]
1341 fn do_ilogb_f32x4(arg: VecF32<4>) -> VecI32<4> {
1342 ilogb_f32(StdSimd::default(), arg)
1343 }
1344
1345 #[test]
1346 fn test_ilogb_f32x4() {
1347 let ctx = StdSimd::<4>::default();
1348 assert_eq!(
1349 do_ilogb_f32x4(ctx.make(0f32)),
1350 ctx.make(ILOGB_UNDERFLOW_RESULT_F32)
1351 );
1352 assert_eq!(do_ilogb_f32x4(ctx.make(1f32)), ctx.make(0));
1353 assert_eq!(do_ilogb_f32x4(ctx.make(2f32)), ctx.make(1));
1354 assert_eq!(do_ilogb_f32x4(ctx.make(3f32)), ctx.make(1));
1355 assert_eq!(do_ilogb_f32x4(ctx.make(3.99999f32)), ctx.make(1));
1356 assert_eq!(do_ilogb_f32x4(ctx.make(0.5f32)), ctx.make(-1));
1357 assert_eq!(do_ilogb_f32x4(ctx.make(0.5f32.powi(130))), ctx.make(-130));
1358 assert_eq!(
1359 do_ilogb_f32x4(ctx.make(f32::INFINITY)),
1360 ctx.make(ILOGB_OVERFLOW_RESULT_F32)
1361 );
1362 assert_eq!(
1363 do_ilogb_f32x4(ctx.make(f32::NAN)),
1364 ctx.make(ILOGB_NAN_RESULT_F32)
1365 );
1366 }
1367 }