remove note to convert to sin_cos_tau instead sin_cos_pi
[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, $count_leading_zeros:ident, $count_trailing_zeros:ident, $count_ones: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 crate::algorithms::integer::$count_leading_zeros(self.ctx(), self)
543 }
544
545 fn trailing_zeros(self) -> Self {
546 crate::algorithms::integer::$count_trailing_zeros(self.ctx(), self)
547 }
548
549 fn count_ones(self) -> Self {
550 crate::algorithms::integer::$count_ones(self.ctx(), self)
551 }
552 }
553 };
554 }
555
556 macro_rules! impl_uint_sint_vector {
557 ($uint:ident, $sint:ident) => {
558 impl_int_vector!(
559 $uint,
560 count_leading_zeros_uint,
561 count_trailing_zeros_uint,
562 count_ones_uint
563 );
564 impl_int_vector!(
565 $sint,
566 count_leading_zeros_sint,
567 count_trailing_zeros_sint,
568 count_ones_sint
569 );
570 impl<const LANES: usize> UInt for Wrapper<$uint<LANES>, LANES>
571 where
572 SimdI8<LANES>: LanesAtMost32,
573 SimdU8<LANES>: LanesAtMost32,
574 Mask8<LANES>: Mask,
575 SimdI16<LANES>: LanesAtMost32,
576 SimdU16<LANES>: LanesAtMost32,
577 Mask16<LANES>: Mask,
578 SimdI32<LANES>: LanesAtMost32,
579 SimdU32<LANES>: LanesAtMost32,
580 SimdF32<LANES>: LanesAtMost32,
581 Mask32<LANES>: Mask,
582 SimdI64<LANES>: LanesAtMost32,
583 SimdU64<LANES>: LanesAtMost32,
584 SimdF64<LANES>: LanesAtMost32,
585 Mask64<LANES>: Mask,
586 {
587 type PrimUInt = Self::Prim;
588 type SignedType = Wrapper<$sint<LANES>, LANES>;
589 }
590
591 impl<const LANES: usize> SInt for Wrapper<$sint<LANES>, LANES>
592 where
593 SimdI8<LANES>: LanesAtMost32,
594 SimdU8<LANES>: LanesAtMost32,
595 Mask8<LANES>: Mask,
596 SimdI16<LANES>: LanesAtMost32,
597 SimdU16<LANES>: LanesAtMost32,
598 Mask16<LANES>: Mask,
599 SimdI32<LANES>: LanesAtMost32,
600 SimdU32<LANES>: LanesAtMost32,
601 SimdF32<LANES>: LanesAtMost32,
602 Mask32<LANES>: Mask,
603 SimdI64<LANES>: LanesAtMost32,
604 SimdU64<LANES>: LanesAtMost32,
605 SimdF64<LANES>: LanesAtMost32,
606 Mask64<LANES>: Mask,
607 {
608 type PrimSInt = Self::Prim;
609 type UnsignedType = Wrapper<$uint<LANES>, LANES>;
610 }
611 };
612 }
613
614 impl_uint_sint_vector!(SimdU8, SimdI8);
615 impl_uint_sint_vector!(SimdU16, SimdI16);
616 impl_uint_sint_vector!(SimdU32, SimdI32);
617 impl_uint_sint_vector!(SimdU64, SimdI64);
618
619 macro_rules! impl_uint_sint_scalar {
620 ($uint:ident, $sint:ident) => {
621 impl_int_scalar!($uint);
622 impl_int_scalar!($sint);
623 impl<const LANES: usize> UInt for Wrapper<$uint, LANES>
624 where
625 SimdI8<LANES>: LanesAtMost32,
626 SimdU8<LANES>: LanesAtMost32,
627 Mask8<LANES>: Mask,
628 SimdI16<LANES>: LanesAtMost32,
629 SimdU16<LANES>: LanesAtMost32,
630 Mask16<LANES>: Mask,
631 SimdI32<LANES>: LanesAtMost32,
632 SimdU32<LANES>: LanesAtMost32,
633 SimdF32<LANES>: LanesAtMost32,
634 Mask32<LANES>: Mask,
635 SimdI64<LANES>: LanesAtMost32,
636 SimdU64<LANES>: LanesAtMost32,
637 SimdF64<LANES>: LanesAtMost32,
638 Mask64<LANES>: Mask,
639 {
640 type PrimUInt = Self::Prim;
641 type SignedType = Wrapper<$sint, LANES>;
642 }
643
644 impl<const LANES: usize> SInt for Wrapper<$sint, LANES>
645 where
646 SimdI8<LANES>: LanesAtMost32,
647 SimdU8<LANES>: LanesAtMost32,
648 Mask8<LANES>: Mask,
649 SimdI16<LANES>: LanesAtMost32,
650 SimdU16<LANES>: LanesAtMost32,
651 Mask16<LANES>: Mask,
652 SimdI32<LANES>: LanesAtMost32,
653 SimdU32<LANES>: LanesAtMost32,
654 SimdF32<LANES>: LanesAtMost32,
655 Mask32<LANES>: Mask,
656 SimdI64<LANES>: LanesAtMost32,
657 SimdU64<LANES>: LanesAtMost32,
658 SimdF64<LANES>: LanesAtMost32,
659 Mask64<LANES>: Mask,
660 {
661 type PrimSInt = Self::Prim;
662 type UnsignedType = Wrapper<$uint, LANES>;
663 }
664 };
665 }
666
667 impl_uint_sint_scalar!(u8, i8);
668 impl_uint_sint_scalar!(u16, i16);
669 impl_uint_sint_scalar!(u32, i32);
670 impl_uint_sint_scalar!(u64, i64);
671
672 macro_rules! impl_float {
673 ($ty:ident, $prim:ident, $uint:ident, $sint:ident) => {
674 impl<const LANES: usize> Float for Wrapper<$prim, LANES>
675 where
676 SimdI8<LANES>: LanesAtMost32,
677 SimdU8<LANES>: LanesAtMost32,
678 Mask8<LANES>: Mask,
679 SimdI16<LANES>: LanesAtMost32,
680 SimdU16<LANES>: LanesAtMost32,
681 Mask16<LANES>: Mask,
682 SimdI32<LANES>: LanesAtMost32,
683 SimdU32<LANES>: LanesAtMost32,
684 SimdF32<LANES>: LanesAtMost32,
685 Mask32<LANES>: Mask,
686 SimdI64<LANES>: LanesAtMost32,
687 SimdU64<LANES>: LanesAtMost32,
688 SimdF64<LANES>: LanesAtMost32,
689 Mask64<LANES>: Mask,
690 {
691 type PrimFloat = $prim;
692
693 type BitsType = Wrapper<<$prim as PrimFloat>::BitsType, LANES>;
694
695 type SignedBitsType = Wrapper<<$prim as PrimFloat>::SignedBitsType, LANES>;
696
697 fn abs(self) -> Self {
698 self.0.abs().into()
699 }
700
701 fn trunc(self) -> Self {
702 self.0.trunc().into()
703 }
704
705 fn ceil(self) -> Self {
706 self.0.ceil().into()
707 }
708
709 fn floor(self) -> Self {
710 self.0.floor().into()
711 }
712
713 fn round(self) -> Self {
714 self.0.round().into()
715 }
716
717 #[cfg(feature = "fma")]
718 fn fma(self, a: Self, b: Self) -> Self {
719 use crate::scalar::Value;
720 let a = Value(a.0);
721 let b = Value(b.0);
722 Value(self.0).fma(a, b).0.into()
723 }
724
725 fn is_finite(self) -> Self::Bool {
726 self.0.is_finite().into()
727 }
728
729 fn from_bits(v: Self::BitsType) -> Self {
730 $prim::from_bits(v.0).into()
731 }
732
733 fn to_bits(self) -> Self::BitsType {
734 self.0.to_bits().into()
735 }
736 }
737
738 impl<const LANES: usize> Float for Wrapper<$ty<LANES>, LANES>
739 where
740 SimdI8<LANES>: LanesAtMost32,
741 SimdU8<LANES>: LanesAtMost32,
742 Mask8<LANES>: Mask,
743 SimdI16<LANES>: LanesAtMost32,
744 SimdU16<LANES>: LanesAtMost32,
745 Mask16<LANES>: Mask,
746 SimdI32<LANES>: LanesAtMost32,
747 SimdU32<LANES>: LanesAtMost32,
748 SimdF32<LANES>: LanesAtMost32,
749 Mask32<LANES>: Mask,
750 SimdI64<LANES>: LanesAtMost32,
751 SimdU64<LANES>: LanesAtMost32,
752 SimdF64<LANES>: LanesAtMost32,
753 Mask64<LANES>: Mask,
754 {
755 type PrimFloat = $prim;
756
757 type BitsType = Wrapper<$uint<LANES>, LANES>;
758
759 type SignedBitsType = Wrapper<$sint<LANES>, LANES>;
760
761 fn abs(self) -> Self {
762 self.0.abs().into()
763 }
764
765 fn trunc(self) -> Self {
766 self.0.trunc().into()
767 }
768
769 fn ceil(self) -> Self {
770 self.0.ceil().into()
771 }
772
773 fn floor(self) -> Self {
774 self.0.floor().into()
775 }
776
777 fn round(self) -> Self {
778 self.0.round().into()
779 }
780
781 #[cfg(feature = "fma")]
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_vector_convert_from_helper {
808 ($src:ty => $dest:ty) => {
809 impl<const LANES: usize> ConvertFrom<Wrapper<$src, LANES>> for Wrapper<$dest, 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 cvt_from(v: Wrapper<$src, LANES>) -> Self {
827 let v: $dest = v.0.to();
828 v.into()
829 }
830 }
831 };
832 }
833
834 macro_rules! impl_vector_convert_from {
835 ($first:ty $(, $ty:ty)*) => {
836 $(
837 impl_vector_convert_from_helper!($first => $ty);
838 impl_vector_convert_from_helper!($ty => $first);
839 )*
840 impl_vector_convert_from![$($ty),*];
841 };
842 () => {};
843 }
844
845 impl_vector_convert_from![u8, i8, u16, i16, F16, u32, i32, u64, i64, f32, f64];
846
847 macro_rules! impl_vector_convert_from_helper {
848 (($(#[From = $From:ident])? $src:ident, $src_prim:ident) => ($(#[From = $From2:ident])? $dest:ident, $dest_prim:ident)) => {
849 impl<const LANES: usize> ConvertFrom<Wrapper<$src<LANES>, LANES>>
850 for Wrapper<$dest<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 cvt_from(v: Wrapper<$src<LANES>, LANES>) -> Self {
868 // FIXME(programmerjake): workaround https://github.com/rust-lang/stdsimd/issues/116
869 let src: [$src_prim; LANES] = v.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_from {
903 ($first:tt $(, $ty:tt)*) => {
904 $(
905 impl_vector_convert_from_helper!($first => $ty);
906 impl_vector_convert_from_helper!($ty => $first);
907 )*
908 impl_vector_convert_from![$($ty),*];
909 };
910 () => {};
911 }
912
913 impl_vector_convert_from![
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_from![
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 <$dest>::cvt_from(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 }