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