add sin_pi_kernel_f64 and cos_pi_kernel_f64
[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 prim::PrimFloat,
6 traits::{
7 Bool, Compare, Context, ConvertFrom, ConvertTo, Float, Int, Make, SInt, Select, UInt,
8 },
9 };
10 use core::{
11 marker::PhantomData,
12 ops::{
13 Add, AddAssign, BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Div,
14 DivAssign, Mul, MulAssign, Neg, Not, Rem, RemAssign, Shl, ShlAssign, Shr, ShrAssign, Sub,
15 SubAssign,
16 },
17 };
18 use core_simd::{
19 LanesAtMost32, Mask, Mask16, Mask32, Mask64, Mask8, SimdF32, SimdF64, SimdI16, SimdI32,
20 SimdI64, SimdI8, SimdU16, SimdU32, SimdU64, SimdU8,
21 };
22
23 #[cfg(not(feature = "f16"))]
24 mod f16 {
25 use super::*;
26
27 #[derive(Copy, Clone, Debug)]
28 #[repr(transparent)]
29 pub struct SimdF16<const LANES: usize>(pub(crate) SimdU16<LANES>)
30 where
31 SimdU16<LANES>: LanesAtMost32;
32
33 impl<const LANES: usize> SimdF16<LANES>
34 where
35 SimdU16<LANES>: LanesAtMost32,
36 SimdI16<LANES>: LanesAtMost32,
37 Mask16<LANES>: Mask,
38 {
39 pub(crate) fn splat(_v: F16) -> Self {
40 panic_f16_feature_disabled()
41 }
42 pub(crate) fn abs(self) -> Self {
43 panic_f16_feature_disabled()
44 }
45 pub(crate) fn trunc(self) -> Self {
46 panic_f16_feature_disabled()
47 }
48 pub(crate) fn floor(self) -> Self {
49 panic_f16_feature_disabled()
50 }
51 pub(crate) fn ceil(self) -> Self {
52 panic_f16_feature_disabled()
53 }
54 pub(crate) fn round(self) -> Self {
55 panic_f16_feature_disabled()
56 }
57 pub(crate) fn from_bits(_v: SimdU16<LANES>) -> Self {
58 panic_f16_feature_disabled()
59 }
60 pub(crate) fn to_bits(self) -> SimdU16<LANES> {
61 panic_f16_feature_disabled()
62 }
63 pub(crate) fn is_finite(self) -> Mask16<LANES> {
64 panic_f16_feature_disabled()
65 }
66 pub(crate) fn lanes_eq(self, _rhs: Self) -> Mask16<LANES> {
67 panic_f16_feature_disabled()
68 }
69 pub(crate) fn lanes_ne(self, _rhs: Self) -> Mask16<LANES> {
70 panic_f16_feature_disabled()
71 }
72 pub(crate) fn lanes_gt(self, _rhs: Self) -> Mask16<LANES> {
73 panic_f16_feature_disabled()
74 }
75 pub(crate) fn lanes_ge(self, _rhs: Self) -> Mask16<LANES> {
76 panic_f16_feature_disabled()
77 }
78 pub(crate) fn lanes_lt(self, _rhs: Self) -> Mask16<LANES> {
79 panic_f16_feature_disabled()
80 }
81 pub(crate) fn lanes_le(self, _rhs: Self) -> Mask16<LANES> {
82 panic_f16_feature_disabled()
83 }
84 }
85
86 impl<const LANES: usize> From<[F16; LANES]> for SimdF16<LANES>
87 where
88 SimdU16<LANES>: LanesAtMost32,
89 {
90 fn from(_v: [F16; LANES]) -> Self {
91 panic_f16_feature_disabled()
92 }
93 }
94
95 impl<const LANES: usize> From<SimdF16<LANES>> for [F16; LANES]
96 where
97 SimdU16<LANES>: LanesAtMost32,
98 {
99 fn from(_v: SimdF16<LANES>) -> Self {
100 panic_f16_feature_disabled()
101 }
102 }
103
104 macro_rules! impl_f16_bin_op {
105 ($trait:ident, $fn:ident) => {
106 impl<const LANES: usize> $trait for SimdF16<LANES>
107 where
108 SimdU16<LANES>: LanesAtMost32,
109 {
110 type Output = Self;
111
112 fn $fn(self, _rhs: Self) -> Self::Output {
113 panic_f16_feature_disabled()
114 }
115 }
116 };
117 }
118
119 impl_f16_bin_op!(Add, add);
120 impl_f16_bin_op!(Sub, sub);
121 impl_f16_bin_op!(Mul, mul);
122 impl_f16_bin_op!(Div, div);
123 impl_f16_bin_op!(Rem, rem);
124
125 macro_rules! impl_f16_bin_assign_op {
126 ($trait:ident, $fn:ident) => {
127 impl<const LANES: usize> $trait for SimdF16<LANES>
128 where
129 SimdU16<LANES>: LanesAtMost32,
130 {
131 fn $fn(&mut self, _rhs: Self) {
132 panic_f16_feature_disabled()
133 }
134 }
135 };
136 }
137
138 impl_f16_bin_assign_op!(AddAssign, add_assign);
139 impl_f16_bin_assign_op!(SubAssign, sub_assign);
140 impl_f16_bin_assign_op!(MulAssign, mul_assign);
141 impl_f16_bin_assign_op!(DivAssign, div_assign);
142 impl_f16_bin_assign_op!(RemAssign, rem_assign);
143
144 impl<const LANES: usize> Neg for SimdF16<LANES>
145 where
146 SimdU16<LANES>: LanesAtMost32,
147 {
148 type Output = Self;
149
150 fn neg(self) -> Self::Output {
151 panic_f16_feature_disabled()
152 }
153 }
154 }
155
156 #[cfg(not(feature = "f16"))]
157 use f16::SimdF16;
158
159 #[cfg(feature = "f16")]
160 compile_error!("core_simd doesn't yet support f16");
161
162 #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Default)]
163 pub struct StdSimd<const LANES: usize>(PhantomData<[(); LANES]>);
164
165 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Default)]
166 #[repr(transparent)]
167 pub struct Wrapper<T, const LANES: usize>(pub T, PhantomData<[(); LANES]>);
168
169 impl<T, const LANES: usize> From<T> for Wrapper<T, LANES> {
170 fn from(v: T) -> Self {
171 Wrapper(v, PhantomData)
172 }
173 }
174
175 macro_rules! impl_bin_op_for_wrapper {
176 ($trait:ident, $fn:ident) => {
177 impl<T: $trait<Output = T>, const LANES: usize> $trait for Wrapper<T, LANES> {
178 type Output = Self;
179
180 fn $fn(self, rhs: Self) -> Self::Output {
181 self.0.$fn(rhs.0).into()
182 }
183 }
184 };
185 }
186
187 impl_bin_op_for_wrapper!(Add, add);
188 impl_bin_op_for_wrapper!(Sub, sub);
189 impl_bin_op_for_wrapper!(Mul, mul);
190 impl_bin_op_for_wrapper!(Div, div);
191 impl_bin_op_for_wrapper!(Rem, rem);
192 impl_bin_op_for_wrapper!(Shl, shl);
193 impl_bin_op_for_wrapper!(Shr, shr);
194 impl_bin_op_for_wrapper!(BitAnd, bitand);
195 impl_bin_op_for_wrapper!(BitOr, bitor);
196 impl_bin_op_for_wrapper!(BitXor, bitxor);
197
198 macro_rules! impl_bin_op_assign_for_wrapper {
199 ($trait:ident, $fn:ident) => {
200 impl<T: $trait, const LANES: usize> $trait for Wrapper<T, LANES> {
201 fn $fn(&mut self, rhs: Self) {
202 self.0.$fn(rhs.0);
203 }
204 }
205 };
206 }
207
208 impl_bin_op_assign_for_wrapper!(AddAssign, add_assign);
209 impl_bin_op_assign_for_wrapper!(SubAssign, sub_assign);
210 impl_bin_op_assign_for_wrapper!(MulAssign, mul_assign);
211 impl_bin_op_assign_for_wrapper!(DivAssign, div_assign);
212 impl_bin_op_assign_for_wrapper!(RemAssign, rem_assign);
213 impl_bin_op_assign_for_wrapper!(ShlAssign, shl_assign);
214 impl_bin_op_assign_for_wrapper!(ShrAssign, shr_assign);
215 impl_bin_op_assign_for_wrapper!(BitAndAssign, bitand_assign);
216 impl_bin_op_assign_for_wrapper!(BitOrAssign, bitor_assign);
217 impl_bin_op_assign_for_wrapper!(BitXorAssign, bitxor_assign);
218
219 macro_rules! impl_un_op_for_wrapper {
220 ($trait:ident, $fn:ident) => {
221 impl<T: $trait<Output = T>, const LANES: usize> $trait for Wrapper<T, LANES> {
222 type Output = Self;
223
224 fn $fn(self) -> Self::Output {
225 self.0.$fn().into()
226 }
227 }
228 };
229 }
230
231 impl_un_op_for_wrapper!(Not, not);
232 impl_un_op_for_wrapper!(Neg, neg);
233
234 macro_rules! impl_make_for_scalar {
235 ($ty:ident) => {
236 impl<const LANES: usize> Make for Wrapper<$ty, LANES>
237 where
238 SimdI8<LANES>: LanesAtMost32,
239 SimdU8<LANES>: LanesAtMost32,
240 Mask8<LANES>: Mask,
241 SimdI16<LANES>: LanesAtMost32,
242 SimdU16<LANES>: LanesAtMost32,
243 Mask16<LANES>: Mask,
244 SimdI32<LANES>: LanesAtMost32,
245 SimdU32<LANES>: LanesAtMost32,
246 SimdF32<LANES>: LanesAtMost32,
247 Mask32<LANES>: Mask,
248 SimdI64<LANES>: LanesAtMost32,
249 SimdU64<LANES>: LanesAtMost32,
250 SimdF64<LANES>: LanesAtMost32,
251 Mask64<LANES>: Mask,
252 {
253 type Prim = $ty;
254
255 type Context = StdSimd<LANES>;
256
257 fn ctx(self) -> Self::Context {
258 StdSimd::default()
259 }
260
261 fn make(_ctx: Self::Context, v: Self::Prim) -> Self {
262 v.into()
263 }
264 }
265 };
266 }
267
268 impl_make_for_scalar!(bool);
269 impl_make_for_scalar!(i8);
270 impl_make_for_scalar!(u8);
271 impl_make_for_scalar!(i16);
272 impl_make_for_scalar!(u16);
273 impl_make_for_scalar!(F16);
274 impl_make_for_scalar!(i32);
275 impl_make_for_scalar!(u32);
276 impl_make_for_scalar!(f32);
277 impl_make_for_scalar!(i64);
278 impl_make_for_scalar!(u64);
279 impl_make_for_scalar!(f64);
280
281 impl<V, const LANES: usize> Select<V> for Wrapper<bool, LANES>
282 where
283 SimdI8<LANES>: LanesAtMost32,
284 SimdU8<LANES>: LanesAtMost32,
285 Mask8<LANES>: Mask,
286 SimdI16<LANES>: LanesAtMost32,
287 SimdU16<LANES>: LanesAtMost32,
288 Mask16<LANES>: Mask,
289 SimdI32<LANES>: LanesAtMost32,
290 SimdU32<LANES>: LanesAtMost32,
291 SimdF32<LANES>: LanesAtMost32,
292 Mask32<LANES>: Mask,
293 SimdI64<LANES>: LanesAtMost32,
294 SimdU64<LANES>: LanesAtMost32,
295 SimdF64<LANES>: LanesAtMost32,
296 Mask64<LANES>: Mask,
297 {
298 fn select(self, true_v: V, false_v: V) -> V {
299 if self.0 {
300 true_v
301 } else {
302 false_v
303 }
304 }
305 }
306
307 macro_rules! impl_scalar_compare {
308 ($ty:ident) => {
309 impl<const LANES: usize> Compare for Wrapper<$ty, LANES>
310 where
311 SimdI8<LANES>: LanesAtMost32,
312 SimdU8<LANES>: LanesAtMost32,
313 Mask8<LANES>: Mask,
314 SimdI16<LANES>: LanesAtMost32,
315 SimdU16<LANES>: LanesAtMost32,
316 Mask16<LANES>: Mask,
317 SimdI32<LANES>: LanesAtMost32,
318 SimdU32<LANES>: LanesAtMost32,
319 SimdF32<LANES>: LanesAtMost32,
320 Mask32<LANES>: Mask,
321 SimdI64<LANES>: LanesAtMost32,
322 SimdU64<LANES>: LanesAtMost32,
323 SimdF64<LANES>: LanesAtMost32,
324 Mask64<LANES>: Mask,
325 {
326 type Bool = Wrapper<bool, LANES>;
327
328 fn eq(self, rhs: Self) -> Self::Bool {
329 self.0.eq(&rhs.0).into()
330 }
331
332 fn ne(self, rhs: Self) -> Self::Bool {
333 self.0.ne(&rhs.0).into()
334 }
335
336 fn lt(self, rhs: Self) -> Self::Bool {
337 self.0.lt(&rhs.0).into()
338 }
339
340 fn gt(self, rhs: Self) -> Self::Bool {
341 self.0.gt(&rhs.0).into()
342 }
343
344 fn le(self, rhs: Self) -> Self::Bool {
345 self.0.le(&rhs.0).into()
346 }
347
348 fn ge(self, rhs: Self) -> Self::Bool {
349 self.0.ge(&rhs.0).into()
350 }
351 }
352 };
353 }
354
355 impl_scalar_compare!(bool);
356 impl_scalar_compare!(i8);
357 impl_scalar_compare!(u8);
358 impl_scalar_compare!(i16);
359 impl_scalar_compare!(u16);
360 impl_scalar_compare!(F16);
361 impl_scalar_compare!(i32);
362 impl_scalar_compare!(u32);
363 impl_scalar_compare!(f32);
364 impl_scalar_compare!(i64);
365 impl_scalar_compare!(u64);
366 impl_scalar_compare!(f64);
367
368 macro_rules! impl_vector_compare {
369 ($ty:ident, $mask:ident) => {
370 impl<const LANES: usize> Compare for Wrapper<$ty<LANES>, LANES>
371 where
372 SimdI8<LANES>: LanesAtMost32,
373 SimdU8<LANES>: LanesAtMost32,
374 Mask8<LANES>: Mask,
375 SimdI16<LANES>: LanesAtMost32,
376 SimdU16<LANES>: LanesAtMost32,
377 Mask16<LANES>: Mask,
378 SimdI32<LANES>: LanesAtMost32,
379 SimdU32<LANES>: LanesAtMost32,
380 SimdF32<LANES>: LanesAtMost32,
381 Mask32<LANES>: Mask,
382 SimdI64<LANES>: LanesAtMost32,
383 SimdU64<LANES>: LanesAtMost32,
384 SimdF64<LANES>: LanesAtMost32,
385 Mask64<LANES>: Mask,
386 {
387 type Bool = Wrapper<$mask<LANES>, LANES>;
388
389 fn eq(self, rhs: Self) -> Self::Bool {
390 self.0.lanes_eq(rhs.0).into()
391 }
392
393 fn ne(self, rhs: Self) -> Self::Bool {
394 self.0.lanes_ne(rhs.0).into()
395 }
396
397 fn lt(self, rhs: Self) -> Self::Bool {
398 self.0.lanes_lt(rhs.0).into()
399 }
400
401 fn gt(self, rhs: Self) -> Self::Bool {
402 self.0.lanes_gt(rhs.0).into()
403 }
404
405 fn le(self, rhs: Self) -> Self::Bool {
406 self.0.lanes_le(rhs.0).into()
407 }
408
409 fn ge(self, rhs: Self) -> Self::Bool {
410 self.0.lanes_ge(rhs.0).into()
411 }
412 }
413 };
414 }
415
416 impl_vector_compare!(SimdI8, Mask8);
417 impl_vector_compare!(SimdU8, Mask8);
418 impl_vector_compare!(SimdI16, Mask16);
419 impl_vector_compare!(SimdU16, Mask16);
420 impl_vector_compare!(SimdF16, Mask16);
421 impl_vector_compare!(SimdI32, Mask32);
422 impl_vector_compare!(SimdU32, Mask32);
423 impl_vector_compare!(SimdF32, Mask32);
424 impl_vector_compare!(SimdI64, Mask64);
425 impl_vector_compare!(SimdU64, Mask64);
426 impl_vector_compare!(SimdF64, Mask64);
427
428 macro_rules! impl_vector_mask_compare {
429 ($ty:ident) => {
430 impl<const LANES: usize> Compare for Wrapper<$ty<LANES>, LANES>
431 where
432 SimdI8<LANES>: LanesAtMost32,
433 SimdU8<LANES>: LanesAtMost32,
434 Mask8<LANES>: Mask,
435 SimdI16<LANES>: LanesAtMost32,
436 SimdU16<LANES>: LanesAtMost32,
437 Mask16<LANES>: Mask,
438 SimdI32<LANES>: LanesAtMost32,
439 SimdU32<LANES>: LanesAtMost32,
440 SimdF32<LANES>: LanesAtMost32,
441 Mask32<LANES>: Mask,
442 SimdI64<LANES>: LanesAtMost32,
443 SimdU64<LANES>: LanesAtMost32,
444 SimdF64<LANES>: LanesAtMost32,
445 Mask64<LANES>: Mask,
446 {
447 type Bool = Self;
448
449 fn eq(self, rhs: Self) -> Self::Bool {
450 !(self ^ rhs)
451 }
452 fn ne(self, rhs: Self) -> Self::Bool {
453 self ^ rhs
454 }
455 fn lt(self, rhs: Self) -> Self::Bool {
456 !self & rhs
457 }
458 fn gt(self, rhs: Self) -> Self::Bool {
459 self & !rhs
460 }
461 fn le(self, rhs: Self) -> Self::Bool {
462 !self | rhs
463 }
464 fn ge(self, rhs: Self) -> Self::Bool {
465 self | !rhs
466 }
467 }
468 };
469 }
470
471 impl_vector_mask_compare!(Mask8);
472 impl_vector_mask_compare!(Mask16);
473 impl_vector_mask_compare!(Mask32);
474 impl_vector_mask_compare!(Mask64);
475
476 macro_rules! impl_int_scalar {
477 ($ty:ident) => {
478 impl<const LANES: usize> Int for Wrapper<$ty, LANES>
479 where
480 SimdI8<LANES>: LanesAtMost32,
481 SimdU8<LANES>: LanesAtMost32,
482 Mask8<LANES>: Mask,
483 SimdI16<LANES>: LanesAtMost32,
484 SimdU16<LANES>: LanesAtMost32,
485 Mask16<LANES>: Mask,
486 SimdI32<LANES>: LanesAtMost32,
487 SimdU32<LANES>: LanesAtMost32,
488 SimdF32<LANES>: LanesAtMost32,
489 Mask32<LANES>: Mask,
490 SimdI64<LANES>: LanesAtMost32,
491 SimdU64<LANES>: LanesAtMost32,
492 SimdF64<LANES>: LanesAtMost32,
493 Mask64<LANES>: Mask,
494 {
495 fn leading_zeros(self) -> Self {
496 (self.0.leading_zeros() as $ty).into()
497 }
498
499 fn trailing_zeros(self) -> Self {
500 (self.0.trailing_zeros() as $ty).into()
501 }
502
503 fn count_ones(self) -> Self {
504 (self.0.count_ones() as $ty).into()
505 }
506
507 fn leading_ones(self) -> Self {
508 (self.0.leading_ones() as $ty).into()
509 }
510
511 fn trailing_ones(self) -> Self {
512 (self.0.trailing_ones() as $ty).into()
513 }
514
515 fn count_zeros(self) -> Self {
516 (self.0.count_zeros() as $ty).into()
517 }
518 }
519 };
520 }
521
522 macro_rules! impl_int_vector {
523 ($ty:ident) => {
524 impl<const LANES: usize> Int for Wrapper<$ty<LANES>, LANES>
525 where
526 SimdI8<LANES>: LanesAtMost32,
527 SimdU8<LANES>: LanesAtMost32,
528 Mask8<LANES>: Mask,
529 SimdI16<LANES>: LanesAtMost32,
530 SimdU16<LANES>: LanesAtMost32,
531 Mask16<LANES>: Mask,
532 SimdI32<LANES>: LanesAtMost32,
533 SimdU32<LANES>: LanesAtMost32,
534 SimdF32<LANES>: LanesAtMost32,
535 Mask32<LANES>: Mask,
536 SimdI64<LANES>: LanesAtMost32,
537 SimdU64<LANES>: LanesAtMost32,
538 SimdF64<LANES>: LanesAtMost32,
539 Mask64<LANES>: Mask,
540 {
541 fn leading_zeros(self) -> Self {
542 todo!()
543 }
544
545 fn trailing_zeros(self) -> Self {
546 todo!()
547 }
548
549 fn count_ones(self) -> Self {
550 todo!()
551 }
552
553 fn leading_ones(self) -> Self {
554 todo!()
555 }
556
557 fn trailing_ones(self) -> Self {
558 todo!()
559 }
560
561 fn count_zeros(self) -> Self {
562 todo!()
563 }
564 }
565 };
566 }
567
568 macro_rules! impl_uint_sint_vector {
569 ($uint:ident, $sint:ident) => {
570 impl_int_vector!($uint);
571 impl_int_vector!($sint);
572 impl<const LANES: usize> UInt for Wrapper<$uint<LANES>, LANES>
573 where
574 SimdI8<LANES>: LanesAtMost32,
575 SimdU8<LANES>: LanesAtMost32,
576 Mask8<LANES>: Mask,
577 SimdI16<LANES>: LanesAtMost32,
578 SimdU16<LANES>: LanesAtMost32,
579 Mask16<LANES>: Mask,
580 SimdI32<LANES>: LanesAtMost32,
581 SimdU32<LANES>: LanesAtMost32,
582 SimdF32<LANES>: LanesAtMost32,
583 Mask32<LANES>: Mask,
584 SimdI64<LANES>: LanesAtMost32,
585 SimdU64<LANES>: LanesAtMost32,
586 SimdF64<LANES>: LanesAtMost32,
587 Mask64<LANES>: Mask,
588 {
589 type PrimUInt = Self::Prim;
590 type SignedType = Wrapper<$sint<LANES>, LANES>;
591 }
592
593 impl<const LANES: usize> SInt for Wrapper<$sint<LANES>, 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 type PrimSInt = Self::Prim;
611 type UnsignedType = Wrapper<$uint<LANES>, LANES>;
612 }
613 };
614 }
615
616 impl_uint_sint_vector!(SimdU8, SimdI8);
617 impl_uint_sint_vector!(SimdU16, SimdI16);
618 impl_uint_sint_vector!(SimdU32, SimdI32);
619 impl_uint_sint_vector!(SimdU64, SimdI64);
620
621 macro_rules! impl_uint_sint_scalar {
622 ($uint:ident, $sint:ident) => {
623 impl_int_scalar!($uint);
624 impl_int_scalar!($sint);
625 impl<const LANES: usize> UInt for Wrapper<$uint, LANES>
626 where
627 SimdI8<LANES>: LanesAtMost32,
628 SimdU8<LANES>: LanesAtMost32,
629 Mask8<LANES>: Mask,
630 SimdI16<LANES>: LanesAtMost32,
631 SimdU16<LANES>: LanesAtMost32,
632 Mask16<LANES>: Mask,
633 SimdI32<LANES>: LanesAtMost32,
634 SimdU32<LANES>: LanesAtMost32,
635 SimdF32<LANES>: LanesAtMost32,
636 Mask32<LANES>: Mask,
637 SimdI64<LANES>: LanesAtMost32,
638 SimdU64<LANES>: LanesAtMost32,
639 SimdF64<LANES>: LanesAtMost32,
640 Mask64<LANES>: Mask,
641 {
642 type PrimUInt = Self::Prim;
643 type SignedType = Wrapper<$sint, LANES>;
644 }
645
646 impl<const LANES: usize> SInt for Wrapper<$sint, LANES>
647 where
648 SimdI8<LANES>: LanesAtMost32,
649 SimdU8<LANES>: LanesAtMost32,
650 Mask8<LANES>: Mask,
651 SimdI16<LANES>: LanesAtMost32,
652 SimdU16<LANES>: LanesAtMost32,
653 Mask16<LANES>: Mask,
654 SimdI32<LANES>: LanesAtMost32,
655 SimdU32<LANES>: LanesAtMost32,
656 SimdF32<LANES>: LanesAtMost32,
657 Mask32<LANES>: Mask,
658 SimdI64<LANES>: LanesAtMost32,
659 SimdU64<LANES>: LanesAtMost32,
660 SimdF64<LANES>: LanesAtMost32,
661 Mask64<LANES>: Mask,
662 {
663 type PrimSInt = Self::Prim;
664 type UnsignedType = Wrapper<$uint, LANES>;
665 }
666 };
667 }
668
669 impl_uint_sint_scalar!(u8, i8);
670 impl_uint_sint_scalar!(u16, i16);
671 impl_uint_sint_scalar!(u32, i32);
672 impl_uint_sint_scalar!(u64, i64);
673
674 macro_rules! impl_float {
675 ($ty:ident, $prim:ident, $uint:ident, $sint:ident) => {
676 impl<const LANES: usize> Float for Wrapper<$prim, LANES>
677 where
678 SimdI8<LANES>: LanesAtMost32,
679 SimdU8<LANES>: LanesAtMost32,
680 Mask8<LANES>: Mask,
681 SimdI16<LANES>: LanesAtMost32,
682 SimdU16<LANES>: LanesAtMost32,
683 Mask16<LANES>: Mask,
684 SimdI32<LANES>: LanesAtMost32,
685 SimdU32<LANES>: LanesAtMost32,
686 SimdF32<LANES>: LanesAtMost32,
687 Mask32<LANES>: Mask,
688 SimdI64<LANES>: LanesAtMost32,
689 SimdU64<LANES>: LanesAtMost32,
690 SimdF64<LANES>: LanesAtMost32,
691 Mask64<LANES>: Mask,
692 {
693 type PrimFloat = $prim;
694
695 type BitsType = Wrapper<<$prim as PrimFloat>::BitsType, LANES>;
696
697 type SignedBitsType = Wrapper<<$prim as PrimFloat>::SignedBitsType, LANES>;
698
699 fn abs(self) -> Self {
700 self.0.abs().into()
701 }
702
703 fn trunc(self) -> Self {
704 self.0.trunc().into()
705 }
706
707 fn ceil(self) -> Self {
708 self.0.ceil().into()
709 }
710
711 fn floor(self) -> Self {
712 self.0.floor().into()
713 }
714
715 fn round(self) -> Self {
716 self.0.round().into()
717 }
718
719 #[cfg(feature = "fma")]
720 fn fma(self, a: Self, b: Self) -> Self {
721 use crate::scalar::Value;
722 let a = Value(a.0);
723 let b = Value(b.0);
724 Value(self.0).fma(a, 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 PrimFloat = $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_vector_convert_from_helper {
810 ($src:ty => $dest:ty) => {
811 impl<const LANES: usize> ConvertFrom<Wrapper<$src, LANES>> for Wrapper<$dest, 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 cvt_from(v: Wrapper<$src, LANES>) -> Self {
829 let v: $dest = v.0.to();
830 v.into()
831 }
832 }
833 };
834 }
835
836 macro_rules! impl_vector_convert_from {
837 ($first:ty $(, $ty:ty)*) => {
838 $(
839 impl_vector_convert_from_helper!($first => $ty);
840 impl_vector_convert_from_helper!($ty => $first);
841 )*
842 impl_vector_convert_from![$($ty),*];
843 };
844 () => {};
845 }
846
847 impl_vector_convert_from![u8, i8, u16, i16, F16, u32, i32, u64, i64, f32, f64];
848
849 macro_rules! impl_vector_convert_from_helper {
850 (($(#[From = $From:ident])? $src:ident, $src_prim:ident) => ($(#[From = $From2:ident])? $dest:ident, $dest_prim:ident)) => {
851 impl<const LANES: usize> ConvertFrom<Wrapper<$src<LANES>, LANES>>
852 for Wrapper<$dest<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 cvt_from(v: Wrapper<$src<LANES>, LANES>) -> Self {
870 // FIXME(programmerjake): workaround https://github.com/rust-lang/stdsimd/issues/116
871 let src: [$src_prim; LANES] = v.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_from {
905 ($first:tt $(, $ty:tt)*) => {
906 $(
907 impl_vector_convert_from_helper!($first => $ty);
908 impl_vector_convert_from_helper!($ty => $first);
909 )*
910 impl_vector_convert_from![$($ty),*];
911 };
912 () => {};
913 }
914
915 impl_vector_convert_from![
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_from![
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 <$dest>::cvt_from(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 }