1#![allow(
61 non_camel_case_types,
62 unknown_lints,
63 clippy::zero_prefixed_literal,
64 clippy::identity_op,
65 clippy::too_many_arguments,
66 clippy::type_complexity,
67 clippy::missing_transmute_annotations,
68 clippy::tabs_in_doc_comments,
69 clippy::modulo_one,
70 clippy::useless_transmute,
71 clippy::not_unsafe_ptr_arg_deref,
72 clippy::manual_is_multiple_of
73)]
74#![cfg_attr(
75 all(feature = "nightly", any(target_arch = "aarch64")),
76 feature(stdarch_neon_i8mm),
77 feature(stdarch_neon_sm4),
78 feature(stdarch_neon_ftts),
79 feature(stdarch_neon_fcma),
80 feature(stdarch_neon_dotprod)
81)]
82#![cfg_attr(not(feature = "std"), no_std)]
83#![cfg_attr(docsrs, feature(doc_cfg))]
84
85macro_rules! match_cfg {
86 (item, match cfg!() {
87 $(
88 const { $i_meta:meta } => { $( $i_tokens:tt )* },
89 )*
90 $(_ => { $( $e_tokens:tt )* },)?
91 }) => {
92 $crate::match_cfg! {
93 @__items () ;
94 $(
95 (( $i_meta ) ( $( $i_tokens )* )) ,
96 )*
97 $((() ( $( $e_tokens )* )),)?
98 }
99 };
100
101 (match cfg!() {
102 $(
103 const { $i_meta:meta } => $i_expr: expr,
104 )*
105 $(_ => $e_expr: expr,)?
106 }) => {
107 $crate::match_cfg! {
108 @ __result @ __exprs ();
109 $(
110 (( $i_meta ) ( $i_expr )) ,
111 )*
112 $((() ( $e_expr )),)?
113 }
114 };
115
116 (@__items ( $( $_:meta , )* ) ; ) => {};
121 (
122 @__items ( $( $no:meta , )* ) ;
123 (( $( $yes:meta )? ) ( $( $tokens:tt )* )) ,
124 $( $rest:tt , )*
125 ) => {
126 #[cfg(all(
130 $( $yes , )?
131 not(any( $( $no ),* ))
132 ))]
133 $crate::match_cfg! { @__identity $( $tokens )* }
134
135 $crate::match_cfg! {
139 @__items ( $( $no , )* $( $yes , )? ) ;
140 $( $rest , )*
141 }
142 };
143
144 (@ $ret: ident @ __exprs ( $( $_:meta , )* ) ; ) => {
149 $ret
150 };
151
152 (
153 @ $ret: ident @__exprs ( $( $no:meta , )* ) ;
154 (( $( $yes:meta )? ) ( $( $tokens:tt )* )) ,
155 $( $rest:tt , )*
156 ) => {{
157 #[cfg(all(
161 $( $yes , )?
162 not(any( $( $no ),* ))
163 ))]
164 let $ret = $crate::match_cfg! { @__identity $( $tokens )* };
165
166 $crate::match_cfg! {
170 @ $ret @ __exprs ( $( $no , )* $( $yes , )? ) ;
171 $( $rest , )*
172 }
173 }};
174
175 (@__identity $( $tokens:tt )* ) => {
178 $( $tokens )*
179 };
180}
181
182const MAX_REGISTER_BYTES: usize = 256;
183
184use match_cfg;
185
186#[macro_export]
190macro_rules! cast {
191 ($val: expr $(,)?) => {{
192 let __val = $val;
193 if const { false } {
194 $crate::cast(__val)
196 } else {
197 #[allow(
198 unused_unsafe,
199 unnecessary_transmutes,
200 clippy::missing_transmute_annotations
201 )]
202 unsafe {
203 ::core::mem::transmute(__val)
204 }
205 }
206 }};
207}
208
209use bytemuck::{AnyBitPattern, CheckedBitPattern, NoUninit, Pod, Zeroable, checked};
210use core::fmt::Debug;
211use core::marker::PhantomData;
212use core::mem::MaybeUninit;
213use core::ops::*;
214use core::slice::{from_raw_parts, from_raw_parts_mut};
215use num_complex::Complex;
216use paste::paste;
217use seal::Seal;
218
219#[cfg(feature = "macro")]
223#[cfg_attr(docsrs, doc(cfg(feature = "macro")))]
224pub use pulp_macro::with_simd;
225
226pub use bytemuck;
227pub use num_complex;
228
229pub type c32 = Complex<f32>;
230pub type c64 = Complex<f64>;
231
232#[derive(Copy, Clone)]
233#[repr(transparent)]
234struct DebugCplx<T>(T);
235
236unsafe impl<T: Zeroable> Zeroable for DebugCplx<T> {}
237unsafe impl<T: Pod> Pod for DebugCplx<T> {}
238
239impl Debug for DebugCplx<c32> {
240 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
241 let c32 { re, im } = self.0;
242 re.fmt(f)?;
243
244 let sign = if im.is_sign_positive() { " + " } else { " - " };
245 f.write_str(sign)?;
246
247 let im = f32::from_bits(im.to_bits() & (u32::MAX >> 1));
248 im.abs().fmt(f)?;
249
250 f.write_str("i")?;
251
252 Ok(())
253 }
254}
255
256impl Debug for DebugCplx<c64> {
257 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
258 let c64 { re, im } = self.0;
259 re.fmt(f)?;
260
261 let sign = if im.is_sign_positive() { " + " } else { " - " };
262 f.write_str(sign)?;
263
264 let im = f64::from_bits(im.to_bits() & (u64::MAX >> 1));
265 im.abs().fmt(f)?;
266
267 f.write_str("i")?;
268
269 Ok(())
270 }
271}
272
273match_cfg!(
274 item,
275 match cfg!() {
276 const { any(target_arch = "x86_64") } => {
277 #[derive(Debug, Copy, Clone)]
278 pub struct MemMask<T> {
279 mask: T,
280 load: Option<unsafe extern "C" fn()>,
281 store: Option<unsafe extern "C" fn()>,
282 }
283
284 impl<T> MemMask<T> {
285 #[inline]
286 pub fn new(mask: T) -> Self {
287 Self {
288 mask,
289 load: None,
290 store: None,
291 }
292 }
293 }
294
295 impl<T> From<T> for MemMask<T> {
296 #[inline]
297 fn from(value: T) -> Self {
298 Self {
299 mask: value,
300 load: None,
301 store: None,
302 }
303 }
304 }
305 },
306
307 _ => {
308 #[derive(Debug, Copy, Clone)]
309 pub struct MemMask<T> {
310 mask: T,
311 }
312
313 impl<T> MemMask<T> {
314 #[inline]
315 pub fn new(mask: T) -> Self {
316 Self { mask }
317 }
318 }
319
320 impl<T> From<T> for MemMask<T> {
321 #[inline]
322 fn from(value: T) -> Self {
323 Self { mask: value }
324 }
325 }
326 },
327 }
328);
329
330impl<T: Copy> MemMask<T> {
331 #[inline]
332 pub fn mask(self) -> T {
333 self.mask
334 }
335}
336
337mod seal {
338 pub trait Seal {}
339}
340
341pub trait NullaryFnOnce {
342 type Output;
343
344 fn call(self) -> Self::Output;
345}
346
347impl<R, F: FnOnce() -> R> NullaryFnOnce for F {
348 type Output = R;
349
350 #[inline(always)]
351 fn call(self) -> Self::Output {
352 self()
353 }
354}
355
356pub trait WithSimd {
357 type Output;
358
359 fn with_simd<S: Simd>(self, simd: S) -> Self::Output;
360}
361
362impl<F: NullaryFnOnce> WithSimd for F {
363 type Output = F::Output;
364
365 #[inline(always)]
366 fn with_simd<S: Simd>(self, simd: S) -> Self::Output {
367 let _simd = &simd;
368 self.call()
369 }
370}
371
372#[inline(always)]
373fn fma_f32(a: f32, b: f32, c: f32) -> f32 {
374 match_cfg!(match cfg!() {
375 const { feature = "std" } => f32::mul_add(a, b, c),
376 _ => libm::fmaf(a, b, c),
377 })
378}
379
380#[inline(always)]
381fn fma_f64(a: f64, b: f64, c: f64) -> f64 {
382 match_cfg!(match cfg!() {
383 const { feature = "std" } => f64::mul_add(a, b, c),
384 _ => libm::fma(a, b, c),
385 })
386}
387
388#[inline(always)]
389fn sqrt_f32(a: f32) -> f32 {
390 match_cfg!(match cfg!() {
391 const { feature = "std" } => f32::sqrt(a),
392 _ => libm::sqrtf(a),
393 })
394}
395
396#[inline(always)]
397fn sqrt_f64(a: f64) -> f64 {
398 match_cfg!(match cfg!() {
399 const { feature = "std" } => f64::sqrt(a, ),
400 _ => libm::sqrt(a),
401 })
402}
403
404#[inline(always)]
408unsafe fn interleave_fallback<Unit: Pod, Reg: Pod, AosReg>(x: AosReg) -> AosReg {
409 assert!(core::mem::size_of::<AosReg>() % core::mem::size_of::<Reg>() == 0);
410 assert!(core::mem::size_of::<Reg>() % core::mem::size_of::<Unit>() == 0);
411 assert!(!core::mem::needs_drop::<AosReg>());
412
413 if const { core::mem::size_of::<AosReg>() == core::mem::size_of::<Reg>() } {
414 x
415 } else {
416 let mut y = core::ptr::read(&x);
417
418 let n = const { core::mem::size_of::<AosReg>() / core::mem::size_of::<Reg>() };
419 let m = const { core::mem::size_of::<Reg>() / core::mem::size_of::<Unit>() };
420
421 unsafe {
422 let y = (&mut y) as *mut _ as *mut Unit;
423 let x = (&x) as *const _ as *const Unit;
424 for j in 0..m {
425 for i in 0..n {
426 *y.add(i + n * j) = *x.add(j + i * m);
427 }
428 }
429 }
430
431 y
432 }
433}
434
435#[inline(always)]
436unsafe fn deinterleave_fallback<Unit: Pod, Reg: Pod, SoaReg>(y: SoaReg) -> SoaReg {
437 assert!(core::mem::size_of::<SoaReg>() % core::mem::size_of::<Reg>() == 0);
438 assert!(core::mem::size_of::<Reg>() % core::mem::size_of::<Unit>() == 0);
439 assert!(!core::mem::needs_drop::<SoaReg>());
440
441 if const { core::mem::size_of::<SoaReg>() == core::mem::size_of::<Reg>() } {
442 y
443 } else {
444 let mut x = core::ptr::read(&y);
445
446 let n = const { core::mem::size_of::<SoaReg>() / core::mem::size_of::<Reg>() };
447 let m = const { core::mem::size_of::<Reg>() / core::mem::size_of::<Unit>() };
448
449 unsafe {
450 let y = (&y) as *const _ as *const Unit;
451 let x = (&mut x) as *mut _ as *mut Unit;
452 for j in 0..m {
453 for i in 0..n {
454 *x.add(j + i * m) = *y.add(i + n * j);
455 }
456 }
457 }
458
459 x
460 }
461}
462
463macro_rules! define_binop {
464 ($func: ident, $ty: ident, $out: ident) => {
465 paste! {
466 fn [<$func _ $ty s>](self, a: Self::[<$ty s>], b: Self::[<$ty s>]) -> Self::[<$out s>];
467 }
468 };
469}
470
471macro_rules! define_binop_all {
472 ($func: ident, $($ty: ident),*) => {
473 $(define_binop!($func, $ty, $ty);)*
474 };
475 ($func: ident, $($ty: ident => $out: ident),*) => {
476 $(define_binop!($func, $ty, $out);)*
477 };
478}
479
480macro_rules! transmute_binop {
481 ($func: ident, $ty: ident, $to: ident) => {
482 paste! {
483 fn [<$func _ $ty s>](self, a: Self::[<$ty s>], b: Self::[<$ty s>]) -> Self::[<$ty s>] {
484 self.[<transmute_ $ty s_ $to s>](
485 self.[<$func _ $to s>](self.[<transmute_ $to s_ $ty s>](a), self.[<transmute_ $to s_ $ty s>](b)),
486 )
487 }
488 }
489 };
490 ($func: ident, $($ty: ident => $to: ident),*) => {
491 $(transmute_binop!($func, $ty, $to);)*
492 };
493}
494
495macro_rules! define_unop {
496 ($func: ident, $ty: ident, $out: ident) => {
497 paste! {
498 fn [<$func _ $ty s>](self, a: Self::[<$ty s>]) -> Self::[<$out s>];
499 }
500 };
501}
502
503macro_rules! define_unop_all {
504 ($func: ident, $($ty: ident),*) => {
505 $(define_unop!($func, $ty, $ty);)*
506 };
507 ($func: ident, $($ty: ident => $out: ident),*) => {
508 $(define_unop!($func, $ty, $out);)*
509 };
510}
511
512macro_rules! transmute_unop {
513 ($func: ident, $ty: ident, $to: ident) => {
514 paste! {
515 fn [<$func _ $ty s>](self, a: Self::[<$ty s>]) -> Self::[<$ty s>] {
516 self.[<transmute_ $ty s_ $to s>](
517 self.[<$func _ $to s>](self.[<transmute_ $to s_ $ty s>](a)),
518 )
519 }
520 }
521 };
522 ($func: ident, $($ty: ident => $to: ident),*) => {
523 $(transmute_unop!($func, $ty, $to);)*
524 };
525}
526
527macro_rules! transmute_cmp {
528 ($func: ident, $ty: ident, $to: ident, $out: ident) => {
529 paste! {
530 fn [<$func _ $ty s>](self, a: Self::[<$ty s>], b: Self::[<$ty s>]) -> Self::[<$out s>] {
531 self.[<$func _ $to s>](self.[<transmute_ $to s_ $ty s>](a), self.[<transmute_ $to s_ $ty s>](b))
532 }
533 }
534 };
535 ($func: ident, $($ty: ident => $to: ident => $out: ident),*) => {
536 $(transmute_cmp!($func, $ty, $to, $out);)*
537 };
538}
539
540macro_rules! define_splat {
541 ($ty: ty) => {
542 paste! {
543 fn [<splat_ $ty s>](self, value: $ty) -> Self::[<$ty s>];
544 }
545 };
546 ($($ty: ident),*) => {
547 $(define_splat!($ty);)*
548 };
549}
550
551macro_rules! split_slice {
552 ($ty: ident) => {
553 paste! {
554 #[inline(always)]
555 fn [<as_mut_rsimd_ $ty s>](slice: &mut [$ty]) -> (&mut [$ty], &mut [Self::[<$ty s>]]) {
556 unsafe { rsplit_mut_slice(slice) }
557 }
558 #[inline(always)]
559 fn [<as_rsimd_ $ty s>](slice: &[$ty]) -> (&[$ty], &[Self::[<$ty s>]]) {
560 unsafe { rsplit_slice(slice) }
561 }
562 #[inline(always)]
563 fn [<as_mut_simd_ $ty s>](slice: &mut [$ty]) -> (&mut [Self::[<$ty s>]], &mut [$ty]) {
564 unsafe { split_mut_slice(slice) }
565 }
566 #[inline(always)]
567 fn [<as_simd_ $ty s>](slice: &[$ty]) -> (&[Self::[<$ty s>]], &[$ty]) {
568 unsafe { split_slice(slice) }
569 }
570 #[inline(always)]
571 fn [<as_uninit_mut_rsimd_ $ty s>](
572 slice: &mut [MaybeUninit<$ty>],
573 ) -> (&mut [MaybeUninit<$ty>], &mut [MaybeUninit<Self::[<$ty s>]>]) {
574 unsafe { rsplit_mut_slice(slice) }
575 }
576 #[inline(always)]
577 fn [<as_uninit_mut_simd_ $ty s>](
578 slice: &mut [MaybeUninit<$ty>],
579 ) -> (&mut [MaybeUninit<Self::[<$ty s>]>], &mut [MaybeUninit<$ty>]) {
580 unsafe { split_mut_slice(slice) }
581 }
582 }
583 };
584 ($($ty: ident),*) => {
585 $(split_slice!($ty);)*
586 };
587}
588
589pub unsafe trait Interleave {}
594unsafe impl<T: Pod> Interleave for T {}
595
596pub trait Simd: Seal + Debug + Copy + Send + Sync + 'static {
597 const IS_SCALAR: bool = false;
598
599 const M64_LANES: usize = core::mem::size_of::<Self::m64s>() / core::mem::size_of::<m64>();
600 const U64_LANES: usize = core::mem::size_of::<Self::u64s>() / core::mem::size_of::<u64>();
601 const I64_LANES: usize = core::mem::size_of::<Self::i64s>() / core::mem::size_of::<i64>();
602 const F64_LANES: usize = core::mem::size_of::<Self::f64s>() / core::mem::size_of::<f64>();
603 const C64_LANES: usize = core::mem::size_of::<Self::c64s>() / core::mem::size_of::<c64>();
604
605 const M32_LANES: usize = core::mem::size_of::<Self::m32s>() / core::mem::size_of::<m32>();
606 const U32_LANES: usize = core::mem::size_of::<Self::u32s>() / core::mem::size_of::<u32>();
607 const I32_LANES: usize = core::mem::size_of::<Self::i32s>() / core::mem::size_of::<i32>();
608 const F32_LANES: usize = core::mem::size_of::<Self::f32s>() / core::mem::size_of::<f32>();
609 const C32_LANES: usize = core::mem::size_of::<Self::c32s>() / core::mem::size_of::<c32>();
610
611 const M16_LANES: usize = core::mem::size_of::<Self::m16s>() / core::mem::size_of::<m16>();
612 const U16_LANES: usize = core::mem::size_of::<Self::u16s>() / core::mem::size_of::<u16>();
613 const I16_LANES: usize = core::mem::size_of::<Self::i16s>() / core::mem::size_of::<i16>();
614
615 const M8_LANES: usize = core::mem::size_of::<Self::m8s>() / core::mem::size_of::<m8>();
616 const U8_LANES: usize = core::mem::size_of::<Self::u8s>() / core::mem::size_of::<u8>();
617 const I8_LANES: usize = core::mem::size_of::<Self::i8s>() / core::mem::size_of::<i8>();
618
619 const REGISTER_COUNT: usize;
620
621 type m8s: Debug + Copy + Send + Sync + Zeroable + NoUninit + CheckedBitPattern + 'static;
622 type i8s: Debug + Copy + Send + Sync + Pod + 'static;
623 type u8s: Debug + Copy + Send + Sync + Pod + 'static;
624
625 type m16s: Debug + Copy + Send + Sync + Zeroable + NoUninit + CheckedBitPattern + 'static;
626 type i16s: Debug + Copy + Send + Sync + Pod + 'static;
627 type u16s: Debug + Copy + Send + Sync + Pod + 'static;
628
629 type m32s: Debug + Copy + Send + Sync + Zeroable + NoUninit + CheckedBitPattern + 'static;
630 type f32s: Debug + Copy + Send + Sync + Pod + 'static;
631 type c32s: Debug + Copy + Send + Sync + Pod + 'static;
632 type i32s: Debug + Copy + Send + Sync + Pod + 'static;
633 type u32s: Debug + Copy + Send + Sync + Pod + 'static;
634
635 type m64s: Debug + Copy + Send + Sync + Zeroable + NoUninit + CheckedBitPattern + 'static;
636 type f64s: Debug + Copy + Send + Sync + Pod + 'static;
637 type c64s: Debug + Copy + Send + Sync + Pod + 'static;
638 type i64s: Debug + Copy + Send + Sync + Pod + 'static;
639 type u64s: Debug + Copy + Send + Sync + Pod + 'static;
640
641 fn abs2_c32s(self, a: Self::c32s) -> Self::c32s;
643
644 fn abs2_c64s(self, a: Self::c64s) -> Self::c64s;
646 #[inline]
647 fn abs_f32s(self, a: Self::f32s) -> Self::f32s {
648 self.and_f32s(self.not_f32s(self.splat_f32s(-0.0)), a)
649 }
650 #[inline]
651 fn abs_f64s(self, a: Self::f64s) -> Self::f64s {
652 self.and_f64s(self.not_f64s(self.splat_f64s(-0.0)), a)
653 }
654 fn abs_max_c32s(self, a: Self::c32s) -> Self::c32s;
656 fn abs_max_c64s(self, a: Self::c64s) -> Self::c64s;
658
659 define_binop_all!(add, c32, c64, f32, f64, u8, u16, u32, u64);
660 define_binop_all!(
661 sub, c32, c64, f32, f64, u8, i8, u16, i16, u32, i32, u64, i64
662 );
663 define_binop_all!(mul, c32, c64, f32, f64, u16, i16, u32, i32, u64, i64);
664 define_binop_all!(div, f32, f64);
665 define_binop_all!(equal, u8 => m8, u16 => m16, u32 => m32, u64 => m64, c32 => m32, f32 => m32, c64 => m64, f64 => m64);
666 define_binop_all!(greater_than, u8 => m8, i8 => m8, u16 => m16, i16 => m16, u32 => m32, i32 => m32, u64 => m64, i64 => m64, f32 => m32, f64 => m64);
667 define_binop_all!(greater_than_or_equal, u8 => m8, i8 => m8, u16 => m16, i16 => m16, u32 => m32, i32 => m32, u64 => m64, i64 => m64, f32 => m32, f64 => m64);
668 define_binop_all!(less_than_or_equal, u8 => m8, i8 => m8, u16 => m16, i16 => m16, u32 => m32, i32 => m32, u64 => m64, i64 => m64, f32 => m32, f64 => m64);
669 define_binop_all!(less_than, u8 => m8, i8 => m8, u16 => m16, i16 => m16, u32 => m32, i32 => m32, u64 => m64, i64 => m64, f32 => m32, f64 => m64);
670
671 define_binop_all!(and, u8, u16, u32, u64);
672 define_binop_all!(or, u8, u16, u32, u64);
673 define_binop_all!(xor, u8, u16, u32, u64);
674
675 transmute_binop!(and, m8 => u8, i8 => u8, m16 => u16, i16 => u16, m32 => u32, i32 => u32, m64 => u64, i64 => u64, f32 => u32, f64 => u64);
676 transmute_binop!(or, m8 => u8, i8 => u8, m16 => u16, i16 => u16, m32 => u32, i32 => u32, m64 => u64, i64 => u64, f32 => u32, f64 => u64);
677 transmute_binop!(xor, m8 => u8, i8 => u8, m16 => u16, i16 => u16, m32 => u32, i32 => u32, m64 => u64, i64 => u64, f32 => u32, f64 => u64);
678
679 transmute_binop!(add, i8 => u8, i16 => u16, i32 => u32, i64 => u64);
680 transmute_cmp!(equal, m8 => u8 => m8, i8 => u8 => m8, m16 => u16 => m16, i16 => u16 => m16, m32 => u32 => m32, i32 => u32 => m32, m64 => u64 => m64, i64 => u64 => m64);
681
682 define_binop_all!(min, f32, f64, u8, i8, u16, i16, u32, i32, u64, i64);
683 define_binop_all!(max, f32, f64, u8, i8, u16, i16, u32, i32, u64, i64);
684
685 define_unop_all!(neg, c32, c64);
686 define_unop_all!(not, m8, u8, m16, u16, m32, u32, m64, u64);
687
688 transmute_unop!(not, i8 => u8, i16 => u16, i32 => u32, i64 => u64, f32 => u32, f64 => u64);
689
690 split_slice!(u8, i8, u16, i16, u32, i32, u64, i64, c32, f32, c64, f64);
691 define_splat!(u8, i8, u16, i16, u32, i32, u64, i64, c32, f32, c64, f64);
692
693 fn sqrt_f32s(self, a: Self::f32s) -> Self::f32s;
694 fn sqrt_f64s(self, a: Self::f64s) -> Self::f64s;
695
696 fn conj_c32s(self, a: Self::c32s) -> Self::c32s;
697 fn conj_c64s(self, a: Self::c64s) -> Self::c64s;
698 fn conj_mul_add_c32s(self, a: Self::c32s, b: Self::c32s, c: Self::c32s) -> Self::c32s;
699 fn conj_mul_add_c64s(self, a: Self::c64s, b: Self::c64s, c: Self::c64s) -> Self::c64s;
700
701 #[inline]
703 fn conj_mul_add_e_c32s(self, a: Self::c32s, b: Self::c32s, c: Self::c32s) -> Self::c32s {
704 self.conj_mul_add_c32s(a, b, c)
705 }
706 #[inline]
708 fn conj_mul_add_e_c64s(self, a: Self::c64s, b: Self::c64s, c: Self::c64s) -> Self::c64s {
709 self.conj_mul_add_c64s(a, b, c)
710 }
711 fn conj_mul_c32s(self, a: Self::c32s, b: Self::c32s) -> Self::c32s;
712
713 fn conj_mul_c64s(self, a: Self::c64s, b: Self::c64s) -> Self::c64s;
714 #[inline]
716 fn conj_mul_e_c32s(self, a: Self::c32s, b: Self::c32s) -> Self::c32s {
717 self.conj_mul_c32s(a, b)
718 }
719 #[inline]
721 fn conj_mul_e_c64s(self, a: Self::c64s, b: Self::c64s) -> Self::c64s {
722 self.conj_mul_c64s(a, b)
723 }
724 #[inline(always)]
725 fn deinterleave_shfl_f32s<T: Interleave>(self, values: T) -> T {
726 unsafe { deinterleave_fallback::<f32, Self::f32s, T>(values) }
727 }
728
729 #[inline(always)]
730 fn deinterleave_shfl_f64s<T: Interleave>(self, values: T) -> T {
731 unsafe { deinterleave_fallback::<f64, Self::f64s, T>(values) }
732 }
733
734 #[inline(always)]
735 fn first_true_m8s(self, mask: Self::m8s) -> usize {
736 if const { core::mem::size_of::<Self::m8s>() == core::mem::size_of::<Self::u8s>() } {
737 let mask: Self::u8s = bytemuck::cast(mask);
738 let slice = bytemuck::cast_slice::<Self::u8s, u8>(core::slice::from_ref(&mask));
739 let mut i = 0;
740 for &x in slice.iter() {
741 if x != 0 {
742 break;
743 }
744 i += 1;
745 }
746 i
747 } else if const { core::mem::size_of::<Self::m8s>() == core::mem::size_of::<u8>() } {
748 let mask: u8 = bytemuck::cast(mask);
749 mask.leading_zeros() as usize
750 } else if const { core::mem::size_of::<Self::m8s>() == core::mem::size_of::<u16>() } {
751 let mask: u16 = bytemuck::cast(mask);
752 mask.leading_zeros() as usize
753 } else {
754 panic!()
755 }
756 }
757
758 #[inline(always)]
759 fn first_true_m16s(self, mask: Self::m16s) -> usize {
760 if const { core::mem::size_of::<Self::m16s>() == core::mem::size_of::<Self::u16s>() } {
761 let mask: Self::u16s = bytemuck::cast(mask);
762 let slice = bytemuck::cast_slice::<Self::u16s, u16>(core::slice::from_ref(&mask));
763 let mut i = 0;
764 for &x in slice.iter() {
765 if x != 0 {
766 break;
767 }
768 i += 1;
769 }
770 i
771 } else if const { core::mem::size_of::<Self::m16s>() == core::mem::size_of::<u8>() } {
772 let mask: u8 = bytemuck::cast(mask);
773 mask.leading_zeros() as usize
774 } else if const { core::mem::size_of::<Self::m16s>() == core::mem::size_of::<u16>() } {
775 let mask: u16 = bytemuck::cast(mask);
776 mask.leading_zeros() as usize
777 } else {
778 panic!()
779 }
780 }
781
782 #[inline(always)]
783 fn first_true_m32s(self, mask: Self::m32s) -> usize {
784 if const { core::mem::size_of::<Self::m32s>() == core::mem::size_of::<Self::u32s>() } {
785 let mask: Self::u32s = bytemuck::cast(mask);
786 let slice = bytemuck::cast_slice::<Self::u32s, u32>(core::slice::from_ref(&mask));
787 let mut i = 0;
788 for &x in slice.iter() {
789 if x != 0 {
790 break;
791 }
792 i += 1;
793 }
794 i
795 } else if const { core::mem::size_of::<Self::m32s>() == core::mem::size_of::<u8>() } {
796 let mask: u8 = bytemuck::cast(mask);
797 mask.leading_zeros() as usize
798 } else if const { core::mem::size_of::<Self::m32s>() == core::mem::size_of::<u16>() } {
799 let mask: u16 = bytemuck::cast(mask);
800 mask.leading_zeros() as usize
801 } else {
802 panic!()
803 }
804 }
805
806 #[inline(always)]
807 fn first_true_m64s(self, mask: Self::m64s) -> usize {
808 if const { core::mem::size_of::<Self::m64s>() == core::mem::size_of::<Self::u64s>() } {
809 let mask: Self::u64s = bytemuck::cast(mask);
810 let slice = bytemuck::cast_slice::<Self::u64s, u64>(core::slice::from_ref(&mask));
811 let mut i = 0;
812 for &x in slice.iter() {
813 if x != 0 {
814 break;
815 }
816 i += 1;
817 }
818 i
819 } else if const { core::mem::size_of::<Self::m64s>() == core::mem::size_of::<u8>() } {
820 let mask: u8 = bytemuck::cast(mask);
821 mask.leading_zeros() as usize
822 } else if const { core::mem::size_of::<Self::m64s>() == core::mem::size_of::<u16>() } {
823 let mask: u16 = bytemuck::cast(mask);
824 mask.leading_zeros() as usize
825 } else {
826 panic!()
827 }
828 }
829
830 #[inline(always)]
831 fn interleave_shfl_f32s<T: Interleave>(self, values: T) -> T {
832 unsafe { interleave_fallback::<f32, Self::f32s, T>(values) }
833 }
834
835 #[inline(always)]
836 fn interleave_shfl_f64s<T: Interleave>(self, values: T) -> T {
837 unsafe { interleave_fallback::<f64, Self::f64s, T>(values) }
838 }
839
840 #[inline(always)]
841 fn mask_between_m8s(self, start: u8, end: u8) -> MemMask<Self::m8s> {
842 let iota: Self::u8s = const {
843 unsafe { core::mem::transmute_copy(&iota_8::<u8, { MAX_REGISTER_BYTES / 1 }>()) }
844 };
845 self.and_m8s(
846 self.greater_than_or_equal_u8s(iota, self.splat_u8s(start)),
847 self.less_than_u8s(iota, self.splat_u8s(end)),
848 )
849 .into()
850 }
851
852 #[inline(always)]
853 fn mask_between_m16s(self, start: u16, end: u16) -> MemMask<Self::m16s> {
854 let iota: Self::u16s = const {
855 unsafe { core::mem::transmute_copy(&iota_16::<u16, { MAX_REGISTER_BYTES / 2 }>()) }
856 };
857 self.and_m16s(
858 self.greater_than_or_equal_u16s(iota, self.splat_u16s(start)),
859 self.less_than_u16s(iota, self.splat_u16s(end)),
860 )
861 .into()
862 }
863
864 #[inline(always)]
865 fn mask_between_m32s(self, start: u32, end: u32) -> MemMask<Self::m32s> {
866 let iota: Self::u32s = const {
867 unsafe { core::mem::transmute_copy(&iota_32::<u32, { MAX_REGISTER_BYTES / 4 }>()) }
868 };
869 self.and_m32s(
870 self.greater_than_or_equal_u32s(iota, self.splat_u32s(start)),
871 self.less_than_u32s(iota, self.splat_u32s(end)),
872 )
873 .into()
874 }
875
876 #[inline(always)]
877 fn mask_between_m64s(self, start: u64, end: u64) -> MemMask<Self::m64s> {
878 let iota: Self::u64s = const {
879 unsafe { core::mem::transmute_copy(&iota_64::<u64, { MAX_REGISTER_BYTES / 8 }>()) }
880 };
881 self.and_m64s(
882 self.greater_than_or_equal_u64s(iota, self.splat_u64s(start)),
883 self.less_than_u64s(iota, self.splat_u64s(end)),
884 )
885 .into()
886 }
887 unsafe fn mask_load_ptr_c32s(self, mask: MemMask<Self::m32s>, ptr: *const c32) -> Self::c32s;
892 unsafe fn mask_load_ptr_c64s(self, mask: MemMask<Self::m64s>, ptr: *const c64) -> Self::c64s;
897 #[inline(always)]
902 unsafe fn mask_load_ptr_f32s(self, mask: MemMask<Self::m32s>, ptr: *const f32) -> Self::f32s {
903 self.transmute_f32s_u32s(self.mask_load_ptr_u32s(mask, ptr as *const u32))
904 }
905
906 #[inline(always)]
911 unsafe fn mask_load_ptr_f64s(self, mask: MemMask<Self::m64s>, ptr: *const f64) -> Self::f64s {
912 self.transmute_f64s_u64s(self.mask_load_ptr_u64s(mask, ptr as *const u64))
913 }
914 #[inline(always)]
919 unsafe fn mask_load_ptr_i8s(self, mask: MemMask<Self::m8s>, ptr: *const i8) -> Self::i8s {
920 self.transmute_i8s_u8s(self.mask_load_ptr_u8s(mask, ptr as *const u8))
921 }
922 #[inline(always)]
927 unsafe fn mask_load_ptr_i16s(self, mask: MemMask<Self::m16s>, ptr: *const i16) -> Self::i16s {
928 self.transmute_i16s_u16s(self.mask_load_ptr_u16s(mask, ptr as *const u16))
929 }
930 #[inline(always)]
935 unsafe fn mask_load_ptr_i32s(self, mask: MemMask<Self::m32s>, ptr: *const i32) -> Self::i32s {
936 self.transmute_i32s_u32s(self.mask_load_ptr_u32s(mask, ptr as *const u32))
937 }
938 #[inline(always)]
943 unsafe fn mask_load_ptr_i64s(self, mask: MemMask<Self::m64s>, ptr: *const i64) -> Self::i64s {
944 self.transmute_i64s_u64s(self.mask_load_ptr_u64s(mask, ptr as *const u64))
945 }
946
947 unsafe fn mask_load_ptr_u8s(self, mask: MemMask<Self::m8s>, ptr: *const u8) -> Self::u8s;
952
953 unsafe fn mask_load_ptr_u16s(self, mask: MemMask<Self::m16s>, ptr: *const u16) -> Self::u16s;
958
959 unsafe fn mask_load_ptr_u32s(self, mask: MemMask<Self::m32s>, ptr: *const u32) -> Self::u32s;
964
965 unsafe fn mask_load_ptr_u64s(self, mask: MemMask<Self::m64s>, ptr: *const u64) -> Self::u64s;
970 unsafe fn mask_store_ptr_c32s(
975 self,
976 mask: MemMask<Self::m32s>,
977 ptr: *mut c32,
978 values: Self::c32s,
979 );
980 unsafe fn mask_store_ptr_c64s(
985 self,
986 mask: MemMask<Self::m64s>,
987 ptr: *mut c64,
988 values: Self::c64s,
989 );
990 #[inline(always)]
995 unsafe fn mask_store_ptr_f32s(
996 self,
997 mask: MemMask<Self::m32s>,
998 ptr: *mut f32,
999 values: Self::f32s,
1000 ) {
1001 self.mask_store_ptr_u32s(mask, ptr as *mut u32, self.transmute_u32s_f32s(values));
1002 }
1003
1004 #[inline(always)]
1009 unsafe fn mask_store_ptr_f64s(
1010 self,
1011 mask: MemMask<Self::m64s>,
1012 ptr: *mut f64,
1013 values: Self::f64s,
1014 ) {
1015 self.mask_store_ptr_u64s(mask, ptr as *mut u64, self.transmute_u64s_f64s(values));
1016 }
1017 #[inline(always)]
1022 unsafe fn mask_store_ptr_i8s(self, mask: MemMask<Self::m8s>, ptr: *mut i8, values: Self::i8s) {
1023 self.mask_store_ptr_u8s(mask, ptr as *mut u8, self.transmute_u8s_i8s(values));
1024 }
1025 #[inline(always)]
1030 unsafe fn mask_store_ptr_i16s(
1031 self,
1032 mask: MemMask<Self::m16s>,
1033 ptr: *mut i16,
1034 values: Self::i16s,
1035 ) {
1036 self.mask_store_ptr_u16s(mask, ptr as *mut u16, self.transmute_u16s_i16s(values));
1037 }
1038 #[inline(always)]
1043 unsafe fn mask_store_ptr_i32s(
1044 self,
1045 mask: MemMask<Self::m32s>,
1046 ptr: *mut i32,
1047 values: Self::i32s,
1048 ) {
1049 self.mask_store_ptr_u32s(mask, ptr as *mut u32, self.transmute_u32s_i32s(values));
1050 }
1051 #[inline(always)]
1056 unsafe fn mask_store_ptr_i64s(
1057 self,
1058 mask: MemMask<Self::m64s>,
1059 ptr: *mut i64,
1060 values: Self::i64s,
1061 ) {
1062 self.mask_store_ptr_u64s(mask, ptr as *mut u64, self.transmute_u64s_i64s(values));
1063 }
1064
1065 unsafe fn mask_store_ptr_u8s(self, mask: MemMask<Self::m8s>, ptr: *mut u8, values: Self::u8s);
1070
1071 unsafe fn mask_store_ptr_u16s(
1076 self,
1077 mask: MemMask<Self::m16s>,
1078 ptr: *mut u16,
1079 values: Self::u16s,
1080 );
1081
1082 unsafe fn mask_store_ptr_u32s(
1087 self,
1088 mask: MemMask<Self::m32s>,
1089 ptr: *mut u32,
1090 values: Self::u32s,
1091 );
1092
1093 unsafe fn mask_store_ptr_u64s(
1098 self,
1099 mask: MemMask<Self::m64s>,
1100 ptr: *mut u64,
1101 values: Self::u64s,
1102 );
1103
1104 fn mul_add_c32s(self, a: Self::c32s, b: Self::c32s, c: Self::c32s) -> Self::c32s;
1105 fn mul_add_c64s(self, a: Self::c64s, b: Self::c64s, c: Self::c64s) -> Self::c64s;
1106 #[inline]
1108 fn mul_add_e_c32s(self, a: Self::c32s, b: Self::c32s, c: Self::c32s) -> Self::c32s {
1109 self.mul_add_c32s(a, b, c)
1110 }
1111 #[inline]
1113 fn mul_add_e_c64s(self, a: Self::c64s, b: Self::c64s, c: Self::c64s) -> Self::c64s {
1114 self.mul_add_c64s(a, b, c)
1115 }
1116 fn mul_add_e_f32s(self, a: Self::f32s, b: Self::f32s, c: Self::f32s) -> Self::f32s;
1117 fn mul_add_e_f64s(self, a: Self::f64s, b: Self::f64s, c: Self::f64s) -> Self::f64s;
1118 fn mul_add_f32s(self, a: Self::f32s, b: Self::f32s, c: Self::f32s) -> Self::f32s;
1119 fn mul_add_f64s(self, a: Self::f64s, b: Self::f64s, c: Self::f64s) -> Self::f64s;
1120
1121 #[inline(always)]
1123 fn negate_mul_add_e_f32s(self, a: Self::f32s, b: Self::f32s, c: Self::f32s) -> Self::f32s {
1124 self.mul_add_e_f32s(self.neg_f32s(a), b, c)
1125 }
1126 #[inline(always)]
1127 fn negate_mul_add_e_f64s(self, a: Self::f64s, b: Self::f64s, c: Self::f64s) -> Self::f64s {
1128 self.mul_add_e_f64s(self.neg_f64s(a), b, c)
1129 }
1130 #[inline(always)]
1131 fn negate_mul_add_f32s(self, a: Self::f32s, b: Self::f32s, c: Self::f32s) -> Self::f32s {
1132 self.mul_add_f32s(self.neg_f32s(a), b, c)
1133 }
1134 #[inline(always)]
1135 fn negate_mul_add_f64s(self, a: Self::f64s, b: Self::f64s, c: Self::f64s) -> Self::f64s {
1136 self.mul_add_f64s(self.neg_f64s(a), b, c)
1137 }
1138
1139 #[inline]
1141 fn mul_e_c32s(self, a: Self::c32s, b: Self::c32s) -> Self::c32s {
1142 self.mul_c32s(a, b)
1143 }
1144 fn mul_e_c64s(self, a: Self::c64s, b: Self::c64s) -> Self::c64s {
1146 self.mul_c64s(a, b)
1147 }
1148
1149 #[inline]
1150 fn neg_f32s(self, a: Self::f32s) -> Self::f32s {
1151 self.xor_f32s(self.splat_f32s(-0.0), a)
1152 }
1153 #[inline]
1154 fn neg_f64s(self, a: Self::f64s) -> Self::f64s {
1155 self.xor_f64s(a, self.splat_f64s(-0.0))
1156 }
1157
1158 #[inline(always)]
1159 fn partial_load_c32s(self, slice: &[c32]) -> Self::c32s {
1160 cast(self.partial_load_f64s(bytemuck::cast_slice(slice)))
1161 }
1162 #[inline(always)]
1163 fn partial_load_c64s(self, slice: &[c64]) -> Self::c64s {
1164 cast(self.partial_load_f64s(bytemuck::cast_slice(slice)))
1165 }
1166 #[inline(always)]
1167 fn partial_load_f32s(self, slice: &[f32]) -> Self::f32s {
1168 cast(self.partial_load_u32s(bytemuck::cast_slice(slice)))
1169 }
1170 #[inline(always)]
1171 fn partial_load_f64s(self, slice: &[f64]) -> Self::f64s {
1172 cast(self.partial_load_u64s(bytemuck::cast_slice(slice)))
1173 }
1174 #[inline(always)]
1175 fn partial_load_i8s(self, slice: &[i8]) -> Self::i8s {
1176 cast(self.partial_load_u8s(bytemuck::cast_slice(slice)))
1177 }
1178 #[inline(always)]
1179 fn partial_load_i16s(self, slice: &[i16]) -> Self::i16s {
1180 cast(self.partial_load_u16s(bytemuck::cast_slice(slice)))
1181 }
1182 #[inline(always)]
1183 fn partial_load_i32s(self, slice: &[i32]) -> Self::i32s {
1184 cast(self.partial_load_u32s(bytemuck::cast_slice(slice)))
1185 }
1186 #[inline(always)]
1187 fn partial_load_i64s(self, slice: &[i64]) -> Self::i64s {
1188 cast(self.partial_load_u64s(bytemuck::cast_slice(slice)))
1189 }
1190 #[inline(always)]
1191 fn partial_load_u8s(self, slice: &[u8]) -> Self::u8s {
1192 unsafe {
1193 self.mask_load_ptr_u8s(self.mask_between_m8s(0, slice.len() as u8), slice.as_ptr())
1194 }
1195 }
1196 #[inline(always)]
1197 fn partial_load_u16s(self, slice: &[u16]) -> Self::u16s {
1198 unsafe {
1199 self.mask_load_ptr_u16s(
1200 self.mask_between_m16s(0, slice.len() as u16),
1201 slice.as_ptr(),
1202 )
1203 }
1204 }
1205 #[inline(always)]
1206 fn partial_load_u32s(self, slice: &[u32]) -> Self::u32s {
1207 unsafe {
1208 self.mask_load_ptr_u32s(
1209 self.mask_between_m32s(0, slice.len() as u32),
1210 slice.as_ptr(),
1211 )
1212 }
1213 }
1214 #[inline(always)]
1215 fn partial_load_u64s(self, slice: &[u64]) -> Self::u64s {
1216 unsafe {
1217 self.mask_load_ptr_u64s(
1218 self.mask_between_m64s(0, slice.len() as u64),
1219 slice.as_ptr(),
1220 )
1221 }
1222 }
1223
1224 #[inline(always)]
1225 fn partial_store_c32s(self, slice: &mut [c32], values: Self::c32s) {
1226 self.partial_store_f64s(bytemuck::cast_slice_mut(slice), cast(values))
1227 }
1228 #[inline(always)]
1229 fn partial_store_c64s(self, slice: &mut [c64], values: Self::c64s) {
1230 self.partial_store_f64s(bytemuck::cast_slice_mut(slice), cast(values))
1231 }
1232
1233 #[inline(always)]
1234 fn partial_store_f32s(self, slice: &mut [f32], values: Self::f32s) {
1235 self.partial_store_u32s(bytemuck::cast_slice_mut(slice), cast(values))
1236 }
1237 #[inline(always)]
1238 fn partial_store_f64s(self, slice: &mut [f64], values: Self::f64s) {
1239 self.partial_store_u64s(bytemuck::cast_slice_mut(slice), cast(values))
1240 }
1241 #[inline(always)]
1242 fn partial_store_i8s(self, slice: &mut [i8], values: Self::i8s) {
1243 self.partial_store_u16s(bytemuck::cast_slice_mut(slice), cast(values))
1244 }
1245 #[inline(always)]
1246 fn partial_store_i16s(self, slice: &mut [i16], values: Self::i16s) {
1247 self.partial_store_u16s(bytemuck::cast_slice_mut(slice), cast(values))
1248 }
1249 #[inline(always)]
1250 fn partial_store_i32s(self, slice: &mut [i32], values: Self::i32s) {
1251 self.partial_store_u32s(bytemuck::cast_slice_mut(slice), cast(values))
1252 }
1253 #[inline(always)]
1254 fn partial_store_i64s(self, slice: &mut [i64], values: Self::i64s) {
1255 self.partial_store_u64s(bytemuck::cast_slice_mut(slice), cast(values))
1256 }
1257 #[inline(always)]
1258 fn partial_store_u8s(self, slice: &mut [u8], values: Self::u8s) {
1259 unsafe {
1260 self.mask_store_ptr_u8s(
1261 self.mask_between_m8s(0, slice.len() as u8),
1262 slice.as_mut_ptr(),
1263 values,
1264 )
1265 }
1266 }
1267 #[inline(always)]
1268 fn partial_store_u16s(self, slice: &mut [u16], values: Self::u16s) {
1269 unsafe {
1270 self.mask_store_ptr_u16s(
1271 self.mask_between_m16s(0, slice.len() as u16),
1272 slice.as_mut_ptr(),
1273 values,
1274 )
1275 }
1276 }
1277 #[inline(always)]
1278 fn partial_store_u32s(self, slice: &mut [u32], values: Self::u32s) {
1279 unsafe {
1280 self.mask_store_ptr_u32s(
1281 self.mask_between_m32s(0, slice.len() as u32),
1282 slice.as_mut_ptr(),
1283 values,
1284 )
1285 }
1286 }
1287 #[inline(always)]
1288 fn partial_store_u64s(self, slice: &mut [u64], values: Self::u64s) {
1289 unsafe {
1290 self.mask_store_ptr_u64s(
1291 self.mask_between_m64s(0, slice.len() as u64),
1292 slice.as_mut_ptr(),
1293 values,
1294 )
1295 }
1296 }
1297 fn reduce_max_c32s(self, a: Self::c32s) -> c32;
1298 fn reduce_max_c64s(self, a: Self::c64s) -> c64;
1299 fn reduce_max_f32s(self, a: Self::f32s) -> f32;
1300 fn reduce_max_f64s(self, a: Self::f64s) -> f64;
1301 fn reduce_min_c32s(self, a: Self::c32s) -> c32;
1302 fn reduce_min_c64s(self, a: Self::c64s) -> c64;
1303 fn reduce_min_f32s(self, a: Self::f32s) -> f32;
1304 fn reduce_min_f64s(self, a: Self::f64s) -> f64;
1305
1306 fn reduce_product_f32s(self, a: Self::f32s) -> f32;
1307 fn reduce_product_f64s(self, a: Self::f64s) -> f64;
1308 fn reduce_sum_c32s(self, a: Self::c32s) -> c32;
1309 fn reduce_sum_c64s(self, a: Self::c64s) -> c64;
1310
1311 fn reduce_sum_f32s(self, a: Self::f32s) -> f32;
1312 fn reduce_sum_f64s(self, a: Self::f64s) -> f64;
1313 #[inline(always)]
1314 fn rotate_left_c32s(self, a: Self::c32s, amount: usize) -> Self::c32s {
1315 self.rotate_right_c32s(a, amount.wrapping_neg())
1316 }
1317 #[inline(always)]
1318 fn rotate_left_c64s(self, a: Self::c64s, amount: usize) -> Self::c64s {
1319 self.rotate_right_c64s(a, amount.wrapping_neg())
1320 }
1321
1322 #[inline(always)]
1323 fn rotate_left_f32s(self, a: Self::f32s, amount: usize) -> Self::f32s {
1324 cast(self.rotate_left_u32s(cast(a), amount))
1325 }
1326 #[inline(always)]
1327 fn rotate_left_f64s(self, a: Self::f64s, amount: usize) -> Self::f64s {
1328 cast(self.rotate_left_u64s(cast(a), amount))
1329 }
1330 #[inline(always)]
1331 fn rotate_left_i32s(self, a: Self::i32s, amount: usize) -> Self::i32s {
1332 cast(self.rotate_left_u32s(cast(a), amount))
1333 }
1334
1335 #[inline(always)]
1336 fn rotate_left_i64s(self, a: Self::i64s, amount: usize) -> Self::i64s {
1337 cast(self.rotate_left_u64s(cast(a), amount))
1338 }
1339
1340 #[inline(always)]
1341 fn rotate_left_u32s(self, a: Self::u32s, amount: usize) -> Self::u32s {
1342 self.rotate_right_u32s(a, amount.wrapping_neg())
1343 }
1344 #[inline(always)]
1345 fn rotate_left_u64s(self, a: Self::u64s, amount: usize) -> Self::u64s {
1346 self.rotate_right_u64s(a, amount.wrapping_neg())
1347 }
1348 fn rotate_right_c32s(self, a: Self::c32s, amount: usize) -> Self::c32s;
1349 fn rotate_right_c64s(self, a: Self::c64s, amount: usize) -> Self::c64s;
1350 #[inline(always)]
1351 fn rotate_right_f32s(self, a: Self::f32s, amount: usize) -> Self::f32s {
1352 cast(self.rotate_right_u32s(cast(a), amount))
1353 }
1354 #[inline(always)]
1355 fn rotate_right_f64s(self, a: Self::f64s, amount: usize) -> Self::f64s {
1356 cast(self.rotate_right_u64s(cast(a), amount))
1357 }
1358 #[inline(always)]
1359 fn rotate_right_i32s(self, a: Self::i32s, amount: usize) -> Self::i32s {
1360 cast(self.rotate_right_u32s(cast(a), amount))
1361 }
1362 #[inline(always)]
1363 fn rotate_right_i64s(self, a: Self::i64s, amount: usize) -> Self::i64s {
1364 cast(self.rotate_right_u64s(cast(a), amount))
1365 }
1366 fn rotate_right_u32s(self, a: Self::u32s, amount: usize) -> Self::u32s;
1367 fn rotate_right_u64s(self, a: Self::u64s, amount: usize) -> Self::u64s;
1368
1369 #[inline]
1370 fn select_f32s(
1371 self,
1372 mask: Self::m32s,
1373 if_true: Self::f32s,
1374 if_false: Self::f32s,
1375 ) -> Self::f32s {
1376 self.transmute_f32s_u32s(self.select_u32s(
1377 mask,
1378 self.transmute_u32s_f32s(if_true),
1379 self.transmute_u32s_f32s(if_false),
1380 ))
1381 }
1382 #[inline]
1383 fn select_f64s(
1384 self,
1385 mask: Self::m64s,
1386 if_true: Self::f64s,
1387 if_false: Self::f64s,
1388 ) -> Self::f64s {
1389 self.transmute_f64s_u64s(self.select_u64s(
1390 mask,
1391 self.transmute_u64s_f64s(if_true),
1392 self.transmute_u64s_f64s(if_false),
1393 ))
1394 }
1395 #[inline]
1396 fn select_i32s(
1397 self,
1398 mask: Self::m32s,
1399 if_true: Self::i32s,
1400 if_false: Self::i32s,
1401 ) -> Self::i32s {
1402 self.transmute_i32s_u32s(self.select_u32s(
1403 mask,
1404 self.transmute_u32s_i32s(if_true),
1405 self.transmute_u32s_i32s(if_false),
1406 ))
1407 }
1408 #[inline]
1409 fn select_i64s(
1410 self,
1411 mask: Self::m64s,
1412 if_true: Self::i64s,
1413 if_false: Self::i64s,
1414 ) -> Self::i64s {
1415 self.transmute_i64s_u64s(self.select_u64s(
1416 mask,
1417 self.transmute_u64s_i64s(if_true),
1418 self.transmute_u64s_i64s(if_false),
1419 ))
1420 }
1421 fn select_u32s(self, mask: Self::m32s, if_true: Self::u32s, if_false: Self::u32s)
1422 -> Self::u32s;
1423 fn select_u64s(self, mask: Self::m64s, if_true: Self::u64s, if_false: Self::u64s)
1424 -> Self::u64s;
1425
1426 fn swap_re_im_c32s(self, a: Self::c32s) -> Self::c32s;
1427 fn swap_re_im_c64s(self, a: Self::c64s) -> Self::c64s;
1428
1429 #[inline]
1430 fn transmute_f32s_i32s(self, a: Self::i32s) -> Self::f32s {
1431 cast(a)
1432 }
1433 #[inline]
1434 fn transmute_f32s_u32s(self, a: Self::u32s) -> Self::f32s {
1435 cast(a)
1436 }
1437
1438 #[inline]
1439 fn transmute_f64s_i64s(self, a: Self::i64s) -> Self::f64s {
1440 cast(a)
1441 }
1442 #[inline]
1443 fn transmute_f64s_u64s(self, a: Self::u64s) -> Self::f64s {
1444 cast(a)
1445 }
1446 #[inline]
1447 fn transmute_i32s_f32s(self, a: Self::f32s) -> Self::i32s {
1448 cast(a)
1449 }
1450 #[inline]
1451 fn transmute_m8s_u8s(self, a: Self::u8s) -> Self::m8s {
1452 checked::cast(a)
1453 }
1454 #[inline]
1455 fn transmute_u8s_m8s(self, a: Self::m8s) -> Self::u8s {
1456 cast(a)
1457 }
1458 #[inline]
1459 fn transmute_m16s_u16s(self, a: Self::u16s) -> Self::m16s {
1460 checked::cast(a)
1461 }
1462 #[inline]
1463 fn transmute_u16s_m16s(self, a: Self::m16s) -> Self::u16s {
1464 cast(a)
1465 }
1466 #[inline]
1467 fn transmute_m32s_u32s(self, a: Self::u32s) -> Self::m32s {
1468 checked::cast(a)
1469 }
1470 #[inline]
1471 fn transmute_u32s_m32s(self, a: Self::m32s) -> Self::u32s {
1472 cast(a)
1473 }
1474 #[inline]
1475 fn transmute_m64s_u64s(self, a: Self::u64s) -> Self::m64s {
1476 checked::cast(a)
1477 }
1478 #[inline]
1479 fn transmute_u64s_m64s(self, a: Self::m64s) -> Self::u64s {
1480 cast(a)
1481 }
1482 #[inline]
1483 fn transmute_i8s_u8s(self, a: Self::u8s) -> Self::i8s {
1484 cast(a)
1485 }
1486 #[inline]
1487 fn transmute_u8s_i8s(self, a: Self::i8s) -> Self::u8s {
1488 cast(a)
1489 }
1490 #[inline]
1491 fn transmute_u16s_i16s(self, a: Self::i16s) -> Self::u16s {
1492 cast(a)
1493 }
1494 #[inline]
1495 fn transmute_i16s_u16s(self, a: Self::u16s) -> Self::i16s {
1496 cast(a)
1497 }
1498 #[inline]
1499 fn transmute_i32s_u32s(self, a: Self::u32s) -> Self::i32s {
1500 cast(a)
1501 }
1502 #[inline]
1503 fn transmute_i64s_f64s(self, a: Self::f64s) -> Self::i64s {
1504 cast(a)
1505 }
1506 #[inline]
1507 fn transmute_i64s_u64s(self, a: Self::u64s) -> Self::i64s {
1508 cast(a)
1509 }
1510
1511 #[inline]
1512 fn transmute_u32s_f32s(self, a: Self::f32s) -> Self::u32s {
1513 cast(a)
1514 }
1515 #[inline]
1516 fn transmute_u32s_i32s(self, a: Self::i32s) -> Self::u32s {
1517 cast(a)
1518 }
1519 #[inline]
1520 fn transmute_u64s_f64s(self, a: Self::f64s) -> Self::u64s {
1521 cast(a)
1522 }
1523 #[inline]
1524 fn transmute_u64s_i64s(self, a: Self::i64s) -> Self::u64s {
1525 cast(a)
1526 }
1527
1528 fn vectorize<Op: WithSimd>(self, op: Op) -> Op::Output;
1529 fn widening_mul_u32s(self, a: Self::u32s, b: Self::u32s) -> (Self::u32s, Self::u32s);
1530 fn wrapping_dyn_shl_u32s(self, a: Self::u32s, amount: Self::u32s) -> Self::u32s;
1531 fn wrapping_dyn_shr_u32s(self, a: Self::u32s, amount: Self::u32s) -> Self::u32s;
1532}
1533
1534pub trait PortableSimd: Simd {}
1535
1536impl PortableSimd for Scalar {}
1537impl PortableSimd for Scalar128b {}
1538impl PortableSimd for Scalar256b {}
1539impl PortableSimd for Scalar512b {}
1540
1541#[derive(Debug, Copy, Clone)]
1542pub struct Scalar;
1543
1544#[derive(Debug, Copy, Clone)]
1545pub struct Scalar128b;
1546#[derive(Debug, Copy, Clone)]
1547pub struct Scalar256b;
1548#[derive(Debug, Copy, Clone)]
1549pub struct Scalar512b;
1550
1551macro_rules! scalar_simd_binop_impl {
1552 ($func: ident, $op: ident, $ty: ty) => {
1553 paste! {
1554 #[inline]
1555 fn [<$func _ $ty s>](self, a: Self::[<$ty s>], b: Self::[<$ty s>],) -> Self::[<$ty s>] {
1556 let mut out = [<$ty as Default>::default(); Self::[<$ty:upper _LANES>]];
1557 let a: [$ty; Self::[<$ty:upper _LANES>]] = cast(a);
1558 let b: [$ty; Self::[<$ty:upper _LANES>]] = cast(b);
1559
1560 for i in 0..Self::[<$ty:upper _LANES>] {
1561 out[i] = a[i].$op(b[i]);
1562 }
1563
1564 cast(out)
1565 }
1566 }
1567 };
1568}
1569
1570macro_rules! scalar_simd_binop {
1571 ($func: ident, op $op: ident, $($ty: ty),*) => {
1572 $(scalar_simd_binop_impl!($func, $op, $ty);)*
1573 };
1574 ($func: ident, $($ty: ty),*) => {
1575 $(scalar_simd_binop_impl!($func, $func, $ty);)*
1576 };
1577}
1578
1579macro_rules! scalar_simd_unop_impl {
1580 ($func: ident, $op: ident, $ty: ty) => {
1581 paste! {
1582 #[inline]
1583 fn [<$func _ $ty s>](self, a: Self::[<$ty s>]) -> Self::[<$ty s>] {
1584 let mut out = [<$ty as Default>::default(); Self::[<$ty:upper _LANES>]];
1585 let a: [$ty; Self::[<$ty:upper _LANES>]] = cast(a);
1586
1587 for i in 0..Self::[<$ty:upper _LANES>] {
1588 out[i] = a[i].$op();
1589 }
1590
1591 cast(out)
1592 }
1593 }
1594 };
1595}
1596
1597macro_rules! scalar_simd_unop {
1598 ($func: ident, $($ty: ty),*) => {
1599 $(scalar_simd_unop_impl!($func, $func, $ty);)*
1600 };
1601}
1602
1603macro_rules! scalar_simd_cmp {
1604 ($func: ident, $op: ident, $ty: ty, $mask: ty) => {
1605 paste! {
1606 #[inline]
1607 fn [<$func _ $ty s>](self, a: Self::[<$ty s>], b: Self::[<$ty s>]) -> Self::[<$mask s>] {
1608 let mut out = [$mask::new(false); Self::[<$ty:upper _LANES>]];
1609 let a: [$ty; Self::[<$ty:upper _LANES>]] = cast(a);
1610 let b: [$ty; Self::[<$ty:upper _LANES>]] = cast(b);
1611 for i in 0..Self::[<$ty:upper _LANES>] {
1612 out[i] = $mask::new(a[i].$op(&b[i]));
1613 }
1614 cast(out)
1615 }
1616 }
1617 };
1618 ($func: ident, op $op: ident, $($ty: ty => $mask: ty),*) => {
1619 $(scalar_simd_cmp!($func, $op, $ty, $mask);)*
1620 };
1621 ($func: ident, $($ty: ty => $mask: ty),*) => {
1622 $(scalar_simd_cmp!($func, $func, $ty, $mask);)*
1623 };
1624}
1625
1626macro_rules! scalar_splat {
1627 ($ty: ident) => {
1628 paste! {
1629 #[inline]
1630 fn [<splat_ $ty s>](self, value: $ty) -> Self::[<$ty s>] {
1631 cast([value; Self::[<$ty:upper _LANES>]])
1632 }
1633 }
1634 };
1635 ($($ty: ident),*) => {
1636 $(scalar_splat!($ty);)*
1637 };
1638}
1639
1640macro_rules! scalar_partial_load {
1641 ($ty: ident) => {
1642 paste! {
1643 #[inline]
1644 fn [<partial_load_ $ty s>](self, slice: &[$ty]) -> Self::[<$ty s>] {
1645 let mut values = [<$ty as Default>::default(); Self::[<$ty:upper _LANES>]];
1646 for i in 0..Ord::min(values.len(), slice.len()) {
1647 values[i] = slice[i];
1648 }
1649 cast(values)
1650 }
1651 }
1652 };
1653 ($($ty: ident),*) => {
1654 $(scalar_partial_load!($ty);)*
1655 };
1656}
1657
1658macro_rules! scalar_partial_store {
1659 ($ty: ident) => {
1660 paste! {
1661 #[inline]
1662 fn [<partial_store_ $ty s>](self, slice: &mut [$ty], values: Self::[<$ty s>]) {
1663 let values: [$ty; Self::[<$ty:upper _LANES>]] = cast(values);
1664 for i in 0..Ord::min(values.len(), slice.len()) {
1665 slice[i] = values[i];
1666 }
1667 }
1668 }
1669 };
1670 ($($ty: ident),*) => {
1671 $(scalar_partial_store!($ty);)*
1672 };
1673}
1674
1675macro_rules! mask_load_ptr {
1676 ($ty: ident, $mask: ident) => {
1677 paste! {
1678 #[inline]
1679 unsafe fn [<mask_load_ptr_ $ty s>](
1680 self,
1681 mask: MemMask<Self::[<$mask s>]>,
1682 ptr: *const $ty,
1683 ) -> Self::[<$ty s>] {
1684 let mut values = [<$ty as Default>::default(); Self::[<$ty:upper _LANES>]];
1685 let mask: [$mask; Self::[<$ty:upper _LANES>]] = cast(mask.mask());
1686 for i in 0..Self::[<$ty:upper _LANES>] {
1687 if mask[i].is_set() {
1688 values[i] = *ptr.add(i);
1689 }
1690 }
1691 cast(values)
1692 }
1693 }
1694 };
1695 (cast $ty: ident, $to: ident, $mask: ident) => {
1696 paste! {
1697 #[inline]
1698 unsafe fn [<mask_load_ptr_ $ty s>](
1699 self,
1700 mask: MemMask<Self::[<$mask s>]>,
1701 ptr: *const $ty,
1702 ) -> Self::[<$ty s>] {
1703 cast(self.[<mask_load_ptr_ $to s>](mask, ptr as *const $to))
1704 }
1705 }
1706 };
1707 ($($ty: ident: $mask: ident),*) => {
1708 $(mask_load_ptr!($ty, $mask);)*
1709 };
1710 (cast $($ty: ident: $mask: ident => $to: ident),*) => {
1711 $(mask_load_ptr!(cast $ty, $to, $mask);)*
1712 };
1713}
1714
1715macro_rules! mask_store_ptr {
1716 ($ty: ident, $mask: ident) => {
1717 paste! {
1718 #[inline]
1719 unsafe fn [<mask_store_ptr_ $ty s>](
1720 self,
1721 mask: MemMask<Self::[<$mask s>]>,
1722 ptr: *mut $ty,
1723 values: Self::[<$ty s>],
1724 ) {
1725 let mask: [$mask; Self::[<$ty:upper _LANES>]] = cast(mask.mask());
1726 let values: [$ty; Self::[<$ty:upper _LANES>]] = cast(values);
1727 for i in 0..Self::[<$ty:upper _LANES>] {
1728 if mask[i].is_set() {
1729 *ptr.add(i) = values[i];
1730 }
1731 }
1732 }
1733 }
1734 };
1735 (cast $ty: ident, $to: ident, $mask: ident) => {
1736 paste! {
1737 #[inline]
1738 unsafe fn [<mask_store_ptr_ $ty s>](
1739 self,
1740 mask: MemMask<Self::[<$mask s>]>,
1741 ptr: *mut $ty,
1742 values: Self::[<$ty s>],
1743 ) {
1744 self.[<mask_store_ptr_ $to s>](mask, ptr as *mut $to, cast(values));
1745 }
1746 }
1747 };
1748 ($($ty: ident: $mask: ident),*) => {
1749 $(mask_store_ptr!($ty, $mask);)*
1750 };
1751 (cast $($ty: ident: $mask: ident => $to: ident),*) => {
1752 $(mask_store_ptr!(cast $ty, $to, $mask);)*
1753 };
1754}
1755
1756macro_rules! scalar_simd {
1757 ($ty: ty, $register_count: expr, $m8s: ty, $i8s: ty, $u8s: ty, $m16s: ty, $i16s: ty, $u16s: ty, $m32s: ty, $f32s: ty, $i32s: ty, $u32s: ty, $m64s: ty, $f64s: ty, $i64s: ty, $u64s: ty $(,)?) => {
1758 impl Seal for $ty {}
1759 impl Simd for $ty {
1760 type m8s = $m8s;
1761 type m16s = $m16s;
1762 type c32s = $f32s;
1763 type c64s = $f64s;
1764 type f32s = $f32s;
1765 type f64s = $f64s;
1766 type i16s = $i16s;
1767 type i32s = $i32s;
1768 type i64s = $i64s;
1769 type i8s = $i8s;
1770 type m32s = $m32s;
1771 type m64s = $m64s;
1772 type u16s = $u16s;
1773 type u32s = $u32s;
1774 type u64s = $u64s;
1775 type u8s = $u8s;
1776
1777 const REGISTER_COUNT: usize = $register_count;
1778
1779 scalar_simd_binop!(min, u8, i8, u16, i16, u32, i32, u64, i64, f32, f64);
1780
1781 scalar_simd_binop!(max, u8, i8, u16, i16, u32, i32, u64, i64, f32, f64);
1782
1783 scalar_simd_binop!(add, c32, f32, c64, f64);
1784 scalar_simd_binop!(add, op wrapping_add, u8, i8, u16, i16, u32, i32, u64, i64);
1785 scalar_simd_binop!(sub, c32, f32, c64, f64);
1786 scalar_simd_binop!(sub, op wrapping_sub, u8, i8, u16, i16, u32, i32, u64, i64);
1787 scalar_simd_binop!(mul, c32, f32, c64, f64);
1788 scalar_simd_binop!(mul, op wrapping_mul, u16, i16, u32, i32, u64, i64);
1789 scalar_simd_binop!(div, f32, f64);
1790
1791 scalar_simd_binop!(and, op bitand, u8, u16, u32, u64);
1792 scalar_simd_binop!(or, op bitor, u8, u16, u32, u64);
1793 scalar_simd_binop!(xor, op bitxor, u8, u16, u32, u64);
1794
1795 scalar_simd_cmp!(equal, op eq, u8 => m8, u16 => m16, u32 => m32, u64 => m64, c32 => m32, f32 => m32, c64 => m64, f64 => m64);
1796 scalar_simd_cmp!(greater_than, op gt, u8 => m8, i8 => m8, u16 => m16, i16 => m16, u32 => m32, i32 => m32, u64 => m64, i64 => m64, f32 => m32, f64 => m64);
1797 scalar_simd_cmp!(greater_than_or_equal, op ge, u8 => m8, i8 => m8, u16 => m16, i16 => m16, u32 => m32, i32 => m32, u64 => m64, i64 => m64, f32 => m32, f64 => m64);
1798 scalar_simd_cmp!(less_than_or_equal, op le, u8 => m8, i8 => m8, u16 => m16, i16 => m16, u32 => m32, i32 => m32, u64 => m64, i64 => m64, f32 => m32, f64 => m64);
1799 scalar_simd_cmp!(less_than, op lt, u8 => m8, i8 => m8, u16 => m16, i16 => m16, u32 => m32, i32 => m32, u64 => m64, i64 => m64, f32 => m32, f64 => m64);
1800
1801 scalar_simd_unop!(not, m8, u8, m16, u16, m32, u32, m64, u64);
1802
1803 scalar_splat!(u8, i8, u16, i16, u32, i32, u64, i64, f32, f64);
1804
1805 scalar_partial_load!(u8, i8, u16, i16, u32, i32, u64, i64, f32, f64);
1806 scalar_partial_store!(u8, i8, u16, i16, u32, i32, u64, i64, f32, f64);
1807
1808 mask_load_ptr!(u8: m8, u16: m16, u32: m32, u64: m64);
1809 mask_load_ptr!(cast i8: m8 => u8, i16: m16 => u16, i32: m32 => u32, i64: m64 => u64, c32: m32 => u32, f32: m32 => u32, c64: m64 => u64, f64: m64 => u64);
1810 mask_store_ptr!(u8: m8, u16: m16, u32: m32, u64: m64);
1811 mask_store_ptr!(cast i8: m8 => u8, i16: m16 => u16, i32: m32 => u32, i64: m64 => u64, c32: m32 => u32, f32: m32 => u32, c64: m64 => u64, f64: m64 => u64);
1812
1813 #[inline]
1814 fn vectorize<Op: WithSimd>(self, op: Op) -> Op::Output {
1815 op.with_simd(self)
1816 }
1817
1818 #[inline]
1819 fn and_m32s(self, a: Self::m32s, b: Self::m32s) -> Self::m32s {
1820 let mut out = [m32::new(false); Self::F32_LANES];
1821 let a: [m32; Self::F32_LANES] = cast(a);
1822 let b: [m32; Self::F32_LANES] = cast(b);
1823 for i in 0..Self::F32_LANES {
1824 out[i] = a[i] & b[i];
1825 }
1826 cast(out)
1827 }
1828
1829 #[inline]
1830 fn or_m32s(self, a: Self::m32s, b: Self::m32s) -> Self::m32s {
1831 let mut out = [m32::new(false); Self::F32_LANES];
1832 let a: [m32; Self::F32_LANES] = cast(a);
1833 let b: [m32; Self::F32_LANES] = cast(b);
1834 for i in 0..Self::F32_LANES {
1835 out[i] = a[i] | b[i];
1836 }
1837 cast(out)
1838 }
1839
1840 #[inline]
1841 fn xor_m32s(self, a: Self::m32s, b: Self::m32s) -> Self::m32s {
1842 let mut out = [m32::new(false); Self::F32_LANES];
1843 let a: [m32; Self::F32_LANES] = cast(a);
1844 let b: [m32; Self::F32_LANES] = cast(b);
1845 for i in 0..Self::F32_LANES {
1846 out[i] = a[i] ^ b[i];
1847 }
1848 cast(out)
1849 }
1850
1851 #[inline]
1852 fn and_m64s(self, a: Self::m64s, b: Self::m64s) -> Self::m64s {
1853 let mut out = [m64::new(false); Self::F64_LANES];
1854 let a: [m64; Self::F64_LANES] = cast(a);
1855 let b: [m64; Self::F64_LANES] = cast(b);
1856 for i in 0..Self::F64_LANES {
1857 out[i] = a[i] & b[i];
1858 }
1859 cast(out)
1860 }
1861
1862 #[inline]
1863 fn or_m64s(self, a: Self::m64s, b: Self::m64s) -> Self::m64s {
1864 let mut out = [m64::new(false); Self::F64_LANES];
1865 let a: [m64; Self::F64_LANES] = cast(a);
1866 let b: [m64; Self::F64_LANES] = cast(b);
1867 for i in 0..Self::F64_LANES {
1868 out[i] = a[i] | b[i];
1869 }
1870 cast(out)
1871 }
1872
1873 #[inline]
1874 fn xor_m64s(self, a: Self::m64s, b: Self::m64s) -> Self::m64s {
1875 let mut out = [m64::new(false); Self::F64_LANES];
1876 let a: [m64; Self::F64_LANES] = cast(a);
1877 let b: [m64; Self::F64_LANES] = cast(b);
1878 for i in 0..Self::F64_LANES {
1879 out[i] = a[i] ^ b[i];
1880 }
1881 cast(out)
1882 }
1883
1884 #[inline]
1885 fn select_u32s(
1886 self,
1887 mask: Self::m32s,
1888 if_true: Self::u32s,
1889 if_false: Self::u32s,
1890 ) -> Self::u32s {
1891 let mut out = [0u32; Self::F32_LANES];
1892 let mask: [m32; Self::F32_LANES] = cast(mask);
1893 let if_true: [u32; Self::F32_LANES] = cast(if_true);
1894 let if_false: [u32; Self::F32_LANES] = cast(if_false);
1895
1896 for i in 0..Self::F32_LANES {
1897 out[i] = if mask[i].is_set() {
1898 if_true[i]
1899 } else {
1900 if_false[i]
1901 };
1902 }
1903
1904 cast(out)
1905 }
1906
1907 #[inline]
1908 fn select_u64s(
1909 self,
1910 mask: Self::m64s,
1911 if_true: Self::u64s,
1912 if_false: Self::u64s,
1913 ) -> Self::u64s {
1914 let mut out = [0u64; Self::F64_LANES];
1915 let mask: [m64; Self::F64_LANES] = cast(mask);
1916 let if_true: [u64; Self::F64_LANES] = cast(if_true);
1917 let if_false: [u64; Self::F64_LANES] = cast(if_false);
1918
1919 for i in 0..Self::F64_LANES {
1920 out[i] = if mask[i].is_set() {
1921 if_true[i]
1922 } else {
1923 if_false[i]
1924 };
1925 }
1926
1927 cast(out)
1928 }
1929
1930 #[inline]
1931 fn wrapping_dyn_shl_u32s(self, a: Self::u32s, amount: Self::u32s) -> Self::u32s {
1932 let mut out = [0u32; Self::F32_LANES];
1933 let a: [u32; Self::F32_LANES] = cast(a);
1934 let b: [u32; Self::F32_LANES] = cast(amount);
1935 for i in 0..Self::F32_LANES {
1936 out[i] = a[i].wrapping_shl(b[i]);
1937 }
1938 cast(out)
1939 }
1940
1941 #[inline]
1942 fn wrapping_dyn_shr_u32s(self, a: Self::u32s, amount: Self::u32s) -> Self::u32s {
1943 let mut out = [0u32; Self::F32_LANES];
1944 let a: [u32; Self::F32_LANES] = cast(a);
1945 let b: [u32; Self::F32_LANES] = cast(amount);
1946 for i in 0..Self::F32_LANES {
1947 out[i] = a[i].wrapping_shr(b[i]);
1948 }
1949 cast(out)
1950 }
1951
1952 #[inline]
1953 fn widening_mul_u32s(self, a: Self::u32s, b: Self::u32s) -> (Self::u32s, Self::u32s) {
1954 let mut lo = [0u32; Self::F32_LANES];
1955 let mut hi = [0u32; Self::F32_LANES];
1956 let a: [u32; Self::F32_LANES] = cast(a);
1957 let b: [u32; Self::F32_LANES] = cast(b);
1958 for i in 0..Self::F32_LANES {
1959 let m = a[i] as u64 * b[i] as u64;
1960
1961 (lo[i], hi[i]) = (m as u32, (m >> 32) as u32);
1962 }
1963 (cast(lo), cast(hi))
1964 }
1965
1966 #[inline]
1967 fn mul_add_f32s(self, a: Self::f32s, b: Self::f32s, c: Self::f32s) -> Self::f32s {
1968 let mut out = [0.0f32; Self::F32_LANES];
1969 let a: [f32; Self::F32_LANES] = cast(a);
1970 let b: [f32; Self::F32_LANES] = cast(b);
1971 let c: [f32; Self::F32_LANES] = cast(c);
1972
1973 for i in 0..Self::F32_LANES {
1974 out[i] = fma_f32(a[i], b[i], c[i]);
1975 }
1976
1977 cast(out)
1978 }
1979
1980 #[inline]
1981 fn negate_mul_add_f32s(self, a: Self::f32s, b: Self::f32s, c: Self::f32s) -> Self::f32s {
1982 let mut out = [0.0f32; Self::F32_LANES];
1983
1984 let a: [f32; Self::F32_LANES] = cast(a);
1985 let b: [f32; Self::F32_LANES] = cast(b);
1986 let c: [f32; Self::F32_LANES] = cast(c);
1987
1988 for i in 0..Self::F32_LANES {
1989 out[i] = fma_f32(-a[i], b[i], c[i]);
1990 }
1991
1992 cast(out)
1993 }
1994
1995 #[inline]
1996 fn reduce_sum_f32s(self, a: Self::f32s) -> f32 {
1997 let mut a: [f32; Self::F32_LANES] = cast(a);
1998
1999 let mut n = Self::F32_LANES;
2000 while n > 1 {
2001 n /= 2;
2002 for i in 0..n {
2003 a[i] += a[i + n];
2004 }
2005 }
2006
2007 a[0]
2008 }
2009
2010 #[inline]
2011 fn reduce_product_f32s(self, a: Self::f32s) -> f32 {
2012 let mut a: [f32; Self::F32_LANES] = cast(a);
2013
2014 let mut n = Self::F32_LANES;
2015 while n > 1 {
2016 n /= 2;
2017 for i in 0..n {
2018 a[i] *= a[i + n];
2019 }
2020 }
2021
2022 a[0]
2023 }
2024
2025 #[inline]
2026 fn reduce_min_f32s(self, a: Self::f32s) -> f32 {
2027 let mut a: [f32; Self::F32_LANES] = cast(a);
2028
2029 let mut n = Self::F32_LANES;
2030 while n > 1 {
2031 n /= 2;
2032 for i in 0..n {
2033 a[i] = f32::min(a[i], a[i + n]);
2034 }
2035 }
2036
2037 a[0]
2038 }
2039
2040 #[inline]
2041 fn reduce_max_f32s(self, a: Self::f32s) -> f32 {
2042 let mut a: [f32; Self::F32_LANES] = cast(a);
2043
2044 let mut n = Self::F32_LANES;
2045 while n > 1 {
2046 n /= 2;
2047 for i in 0..n {
2048 a[i] = f32::max(a[i], a[i + n]);
2049 }
2050 }
2051
2052 a[0]
2053 }
2054
2055 #[inline]
2056 fn splat_c32s(self, value: c32) -> Self::c32s {
2057 cast([value; Self::C32_LANES])
2058 }
2059
2060 #[inline]
2061 fn conj_c32s(self, a: Self::c32s) -> Self::c32s {
2062 let mut out = [c32::ZERO; Self::C32_LANES];
2063 let a: [c32; Self::C32_LANES] = cast(a);
2064
2065 for i in 0..Self::C32_LANES {
2066 out[i] = c32::new(a[i].re, -a[i].im);
2067 }
2068
2069 cast(out)
2070 }
2071
2072 #[inline]
2073 fn neg_c32s(self, a: Self::c32s) -> Self::c32s {
2074 let mut out = [c32::ZERO; Self::C32_LANES];
2075 let a: [c32; Self::C32_LANES] = cast(a);
2076
2077 for i in 0..Self::C32_LANES {
2078 out[i] = c32::new(-a[i].re, -a[i].im);
2079 }
2080
2081 cast(out)
2082 }
2083
2084 #[inline]
2085 fn swap_re_im_c32s(self, a: Self::c32s) -> Self::c32s {
2086 let mut out = [c32::ZERO; Self::C32_LANES];
2087 let a: [c32; Self::C32_LANES] = cast(a);
2088
2089 for i in 0..Self::C32_LANES {
2090 out[i] = c32::new(a[i].im, a[i].re);
2091 }
2092
2093 cast(out)
2094 }
2095
2096 #[inline]
2097 fn conj_mul_c32s(self, a: Self::c32s, b: Self::c32s) -> Self::c32s {
2098 let mut out = [c32::ZERO; Self::C32_LANES];
2099 let a: [c32; Self::C32_LANES] = cast(a);
2100 let b: [c32; Self::C32_LANES] = cast(b);
2101
2102 for i in 0..Self::C32_LANES {
2103 out[i].re = fma_f32(a[i].re, b[i].re, a[i].im * b[i].im);
2104 out[i].im = fma_f32(a[i].re, b[i].im, -(a[i].im * b[i].re));
2105 }
2106
2107 cast(out)
2108 }
2109
2110 #[inline]
2111 fn mul_add_c32s(self, a: Self::c32s, b: Self::c32s, c: Self::c32s) -> Self::c32s {
2112 let mut out = [c32::ZERO; Self::C32_LANES];
2113 let a: [c32; Self::C32_LANES] = cast(a);
2114 let b: [c32; Self::C32_LANES] = cast(b);
2115 let c: [c32; Self::C32_LANES] = cast(c);
2116
2117 for i in 0..Self::C32_LANES {
2118 out[i].re = fma_f32(a[i].re, b[i].re, -fma_f32(a[i].im, b[i].im, -c[i].re));
2119 out[i].im = fma_f32(a[i].re, b[i].im, fma_f32(a[i].im, b[i].re, c[i].im));
2120 }
2121
2122 cast(out)
2123 }
2124
2125 #[inline]
2126 fn conj_mul_add_c32s(self, a: Self::c32s, b: Self::c32s, c: Self::c32s) -> Self::c32s {
2127 let mut out = [c32::ZERO; Self::C32_LANES];
2128 let a: [c32; Self::C32_LANES] = cast(a);
2129 let b: [c32; Self::C32_LANES] = cast(b);
2130 let c: [c32; Self::C32_LANES] = cast(c);
2131
2132 for i in 0..Self::C32_LANES {
2133 out[i].re = fma_f32(a[i].re, b[i].re, fma_f32(a[i].im, b[i].im, c[i].re));
2134 out[i].im = fma_f32(a[i].re, b[i].im, -fma_f32(a[i].im, b[i].re, -c[i].im));
2135 }
2136
2137 cast(out)
2138 }
2139
2140 #[inline]
2141 fn abs2_c32s(self, a: Self::c32s) -> Self::c32s {
2142 let mut out = [c32::ZERO; Self::C32_LANES];
2143 let a: [c32; Self::C32_LANES] = cast(a);
2144
2145 for i in 0..Self::C32_LANES {
2146 let x = a[i].re * a[i].re + a[i].im * a[i].im;
2147 out[i].re = x;
2148 out[i].im = x;
2149 }
2150
2151 cast(out)
2152 }
2153
2154 #[inline]
2155 fn abs_max_c32s(self, a: Self::c32s) -> Self::c32s {
2156 let mut out = [c32::ZERO; Self::C32_LANES];
2157 let a: [c32; Self::C32_LANES] = cast(self.abs_f32s(a));
2158
2159 for i in 0..Self::C32_LANES {
2160 let x = f32::max(a[i].re, a[i].im);
2161 out[i].re = x;
2162 out[i].im = x;
2163 }
2164
2165 cast(out)
2166 }
2167
2168 #[inline]
2169 fn reduce_sum_c32s(self, a: Self::c32s) -> c32 {
2170 let mut a: [c32; Self::C32_LANES] = cast(a);
2171
2172 let mut n = Self::C32_LANES;
2173 while n > 1 {
2174 n /= 2;
2175 for i in 0..n {
2176 a[i].re += a[i + n].re;
2177 a[i].im += a[i + n].im;
2178 }
2179 }
2180
2181 a[0]
2182 }
2183
2184 #[inline]
2185 fn reduce_min_c32s(self, a: Self::c32s) -> c32 {
2186 let mut a: [c32; Self::C32_LANES] = cast(a);
2187
2188 let mut n = Self::C32_LANES;
2189 while n > 1 {
2190 n /= 2;
2191 for i in 0..n {
2192 a[i].re = f32::min(a[i].re, a[i + n].re);
2193 a[i].im = f32::min(a[i].im, a[i + n].im);
2194 }
2195 }
2196
2197 a[0]
2198 }
2199
2200 #[inline]
2201 fn reduce_max_c32s(self, a: Self::c32s) -> c32 {
2202 let mut a: [c32; Self::C32_LANES] = cast(a);
2203
2204 let mut n = Self::C32_LANES;
2205 while n > 1 {
2206 n /= 2;
2207 for i in 0..n {
2208 a[i].re = f32::max(a[i].re, a[i + n].re);
2209 a[i].im = f32::max(a[i].im, a[i + n].im);
2210 }
2211 }
2212
2213 a[0]
2214 }
2215
2216 #[inline]
2217 fn rotate_right_u32s(self, a: Self::u32s, amount: usize) -> Self::u32s {
2218 let mut a: [u32; Self::F32_LANES] = cast(a);
2219 let amount = amount % Self::F32_LANES;
2220 a.rotate_right(amount);
2221 cast(a)
2222 }
2223
2224 #[inline]
2225 fn rotate_right_c32s(self, a: Self::c32s, amount: usize) -> Self::c32s {
2226 let mut a: [c32; Self::C32_LANES] = cast(a);
2227 let amount = amount % Self::C32_LANES;
2228 a.rotate_right(amount);
2229 cast(a)
2230 }
2231
2232 #[inline]
2233 fn mul_add_f64s(self, a: Self::f64s, b: Self::f64s, c: Self::f64s) -> Self::f64s {
2234 let mut out = [0.0f64; Self::F64_LANES];
2235 let a: [f64; Self::F64_LANES] = cast(a);
2236 let b: [f64; Self::F64_LANES] = cast(b);
2237 let c: [f64; Self::F64_LANES] = cast(c);
2238
2239 for i in 0..Self::F64_LANES {
2240 out[i] = fma_f64(a[i], b[i], c[i]);
2241 }
2242
2243 cast(out)
2244 }
2245
2246 #[inline]
2247 fn negate_mul_add_f64s(self, a: Self::f64s, b: Self::f64s, c: Self::f64s) -> Self::f64s {
2248 let mut out = [0.0f64; Self::F64_LANES];
2249 let a: [f64; Self::F64_LANES] = cast(a);
2250 let b: [f64; Self::F64_LANES] = cast(b);
2251 let c: [f64; Self::F64_LANES] = cast(c);
2252
2253 for i in 0..Self::F64_LANES {
2254 out[i] = fma_f64(-a[i], b[i], c[i]);
2255 }
2256
2257 cast(out)
2258 }
2259
2260 #[inline]
2261 fn reduce_sum_f64s(self, a: Self::f64s) -> f64 {
2262 let mut a: [f64; Self::F64_LANES] = cast(a);
2263
2264 let mut n = Self::F64_LANES;
2265 while n > 1 {
2266 n /= 2;
2267 for i in 0..n {
2268 a[i] += a[i + n];
2269 }
2270 }
2271
2272 a[0]
2273 }
2274
2275 #[inline]
2276 fn reduce_product_f64s(self, a: Self::f64s) -> f64 {
2277 let mut a: [f64; Self::F64_LANES] = cast(a);
2278
2279 let mut n = Self::F64_LANES;
2280 while n > 1 {
2281 n /= 2;
2282 for i in 0..n {
2283 a[i] *= a[i + n];
2284 }
2285 }
2286
2287 a[0]
2288 }
2289
2290 #[inline]
2291 fn reduce_min_f64s(self, a: Self::f64s) -> f64 {
2292 let mut a: [f64; Self::F64_LANES] = cast(a);
2293
2294 let mut n = Self::F64_LANES;
2295 while n > 1 {
2296 n /= 2;
2297 for i in 0..n {
2298 a[i] = f64::min(a[i], a[i + n]);
2299 }
2300 }
2301
2302 a[0]
2303 }
2304
2305 #[inline]
2306 fn reduce_max_f64s(self, a: Self::f64s) -> f64 {
2307 let mut a: [f64; Self::F64_LANES] = cast(a);
2308
2309 let mut n = Self::F64_LANES;
2310 while n > 1 {
2311 n /= 2;
2312 for i in 0..n {
2313 a[i] = f64::max(a[i], a[i + n]);
2314 }
2315 }
2316
2317 a[0]
2318 }
2319
2320 #[inline]
2321 fn splat_c64s(self, value: c64) -> Self::c64s {
2322 cast([value; Self::C64_LANES])
2323 }
2324
2325 #[inline]
2326 fn conj_c64s(self, a: Self::c64s) -> Self::c64s {
2327 let mut out = [c64::ZERO; Self::C64_LANES];
2328 let a: [c64; Self::C64_LANES] = cast(a);
2329
2330 for i in 0..Self::C64_LANES {
2331 out[i] = c64::new(a[i].re, -a[i].im);
2332 }
2333
2334 cast(out)
2335 }
2336
2337 #[inline]
2338 fn neg_c64s(self, a: Self::c64s) -> Self::c64s {
2339 let mut out = [c64::ZERO; Self::C64_LANES];
2340 let a: [c64; Self::C64_LANES] = cast(a);
2341
2342 for i in 0..Self::C64_LANES {
2343 out[i] = c64::new(-a[i].re, -a[i].im);
2344 }
2345
2346 cast(out)
2347 }
2348
2349 #[inline]
2350 fn swap_re_im_c64s(self, a: Self::c64s) -> Self::c64s {
2351 let mut out = [c64::ZERO; Self::C64_LANES];
2352 let a: [c64; Self::C64_LANES] = cast(a);
2353
2354 for i in 0..Self::C64_LANES {
2355 out[i] = c64::new(a[i].im, a[i].re);
2356 }
2357
2358 cast(out)
2359 }
2360
2361 #[inline]
2362 fn conj_mul_c64s(self, a: Self::c64s, b: Self::c64s) -> Self::c64s {
2363 let mut out = [c64::ZERO; Self::C64_LANES];
2364 let a: [c64; Self::C64_LANES] = cast(a);
2365 let b: [c64; Self::C64_LANES] = cast(b);
2366
2367 for i in 0..Self::C64_LANES {
2368 out[i].re = fma_f64(a[i].re, b[i].re, a[i].im * b[i].im);
2369 out[i].im = fma_f64(a[i].re, b[i].im, -(a[i].im * b[i].re));
2370 }
2371
2372 cast(out)
2373 }
2374
2375 #[inline]
2376 fn mul_add_c64s(self, a: Self::c64s, b: Self::c64s, c: Self::c64s) -> Self::c64s {
2377 let mut out = [c64::ZERO; Self::C64_LANES];
2378 let a: [c64; Self::C64_LANES] = cast(a);
2379 let b: [c64; Self::C64_LANES] = cast(b);
2380 let c: [c64; Self::C64_LANES] = cast(c);
2381
2382 for i in 0..Self::C64_LANES {
2383 out[i].re = fma_f64(a[i].re, b[i].re, -fma_f64(a[i].im, b[i].im, -c[i].re));
2384 out[i].im = fma_f64(a[i].re, b[i].im, fma_f64(a[i].im, b[i].re, c[i].im));
2385 }
2386
2387 cast(out)
2388 }
2389
2390 #[inline]
2391 fn conj_mul_add_c64s(self, a: Self::c64s, b: Self::c64s, c: Self::c64s) -> Self::c64s {
2392 let mut out = [c64::ZERO; Self::C64_LANES];
2393 let a: [c64; Self::C64_LANES] = cast(a);
2394 let b: [c64; Self::C64_LANES] = cast(b);
2395 let c: [c64; Self::C64_LANES] = cast(c);
2396
2397 for i in 0..Self::C64_LANES {
2398 out[i].re = fma_f64(a[i].re, b[i].re, fma_f64(a[i].im, b[i].im, c[i].re));
2399 out[i].im = fma_f64(a[i].re, b[i].im, -fma_f64(a[i].im, b[i].re, -c[i].im));
2400 }
2401
2402 cast(out)
2403 }
2404
2405 #[inline]
2406 fn abs2_c64s(self, a: Self::c64s) -> Self::c64s {
2407 let mut out = [c64::ZERO; Self::C64_LANES];
2408 let a: [c64; Self::C64_LANES] = cast(a);
2409
2410 for i in 0..Self::C64_LANES {
2411 let x = a[i].re * a[i].re + a[i].im * a[i].im;
2412 out[i].re = x;
2413 out[i].im = x;
2414 }
2415
2416 cast(out)
2417 }
2418
2419 #[inline]
2420 fn abs_max_c64s(self, a: Self::c64s) -> Self::c64s {
2421 let mut out = [c64::ZERO; Self::C64_LANES];
2422 let a: [c64; Self::C64_LANES] = cast(self.abs_f64s(a));
2423
2424 for i in 0..Self::C64_LANES {
2425 let x = f64::max(a[i].re, a[i].im);
2426 out[i].re = x;
2427 out[i].im = x;
2428 }
2429
2430 cast(out)
2431 }
2432
2433 #[inline]
2434 fn reduce_sum_c64s(self, a: Self::c64s) -> c64 {
2435 let mut a: [c64; Self::C64_LANES] = cast(a);
2436
2437 let mut n = Self::C64_LANES;
2438 while n > 1 {
2439 n /= 2;
2440 for i in 0..n {
2441 a[i].re += a[i + n].re;
2442 a[i].im += a[i + n].im;
2443 }
2444 }
2445
2446 a[0]
2447 }
2448
2449 #[inline]
2450 fn reduce_min_c64s(self, a: Self::c64s) -> c64 {
2451 let mut a: [c64; Self::C64_LANES] = cast(a);
2452
2453 let mut n = Self::C64_LANES;
2454 while n > 1 {
2455 n /= 2;
2456 for i in 0..n {
2457 a[i].re = f64::min(a[i].re, a[i + n].re);
2458 a[i].im = f64::min(a[i].im, a[i + n].im);
2459 }
2460 }
2461
2462 a[0]
2463 }
2464
2465 #[inline]
2466 fn reduce_max_c64s(self, a: Self::c64s) -> c64 {
2467 let mut a: [c64; Self::C64_LANES] = cast(a);
2468
2469 let mut n = Self::C64_LANES;
2470 while n > 1 {
2471 n /= 2;
2472 for i in 0..n {
2473 a[i].re = f64::max(a[i].re, a[i + n].re);
2474 a[i].im = f64::max(a[i].im, a[i + n].im);
2475 }
2476 }
2477
2478 a[0]
2479 }
2480
2481 #[inline]
2482 fn rotate_right_u64s(self, a: Self::u64s, amount: usize) -> Self::u64s {
2483 let mut a: [u64; Self::F64_LANES] = cast(a);
2484 let amount = amount % Self::F64_LANES;
2485 a.rotate_right(amount);
2486 cast(a)
2487 }
2488
2489 #[inline]
2490 fn rotate_right_c64s(self, a: Self::c64s, amount: usize) -> Self::c64s {
2491 let mut a: [c64; Self::C64_LANES] = cast(a);
2492 let amount = amount % Self::C64_LANES;
2493 a.rotate_right(amount);
2494 cast(a)
2495 }
2496
2497 #[inline]
2498 fn mul_add_e_f32s(self, a: Self::f32s, b: Self::f32s, c: Self::f32s) -> Self::f32s {
2499 self.mul_add_f32s(a, b, c)
2500 }
2501
2502 #[inline]
2503 fn mul_add_e_f64s(self, a: Self::f64s, b: Self::f64s, c: Self::f64s) -> Self::f64s {
2504 self.mul_add_f64s(a, b, c)
2505 }
2506
2507 #[inline]
2508 fn negate_mul_add_e_f32s(self, a: Self::f32s, b: Self::f32s, c: Self::f32s) -> Self::f32s {
2509 self.negate_mul_add_f32s(a, b, c)
2510 }
2511
2512 #[inline]
2513 fn negate_mul_add_e_f64s(self, a: Self::f64s, b: Self::f64s, c: Self::f64s) -> Self::f64s {
2514 self.negate_mul_add_f64s(a, b, c)
2515 }
2516
2517 #[inline(always)]
2518 fn sqrt_f32s(self, a: Self::f32s) -> Self::f32s {
2519 let mut out = [0.0_f32; Self::F32_LANES];
2520 let a: [f32; Self::F32_LANES] = cast(a);
2521
2522 for i in 0..Self::F32_LANES {
2523 out[i] = sqrt_f32(a[i]);
2524 }
2525
2526 cast(out)
2527 }
2528 #[inline(always)]
2529 fn sqrt_f64s(self, a: Self::f64s) -> Self::f64s {
2530 let mut out = [0.0_f64; Self::F64_LANES];
2531 let a: [f64; Self::F64_LANES] = cast(a);
2532
2533 for i in 0..Self::F64_LANES {
2534 out[i] = sqrt_f64(a[i]);
2535 }
2536
2537 cast(out)
2538 }
2539 }
2540 };
2541}
2542
2543scalar_simd!(
2544 Scalar128b, 16, m8x16, i8x16, u8x16, m16x8, i16x8, u16x8, m32x4, f32x4, i32x4, u32x4, m64x2,
2545 f64x2, i64x2, u64x2
2546);
2547scalar_simd!(
2548 Scalar256b, 16, m8x32, i8x32, u8x32, m16x16, i16x16, u16x16, m32x8, f32x8, i32x8, u32x8, m64x4,
2549 f64x4, i64x4, u64x4
2550);
2551scalar_simd!(
2552 Scalar512b, 8, m8x64, i8x64, u8x64, m16x32, i16x32, u16x32, m32x16, f32x16, i32x16, u32x16,
2553 m64x8, f64x8, i64x8, u64x8
2554);
2555
2556impl Default for Scalar {
2557 #[inline]
2558 fn default() -> Self {
2559 Self::new()
2560 }
2561}
2562
2563impl Scalar {
2564 #[inline]
2565 pub fn new() -> Self {
2566 Self
2567 }
2568}
2569
2570macro_rules! impl_primitive_binop {
2571 ($func: ident, $op: ident, $ty: ident, $out: ty) => {
2572 paste! {
2573 #[inline(always)]
2574 fn [<$func _ $ty s>](self, a: Self::[<$ty s>], b: Self::[<$ty s>]) -> Self::[<$out s>] {
2575 a.$op(b)
2576 }
2577 }
2578 };
2579 (ref $func: ident, $op: ident, $ty: ident, $out: ty) => {
2580 paste! {
2581 #[inline(always)]
2582 fn [<$func _ $ty s>](self, a: Self::[<$ty s>], b: Self::[<$ty s>]) -> Self::[<$out s>] {
2583 a.$op(&b)
2584 }
2585 }
2586 };
2587}
2588
2589macro_rules! primitive_binop {
2590 (ref $func: ident, op $op: ident, $($ty: ident => $out: ty),*) => {
2591 $(impl_primitive_binop!(ref $func, $op, $ty, $out);)*
2592 };
2593 ($func: ident, $($ty: ident => $out: ty),*) => {
2594 $(impl_primitive_binop!($func, $func, $ty, $out);)*
2595 };
2596 ($func: ident, op $op: ident, $($ty: ident),*) => {
2597 $(impl_primitive_binop!($func, $op, $ty, $ty);)*
2598 };
2599 ($func: ident, $($ty: ident),*) => {
2600 $(impl_primitive_binop!($func, $func, $ty, $ty);)*
2601 };
2602}
2603
2604macro_rules! impl_primitive_unop {
2605 ($func: ident, $op: ident, $ty: ident, $out: ty) => {
2606 paste! {
2607 #[inline(always)]
2608 fn [<$func _ $ty s>](self, a: Self::[<$ty s>]) -> Self::[<$out s>] {
2609 a.$op()
2610 }
2611 }
2612 };
2613}
2614
2615macro_rules! primitive_unop {
2616 ($func: ident, $($ty: ident),*) => {
2617 $(impl_primitive_unop!($func, $func, $ty, $ty);)*
2618 };
2619}
2620
2621macro_rules! splat_primitive {
2622 ($ty: ty) => {
2623 paste! {
2624 #[inline]
2625 fn [<splat_ $ty s>](self, value: $ty) -> Self::[<$ty s>] {
2626 value
2627 }
2628 }
2629 };
2630 ($($ty: ty),*) => {
2631 $(splat_primitive!($ty);)*
2632 }
2633}
2634
2635impl Seal for Scalar {}
2636impl Simd for Scalar {
2637 type c32s = c32;
2638 type c64s = c64;
2639 type f32s = f32;
2640 type f64s = f64;
2641 type i16s = i16;
2642 type i32s = i32;
2643 type i64s = i64;
2644 type i8s = i8;
2645 type m16s = bool;
2646 type m32s = bool;
2647 type m64s = bool;
2648 type m8s = bool;
2649 type u16s = u16;
2650 type u32s = u32;
2651 type u64s = u64;
2652 type u8s = u8;
2653
2654 const IS_SCALAR: bool = true;
2655 const REGISTER_COUNT: usize = 16;
2656
2657 primitive_binop!(add, c32, f32, c64, f64);
2658
2659 primitive_binop!(add, op wrapping_add, u8, i8, u16, i16, u32, i32, u64, i64);
2660
2661 primitive_binop!(sub, c32, f32, c64, f64);
2662
2663 primitive_binop!(sub, op wrapping_sub, u8, i8, u16, i16, u32, i32, u64, i64);
2664
2665 primitive_binop!(mul, f32, f64);
2666
2667 primitive_binop!(mul, op wrapping_mul, u16, i16, u32, i32, u64, i64);
2668
2669 primitive_binop!(div, f32, f64);
2670
2671 primitive_binop!(and, op bitand, m8, u8, m16, u16, m32, u32, m64, u64);
2672
2673 primitive_binop!(or, op bitor, m8, u8, m16, u16, m32, u32, m64, u64);
2674
2675 primitive_binop!(xor, op bitxor, m8, u8, m16, u16, m32, u32, m64, u64);
2676
2677 primitive_binop!(ref equal, op eq, m8 => m8, u8 => m8, m16 => m16, u16 => m16, m32 => m32, u32 => m32, m64 => m64, u64 => m64, c32 => m32, f32 => m32, c64 => m64, f64 => m64);
2678
2679 primitive_binop!(ref greater_than, op gt, u8 => m8, i8 => m8, u16 => m16, i16 => m16, u32 => m32, i32 => m32, u64 => m64, i64 => m64, f32 => m32, f64 => m64);
2680
2681 primitive_binop!(ref greater_than_or_equal, op ge, u8 => m8, i8 => m8, u16 => m16, i16 => m16, u32 => m32, i32 => m32, u64 => m64, i64 => m64, f32 => m32, f64 => m64);
2682
2683 primitive_binop!(ref less_than, op lt, u8 => m8, i8 => m8, u16 => m16, i16 => m16, u32 => m32, i32 => m32, u64 => m64, i64 => m64, f32 => m32, f64 => m64);
2684
2685 primitive_binop!(ref less_than_or_equal, op le, u8 => m8, i8 => m8, u16 => m16, i16 => m16, u32 => m32, i32 => m32, u64 => m64, i64 => m64, f32 => m32, f64 => m64);
2686
2687 primitive_binop!(min, u8, i8, u16, i16, u32, i32, u64, i64, f32, f64);
2688
2689 primitive_binop!(max, u8, i8, u16, i16, u32, i32, u64, i64, f32, f64);
2690
2691 primitive_unop!(neg, c32, c64, f32, f64);
2692
2693 primitive_unop!(not, m8, u8, m16, u16, m32, u32, m64, u64);
2694
2695 splat_primitive!(u8, i8, u16, i16, u32, i32, u64, i64, c32, f32, c64, f64);
2696
2697 #[inline]
2698 fn abs2_c32s(self, a: Self::c32s) -> Self::c32s {
2699 let norm2 = a.re * a.re + a.im * a.im;
2700 c32::new(norm2, norm2)
2701 }
2702
2703 #[inline]
2704 fn abs2_c64s(self, a: Self::c64s) -> Self::c64s {
2705 let norm2 = a.re * a.re + a.im * a.im;
2706 c64::new(norm2, norm2)
2707 }
2708
2709 #[inline(always)]
2710 fn abs_max_c32s(self, a: Self::c32s) -> Self::c32s {
2711 let re = if a.re > a.im { a.re } else { a.im };
2712 let im = re;
2713 Complex { re, im }
2714 }
2715
2716 #[inline(always)]
2717 fn abs_max_c64s(self, a: Self::c64s) -> Self::c64s {
2718 let re = if a.re > a.im { a.re } else { a.im };
2719 let im = re;
2720 Complex { re, im }
2721 }
2722
2723 #[inline]
2724 fn conj_c32s(self, a: Self::c32s) -> Self::c32s {
2725 a.conj()
2726 }
2727
2728 #[inline]
2729 fn conj_c64s(self, a: Self::c64s) -> Self::c64s {
2730 a.conj()
2731 }
2732
2733 #[inline]
2734 fn conj_mul_add_c32s(self, a: Self::c32s, b: Self::c32s, c: Self::c32s) -> Self::c32s {
2735 let re = fma_f32(a.re, b.re, fma_f32(a.im, b.im, c.re));
2736 let im = fma_f32(a.re, b.im, -fma_f32(a.im, b.re, -c.im));
2737 Complex { re, im }
2738 }
2739
2740 #[inline]
2741 fn conj_mul_add_c64s(self, a: Self::c64s, b: Self::c64s, c: Self::c64s) -> Self::c64s {
2742 let re = fma_f64(a.re, b.re, fma_f64(a.im, b.im, c.re));
2743 let im = fma_f64(a.re, b.im, -fma_f64(a.im, b.re, -c.im));
2744 Complex { re, im }
2745 }
2746
2747 #[inline]
2748 fn conj_mul_add_e_c32s(self, a: Self::c32s, b: Self::c32s, c: Self::c32s) -> Self::c32s {
2749 a.conj() * b + c
2750 }
2751
2752 #[inline]
2753 fn conj_mul_add_e_c64s(self, a: Self::c64s, b: Self::c64s, c: Self::c64s) -> Self::c64s {
2754 a.conj() * b + c
2755 }
2756
2757 #[inline]
2758 fn conj_mul_c32s(self, a: Self::c32s, b: Self::c32s) -> Self::c32s {
2759 let re = fma_f32(a.re, b.re, a.im * b.im);
2760 let im = fma_f32(a.re, b.im, -(a.im * b.re));
2761 Complex { re, im }
2762 }
2763
2764 #[inline]
2765 fn conj_mul_c64s(self, a: Self::c64s, b: Self::c64s) -> Self::c64s {
2766 let re = fma_f64(a.re, b.re, a.im * b.im);
2767 let im = fma_f64(a.re, b.im, -(a.im * b.re));
2768 Complex { re, im }
2769 }
2770
2771 #[inline]
2772 fn conj_mul_e_c32s(self, a: Self::c32s, b: Self::c32s) -> Self::c32s {
2773 a.conj() * b
2774 }
2775
2776 #[inline]
2777 fn conj_mul_e_c64s(self, a: Self::c64s, b: Self::c64s) -> Self::c64s {
2778 a.conj() * b
2779 }
2780
2781 #[inline(always)]
2782 fn first_true_m32s(self, mask: Self::m32s) -> usize {
2783 if mask { 0 } else { 1 }
2784 }
2785
2786 #[inline(always)]
2787 fn first_true_m64s(self, mask: Self::m64s) -> usize {
2788 if mask { 0 } else { 1 }
2789 }
2790
2791 #[inline(always)]
2792 unsafe fn mask_load_ptr_c32s(self, mask: MemMask<Self::m32s>, ptr: *const c32) -> Self::c32s {
2793 if mask.mask { *ptr } else { core::mem::zeroed() }
2794 }
2795
2796 #[inline(always)]
2797 unsafe fn mask_load_ptr_c64s(self, mask: MemMask<Self::m64s>, ptr: *const c64) -> Self::c64s {
2798 if mask.mask { *ptr } else { core::mem::zeroed() }
2799 }
2800
2801 #[inline(always)]
2802 unsafe fn mask_load_ptr_u32s(self, mask: MemMask<Self::m32s>, ptr: *const u32) -> Self::u32s {
2803 if mask.mask { *ptr } else { 0 }
2804 }
2805
2806 #[inline(always)]
2807 unsafe fn mask_load_ptr_u64s(self, mask: MemMask<Self::m64s>, ptr: *const u64) -> Self::u64s {
2808 if mask.mask { *ptr } else { 0 }
2809 }
2810
2811 #[inline(always)]
2812 unsafe fn mask_store_ptr_c32s(
2813 self,
2814 mask: MemMask<Self::m32s>,
2815 ptr: *mut c32,
2816 values: Self::c32s,
2817 ) {
2818 if mask.mask {
2819 *ptr = values
2820 }
2821 }
2822
2823 #[inline(always)]
2824 unsafe fn mask_store_ptr_c64s(
2825 self,
2826 mask: MemMask<Self::m64s>,
2827 ptr: *mut c64,
2828 values: Self::c64s,
2829 ) {
2830 if mask.mask {
2831 *ptr = values
2832 }
2833 }
2834
2835 #[inline(always)]
2836 unsafe fn mask_store_ptr_u8s(self, mask: MemMask<Self::m8s>, ptr: *mut u8, values: Self::u8s) {
2837 if mask.mask {
2838 *ptr = values
2839 }
2840 }
2841
2842 #[inline(always)]
2843 unsafe fn mask_store_ptr_u16s(
2844 self,
2845 mask: MemMask<Self::m16s>,
2846 ptr: *mut u16,
2847 values: Self::u16s,
2848 ) {
2849 if mask.mask {
2850 *ptr = values
2851 }
2852 }
2853
2854 #[inline(always)]
2855 unsafe fn mask_store_ptr_u32s(
2856 self,
2857 mask: MemMask<Self::m32s>,
2858 ptr: *mut u32,
2859 values: Self::u32s,
2860 ) {
2861 if mask.mask {
2862 *ptr = values
2863 }
2864 }
2865
2866 #[inline(always)]
2867 unsafe fn mask_store_ptr_u64s(
2868 self,
2869 mask: MemMask<Self::m64s>,
2870 ptr: *mut u64,
2871 values: Self::u64s,
2872 ) {
2873 if mask.mask {
2874 *ptr = values
2875 }
2876 }
2877
2878 #[inline]
2879 fn mul_add_c32s(self, a: Self::c32s, b: Self::c32s, c: Self::c32s) -> Self::c32s {
2880 let re = fma_f32(a.re, b.re, -fma_f32(a.im, b.im, -c.re));
2881 let im = fma_f32(a.re, b.im, fma_f32(a.im, b.re, c.im));
2882 Complex { re, im }
2883 }
2884
2885 #[inline]
2886 fn mul_add_c64s(self, a: Self::c64s, b: Self::c64s, c: Self::c64s) -> Self::c64s {
2887 let re = fma_f64(a.re, b.re, -fma_f64(a.im, b.im, -c.re));
2888 let im = fma_f64(a.re, b.im, fma_f64(a.im, b.re, c.im));
2889 Complex { re, im }
2890 }
2891
2892 #[inline]
2893 fn mul_add_e_c32s(self, a: Self::c32s, b: Self::c32s, c: Self::c32s) -> Self::c32s {
2894 a * b + c
2895 }
2896
2897 #[inline]
2898 fn mul_add_e_c64s(self, a: Self::c64s, b: Self::c64s, c: Self::c64s) -> Self::c64s {
2899 a * b + c
2900 }
2901
2902 #[inline(always)]
2903 fn mul_add_e_f32s(self, a: Self::f32s, b: Self::f32s, c: Self::f32s) -> Self::f32s {
2904 a * b + c
2905 }
2906
2907 #[inline(always)]
2908 fn mul_add_e_f64s(self, a: Self::f64s, b: Self::f64s, c: Self::f64s) -> Self::f64s {
2909 a * b + c
2910 }
2911
2912 #[inline]
2913 fn mul_add_f32s(self, a: Self::f32s, b: Self::f32s, c: Self::f32s) -> Self::f32s {
2914 fma_f32(a, b, c)
2915 }
2916
2917 #[inline]
2918 fn mul_add_f64s(self, a: Self::f64s, b: Self::f64s, c: Self::f64s) -> Self::f64s {
2919 fma_f64(a, b, c)
2920 }
2921
2922 #[inline]
2923 fn negate_mul_add_e_f32s(self, a: Self::f32s, b: Self::f32s, c: Self::f32s) -> Self::f32s {
2924 c - a * b
2925 }
2926
2927 #[inline]
2928 fn negate_mul_add_e_f64s(self, a: Self::f64s, b: Self::f64s, c: Self::f64s) -> Self::f64s {
2929 c - a * b
2930 }
2931
2932 #[inline]
2933 fn negate_mul_add_f32s(self, a: Self::f32s, b: Self::f32s, c: Self::f32s) -> Self::f32s {
2934 fma_f32(-a, b, c)
2935 }
2936
2937 #[inline]
2938 fn negate_mul_add_f64s(self, a: Self::f64s, b: Self::f64s, c: Self::f64s) -> Self::f64s {
2939 fma_f64(-a, b, c)
2940 }
2941
2942 #[inline]
2943 fn mul_c32s(self, a: Self::c32s, b: Self::c32s) -> Self::c32s {
2944 let re = fma_f32(a.re, b.re, -(a.im * b.im));
2945 let im = fma_f32(a.re, b.im, a.im * b.re);
2946 Complex { re, im }
2947 }
2948
2949 #[inline]
2950 fn mul_c64s(self, a: Self::c64s, b: Self::c64s) -> Self::c64s {
2951 let re = fma_f64(a.re, b.re, -(a.im * b.im));
2952 let im = fma_f64(a.re, b.im, a.im * b.re);
2953 Complex { re, im }
2954 }
2955
2956 #[inline]
2957 fn mul_e_c32s(self, a: Self::c32s, b: Self::c32s) -> Self::c32s {
2958 a * b
2959 }
2960
2961 #[inline]
2962 fn mul_e_c64s(self, a: Self::c64s, b: Self::c64s) -> Self::c64s {
2963 a * b
2964 }
2965
2966 #[inline]
2967 fn partial_load_c64s(self, slice: &[c64]) -> Self::c64s {
2968 if let Some((head, _)) = slice.split_first() {
2969 *head
2970 } else {
2971 c64 { re: 0.0, im: 0.0 }
2972 }
2973 }
2974
2975 #[inline]
2976 fn partial_load_u32s(self, slice: &[u32]) -> Self::u32s {
2977 if let Some((head, _)) = slice.split_first() {
2978 *head
2979 } else {
2980 0
2981 }
2982 }
2983
2984 #[inline]
2985 fn partial_load_u64s(self, slice: &[u64]) -> Self::u64s {
2986 if let Some((head, _)) = slice.split_first() {
2987 *head
2988 } else {
2989 0
2990 }
2991 }
2992
2993 #[inline]
2994 fn partial_store_c64s(self, slice: &mut [c64], values: Self::c64s) {
2995 if let Some((head, _)) = slice.split_first_mut() {
2996 *head = values;
2997 }
2998 }
2999
3000 #[inline]
3001 fn partial_store_u32s(self, slice: &mut [u32], values: Self::u32s) {
3002 if let Some((head, _)) = slice.split_first_mut() {
3003 *head = values;
3004 }
3005 }
3006
3007 #[inline]
3008 fn partial_store_u64s(self, slice: &mut [u64], values: Self::u64s) {
3009 if let Some((head, _)) = slice.split_first_mut() {
3010 *head = values;
3011 }
3012 }
3013
3014 #[inline(always)]
3015 fn reduce_max_c32s(self, a: Self::c32s) -> c32 {
3016 a
3017 }
3018
3019 #[inline(always)]
3020 fn reduce_max_c64s(self, a: Self::c64s) -> c64 {
3021 a
3022 }
3023
3024 #[inline]
3025 fn reduce_max_f32s(self, a: Self::f32s) -> f32 {
3026 a
3027 }
3028
3029 #[inline]
3030 fn reduce_max_f64s(self, a: Self::f64s) -> f64 {
3031 a
3032 }
3033
3034 #[inline(always)]
3035 fn reduce_min_c32s(self, a: Self::c32s) -> c32 {
3036 a
3037 }
3038
3039 #[inline(always)]
3040 fn reduce_min_c64s(self, a: Self::c64s) -> c64 {
3041 a
3042 }
3043
3044 #[inline]
3045 fn reduce_min_f32s(self, a: Self::f32s) -> f32 {
3046 a
3047 }
3048
3049 #[inline]
3050 fn reduce_min_f64s(self, a: Self::f64s) -> f64 {
3051 a
3052 }
3053
3054 #[inline]
3055 fn reduce_product_f32s(self, a: Self::f32s) -> f32 {
3056 a
3057 }
3058
3059 #[inline]
3060 fn reduce_product_f64s(self, a: Self::f64s) -> f64 {
3061 a
3062 }
3063
3064 #[inline]
3065 fn reduce_sum_c32s(self, a: Self::c32s) -> c32 {
3066 a
3067 }
3068
3069 #[inline]
3070 fn reduce_sum_c64s(self, a: Self::c64s) -> c64 {
3071 a
3072 }
3073
3074 #[inline]
3075 fn reduce_sum_f32s(self, a: Self::f32s) -> f32 {
3076 a
3077 }
3078
3079 #[inline]
3080 fn reduce_sum_f64s(self, a: Self::f64s) -> f64 {
3081 a
3082 }
3083
3084 #[inline(always)]
3085 fn rotate_right_c32s(self, a: Self::c32s, _amount: usize) -> Self::c32s {
3086 a
3087 }
3088
3089 #[inline(always)]
3090 fn rotate_right_c64s(self, a: Self::c64s, _amount: usize) -> Self::c64s {
3091 a
3092 }
3093
3094 #[inline(always)]
3095 fn rotate_right_u32s(self, a: Self::u32s, _amount: usize) -> Self::u32s {
3096 a
3097 }
3098
3099 #[inline(always)]
3100 fn rotate_right_u64s(self, a: Self::u64s, _amount: usize) -> Self::u64s {
3101 a
3102 }
3103
3104 #[inline]
3105 fn select_u32s(
3106 self,
3107 mask: Self::m32s,
3108 if_true: Self::u32s,
3109 if_false: Self::u32s,
3110 ) -> Self::u32s {
3111 if mask { if_true } else { if_false }
3112 }
3113
3114 #[inline]
3115 fn select_u64s(
3116 self,
3117 mask: Self::m64s,
3118 if_true: Self::u64s,
3119 if_false: Self::u64s,
3120 ) -> Self::u64s {
3121 if mask { if_true } else { if_false }
3122 }
3123
3124 #[inline]
3125 fn swap_re_im_c32s(self, a: Self::c32s) -> Self::c32s {
3126 c32 { re: a.im, im: a.re }
3127 }
3128
3129 fn swap_re_im_c64s(self, a: Self::c64s) -> Self::c64s {
3130 c64 { re: a.im, im: a.re }
3131 }
3132
3133 #[inline]
3134 fn vectorize<Op: WithSimd>(self, op: Op) -> Op::Output {
3135 op.with_simd(self)
3136 }
3137
3138 #[inline]
3139 fn widening_mul_u32s(self, a: Self::u32s, b: Self::u32s) -> (Self::u32s, Self::u32s) {
3140 let c = a as u64 * b as u64;
3141 let lo = c as u32;
3142 let hi = (c >> 32) as u32;
3143 (lo, hi)
3144 }
3145
3146 #[inline]
3147 fn wrapping_dyn_shl_u32s(self, a: Self::u32s, amount: Self::u32s) -> Self::u32s {
3148 a.wrapping_shl(amount)
3149 }
3150
3151 #[inline]
3152 fn wrapping_dyn_shr_u32s(self, a: Self::u32s, amount: Self::u32s) -> Self::u32s {
3153 a.wrapping_shr(amount)
3154 }
3155
3156 unsafe fn mask_load_ptr_u8s(self, mask: MemMask<Self::m8s>, ptr: *const u8) -> Self::u8s {
3157 if mask.mask { *ptr } else { 0 }
3158 }
3159
3160 unsafe fn mask_load_ptr_u16s(self, mask: MemMask<Self::m16s>, ptr: *const u16) -> Self::u16s {
3161 if mask.mask { *ptr } else { 0 }
3162 }
3163
3164 #[inline(always)]
3165 fn sqrt_f32s(self, a: Self::f32s) -> Self::f32s {
3166 sqrt_f32(a)
3167 }
3168
3169 #[inline(always)]
3170 fn sqrt_f64s(self, a: Self::f64s) -> Self::f64s {
3171 sqrt_f64(a)
3172 }
3173}
3174
3175#[inline(always)]
3176unsafe fn split_slice<T, U>(slice: &[T]) -> (&[U], &[T]) {
3177 assert_eq!(core::mem::size_of::<U>() % core::mem::size_of::<T>(), 0);
3178 assert_eq!(core::mem::align_of::<U>(), core::mem::align_of::<T>());
3179
3180 let chunk_size = core::mem::size_of::<U>() / core::mem::size_of::<T>();
3181
3182 let len = slice.len();
3183 let data = slice.as_ptr();
3184
3185 let div = len / chunk_size;
3186 let rem = len % chunk_size;
3187 (
3188 from_raw_parts(data as *const U, div),
3189 from_raw_parts(data.add(len - rem), rem),
3190 )
3191}
3192
3193#[inline(always)]
3194unsafe fn split_mut_slice<T, U>(slice: &mut [T]) -> (&mut [U], &mut [T]) {
3195 assert_eq!(core::mem::size_of::<U>() % core::mem::size_of::<T>(), 0);
3196 assert_eq!(core::mem::align_of::<U>(), core::mem::align_of::<T>());
3197
3198 let chunk_size = core::mem::size_of::<U>() / core::mem::size_of::<T>();
3199
3200 let len = slice.len();
3201 let data = slice.as_mut_ptr();
3202
3203 let div = len / chunk_size;
3204 let rem = len % chunk_size;
3205 (
3206 from_raw_parts_mut(data as *mut U, div),
3207 from_raw_parts_mut(data.add(len - rem), rem),
3208 )
3209}
3210
3211#[inline(always)]
3212unsafe fn rsplit_slice<T, U>(slice: &[T]) -> (&[T], &[U]) {
3213 assert_eq!(core::mem::size_of::<U>() % core::mem::size_of::<T>(), 0);
3214 assert_eq!(core::mem::align_of::<U>(), core::mem::align_of::<T>());
3215
3216 let chunk_size = core::mem::size_of::<U>() / core::mem::size_of::<T>();
3217
3218 let len = slice.len();
3219 let data = slice.as_ptr();
3220
3221 let div = len / chunk_size;
3222 let rem = len % chunk_size;
3223 (
3224 from_raw_parts(data, rem),
3225 from_raw_parts(data.add(rem) as *const U, div),
3226 )
3227}
3228
3229#[inline(always)]
3230unsafe fn rsplit_mut_slice<T, U>(slice: &mut [T]) -> (&mut [T], &mut [U]) {
3231 assert_eq!(core::mem::size_of::<U>() % core::mem::size_of::<T>(), 0);
3232 assert_eq!(core::mem::align_of::<U>(), core::mem::align_of::<T>());
3233
3234 let chunk_size = core::mem::size_of::<U>() / core::mem::size_of::<T>();
3235
3236 let len = slice.len();
3237 let data = slice.as_mut_ptr();
3238
3239 let div = len / chunk_size;
3240 let rem = len % chunk_size;
3241 (
3242 from_raw_parts_mut(data, rem),
3243 from_raw_parts_mut(data.add(rem) as *mut U, div),
3244 )
3245}
3246
3247match_cfg!(
3248 item,
3249 match cfg!() {
3250 const { any(target_arch = "x86", target_arch = "x86_64") } => {
3251 pub use x86::Arch;
3252 },
3253 const { target_arch = "aarch64" } => {
3254 pub use aarch64::Arch;
3255 },
3256 const { target_arch = "wasm32" } => {
3257 pub use wasm::Arch;
3258 },
3259 _ => {
3260 #[derive(Debug, Clone, Copy)]
3261 #[non_exhaustive]
3262 pub enum Arch {
3263 Scalar,
3264 }
3265
3266 impl Arch {
3267 #[inline(always)]
3268 pub fn new() -> Self {
3269 Self::Scalar
3270 }
3271
3272 #[inline(always)]
3273 pub fn dispatch<Op: WithSimd>(self, op: Op) -> Op::Output {
3274 op.with_simd(Scalar)
3275 }
3276 }
3277 impl Default for Arch {
3278 #[inline]
3279 fn default() -> Self {
3280 Self::new()
3281 }
3282 }
3283 },
3284 }
3285);
3286
3287#[doc(hidden)]
3288pub struct CheckSameSize<T, U>(PhantomData<(T, U)>);
3289impl<T, U> CheckSameSize<T, U> {
3290 pub const VALID: () = {
3291 assert!(core::mem::size_of::<T>() == core::mem::size_of::<U>());
3292 };
3293}
3294
3295#[doc(hidden)]
3296pub struct CheckSizeLessThanOrEqual<T, U>(PhantomData<(T, U)>);
3297impl<T, U> CheckSizeLessThanOrEqual<T, U> {
3298 pub const VALID: () = {
3299 assert!(core::mem::size_of::<T>() <= core::mem::size_of::<U>());
3300 };
3301}
3302
3303#[macro_export]
3304macro_rules! static_assert_same_size {
3305 ($t: ty, $u: ty) => {
3306 let _ = $crate::CheckSameSize::<$t, $u>::VALID;
3307 };
3308}
3309#[macro_export]
3310macro_rules! static_assert_size_less_than_or_equal {
3311 ($t: ty, $u: ty) => {
3312 let _ = $crate::CheckSizeLessThanOrEqual::<$t, $u>::VALID;
3313 };
3314}
3315
3316#[inline(always)]
3320pub const fn cast<T: NoUninit, U: AnyBitPattern>(value: T) -> U {
3321 static_assert_same_size!(T, U);
3322 let ptr = &raw const value as *const U;
3323 unsafe { ptr.read_unaligned() }
3324}
3325
3326#[inline(always)]
3330pub const fn cast_lossy<T: NoUninit, U: AnyBitPattern>(value: T) -> U {
3331 static_assert_size_less_than_or_equal!(U, T);
3332 let value = core::mem::ManuallyDrop::new(value);
3333 let ptr = &raw const value as *const U;
3334 unsafe { ptr.read_unaligned() }
3335}
3336
3337#[inline(always)]
3341pub fn as_arrays<const N: usize, T>(slice: &[T]) -> (&[[T; N]], &[T]) {
3342 let n = slice.len();
3343 let mid_div_n = n / N;
3344 let mid = mid_div_n * N;
3345 let ptr = slice.as_ptr();
3346 unsafe {
3347 (
3348 from_raw_parts(ptr as *const [T; N], mid_div_n),
3349 from_raw_parts(ptr.add(mid), n - mid),
3350 )
3351 }
3352}
3353
3354#[inline(always)]
3358pub fn as_arrays_mut<const N: usize, T>(slice: &mut [T]) -> (&mut [[T; N]], &mut [T]) {
3359 let n = slice.len();
3360 let mid_div_n = n / N;
3361 let mid = mid_div_n * N;
3362 let ptr = slice.as_mut_ptr();
3363 unsafe {
3364 (
3365 from_raw_parts_mut(ptr as *mut [T; N], mid_div_n),
3366 from_raw_parts_mut(ptr.add(mid), n - mid),
3367 )
3368 }
3369}
3370
3371pub mod core_arch;
3373
3374#[allow(unused_macros)]
3375macro_rules! inherit {
3376 ({$(
3377 $(#[$attr: meta])*
3378 $(unsafe $($placeholder: lifetime)?)?
3379 fn $func: ident(self
3380 $(,$arg: ident: $ty: ty)* $(,)?
3381 ) $(-> $ret: ty)?;
3382 )*}) => {
3383 $(
3384 $(#[$attr])*
3385 #[inline(always)]
3386 $(unsafe $($placeholder)?)? fn $func (self, $($arg: $ty,)*) $(-> $ret)? {
3387 (*self).$func ($($arg,)*)
3388 }
3389 )*
3390 };
3391}
3392
3393#[allow(unused_macros)]
3394macro_rules! inherit_x2 {
3395 ($base: expr, {$(
3396 $(#[$attr: meta])*
3397 $(unsafe $($placeholder: lifetime)?)?
3398 fn $func: ident ($self: ident
3399 $(,$arg: ident: $ty: ty)* $(,)?
3400 ) $(-> $ret: ty)?;
3401 )*}) => {
3402 $(
3403 $(#[$attr])*
3404 #[inline(always)]
3405 $(unsafe $($placeholder)?)? fn $func ($self, $($arg: $ty,)*) $(-> $ret)? {
3406 $(let $arg: [_; 2] = cast!($arg);)*
3407 cast!([($base).$func ($($arg[0],)*), ($base).$func ($($arg[1],)*)])
3408 }
3409 )*
3410 };
3411
3412 ($base: expr, splat, {$(
3413 $(#[$attr: meta])*
3414 $(unsafe $($placeholder: lifetime)?)?
3415 fn $func: ident ($self: ident
3416 $(,$arg: ident: $ty: ty)* $(,)?
3417 ) $(-> $ret: ty)?;
3418 )*}) => {
3419 $(
3420 $(#[$attr])*
3421 #[inline(always)]
3422 $(unsafe $($placeholder)?)? fn $func ($self, $($arg: $ty,)*) $(-> $ret)? {
3423 cast!([($base).$func ($($arg,)*), ($base).$func ($($arg,)*)])
3424 }
3425 )*
3426 };
3427
3428 ($base: expr, wide, {$(
3429 $(#[$attr: meta])*
3430 $(unsafe $($placeholder: lifetime)?)?
3431 fn $func: ident ($self: ident
3432 $(,$arg: ident: $ty: ty)* $(,)?
3433 ) $(-> $ret: ty)?;
3434 )*}) => {
3435 $(
3436 $(#[$attr])*
3437 #[inline(always)]
3438 $(unsafe $($placeholder)?)? fn $func ($self, $($arg: $ty,)*) $(-> $ret)? {
3439 $(let $arg: [_; 2] = cast!($arg);)*
3440 let (r0, r1) = ($base).$func ($($arg[0],)*); let (s0, s1) = ($base).$func ($($arg[1],)*);
3441 (cast!([r0, s0]), cast!([r1, s1]))
3442 }
3443 )*
3444 };
3445}
3446
3447#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
3448#[cfg_attr(docsrs, doc(cfg(any(target_arch = "x86", target_arch = "x86_64"))))]
3449pub mod x86;
3451
3452#[cfg(target_arch = "wasm32")]
3453#[cfg_attr(docsrs, doc(cfg(target_arch = "wasm32")))]
3454pub mod wasm;
3456
3457#[cfg(target_arch = "aarch64")]
3458#[cfg_attr(docsrs, doc(cfg(target_arch = "aarch64")))]
3459pub mod aarch64;
3461
3462#[derive(Copy, Clone, PartialEq, Eq, Default)]
3465#[repr(transparent)]
3466pub struct m8(u8);
3467#[derive(Copy, Clone, PartialEq, Eq, Default)]
3470#[repr(transparent)]
3471pub struct m16(u16);
3472#[derive(Copy, Clone, PartialEq, Eq, Default)]
3475#[repr(transparent)]
3476pub struct m32(u32);
3477#[derive(Copy, Clone, PartialEq, Eq, Default)]
3480#[repr(transparent)]
3481pub struct m64(u64);
3482
3483#[derive(Copy, Clone, PartialEq, Eq)]
3485#[repr(transparent)]
3486pub struct b8(pub u8);
3487#[derive(Copy, Clone, PartialEq, Eq)]
3489#[repr(transparent)]
3490pub struct b16(pub u16);
3491#[derive(Copy, Clone, PartialEq, Eq)]
3493#[repr(transparent)]
3494pub struct b32(pub u32);
3495#[derive(Copy, Clone, PartialEq, Eq)]
3497#[repr(transparent)]
3498pub struct b64(pub u64);
3499
3500impl core::ops::Not for b8 {
3501 type Output = b8;
3502
3503 #[inline(always)]
3504 fn not(self) -> Self::Output {
3505 b8(!self.0)
3506 }
3507}
3508impl core::ops::BitAnd for b8 {
3509 type Output = b8;
3510
3511 #[inline(always)]
3512 fn bitand(self, rhs: Self) -> Self::Output {
3513 b8(self.0 & rhs.0)
3514 }
3515}
3516impl core::ops::BitOr for b8 {
3517 type Output = b8;
3518
3519 #[inline(always)]
3520 fn bitor(self, rhs: Self) -> Self::Output {
3521 b8(self.0 | rhs.0)
3522 }
3523}
3524impl core::ops::BitXor for b8 {
3525 type Output = b8;
3526
3527 #[inline(always)]
3528 fn bitxor(self, rhs: Self) -> Self::Output {
3529 b8(self.0 ^ rhs.0)
3530 }
3531}
3532
3533impl core::ops::Not for m8 {
3534 type Output = m8;
3535
3536 #[inline(always)]
3537 fn not(self) -> Self::Output {
3538 m8(!self.0)
3539 }
3540}
3541impl core::ops::BitAnd for m8 {
3542 type Output = m8;
3543
3544 #[inline(always)]
3545 fn bitand(self, rhs: Self) -> Self::Output {
3546 m8(self.0 & rhs.0)
3547 }
3548}
3549impl core::ops::BitOr for m8 {
3550 type Output = m8;
3551
3552 #[inline(always)]
3553 fn bitor(self, rhs: Self) -> Self::Output {
3554 m8(self.0 | rhs.0)
3555 }
3556}
3557impl core::ops::BitXor for m8 {
3558 type Output = m8;
3559
3560 #[inline(always)]
3561 fn bitxor(self, rhs: Self) -> Self::Output {
3562 m8(self.0 ^ rhs.0)
3563 }
3564}
3565
3566impl core::ops::Not for m16 {
3567 type Output = m16;
3568
3569 #[inline(always)]
3570 fn not(self) -> Self::Output {
3571 m16(!self.0)
3572 }
3573}
3574impl core::ops::BitAnd for m16 {
3575 type Output = m16;
3576
3577 #[inline(always)]
3578 fn bitand(self, rhs: Self) -> Self::Output {
3579 m16(self.0 & rhs.0)
3580 }
3581}
3582impl core::ops::BitOr for m16 {
3583 type Output = m16;
3584
3585 #[inline(always)]
3586 fn bitor(self, rhs: Self) -> Self::Output {
3587 m16(self.0 | rhs.0)
3588 }
3589}
3590impl core::ops::BitXor for m16 {
3591 type Output = m16;
3592
3593 #[inline(always)]
3594 fn bitxor(self, rhs: Self) -> Self::Output {
3595 m16(self.0 ^ rhs.0)
3596 }
3597}
3598
3599impl core::ops::Not for m32 {
3600 type Output = m32;
3601
3602 #[inline(always)]
3603 fn not(self) -> Self::Output {
3604 m32(!self.0)
3605 }
3606}
3607impl core::ops::BitAnd for m32 {
3608 type Output = m32;
3609
3610 #[inline(always)]
3611 fn bitand(self, rhs: Self) -> Self::Output {
3612 m32(self.0 & rhs.0)
3613 }
3614}
3615impl core::ops::BitOr for m32 {
3616 type Output = m32;
3617
3618 #[inline(always)]
3619 fn bitor(self, rhs: Self) -> Self::Output {
3620 m32(self.0 | rhs.0)
3621 }
3622}
3623impl core::ops::BitXor for m32 {
3624 type Output = m32;
3625
3626 #[inline(always)]
3627 fn bitxor(self, rhs: Self) -> Self::Output {
3628 m32(self.0 ^ rhs.0)
3629 }
3630}
3631
3632impl core::ops::Not for m64 {
3633 type Output = m64;
3634
3635 #[inline(always)]
3636 fn not(self) -> Self::Output {
3637 m64(!self.0)
3638 }
3639}
3640impl core::ops::BitAnd for m64 {
3641 type Output = m64;
3642
3643 #[inline(always)]
3644 fn bitand(self, rhs: Self) -> Self::Output {
3645 m64(self.0 & rhs.0)
3646 }
3647}
3648impl core::ops::BitOr for m64 {
3649 type Output = m64;
3650
3651 #[inline(always)]
3652 fn bitor(self, rhs: Self) -> Self::Output {
3653 m64(self.0 | rhs.0)
3654 }
3655}
3656impl core::ops::BitXor for m64 {
3657 type Output = m64;
3658
3659 #[inline(always)]
3660 fn bitxor(self, rhs: Self) -> Self::Output {
3661 m64(self.0 ^ rhs.0)
3662 }
3663}
3664
3665impl core::ops::Not for b16 {
3666 type Output = b16;
3667
3668 #[inline(always)]
3669 fn not(self) -> Self::Output {
3670 b16(!self.0)
3671 }
3672}
3673impl core::ops::BitAnd for b16 {
3674 type Output = b16;
3675
3676 #[inline(always)]
3677 fn bitand(self, rhs: Self) -> Self::Output {
3678 b16(self.0 & rhs.0)
3679 }
3680}
3681impl core::ops::BitOr for b16 {
3682 type Output = b16;
3683
3684 #[inline(always)]
3685 fn bitor(self, rhs: Self) -> Self::Output {
3686 b16(self.0 | rhs.0)
3687 }
3688}
3689impl core::ops::BitXor for b16 {
3690 type Output = b16;
3691
3692 #[inline(always)]
3693 fn bitxor(self, rhs: Self) -> Self::Output {
3694 b16(self.0 ^ rhs.0)
3695 }
3696}
3697
3698impl core::ops::Not for b32 {
3699 type Output = b32;
3700
3701 #[inline(always)]
3702 fn not(self) -> Self::Output {
3703 b32(!self.0)
3704 }
3705}
3706impl core::ops::BitAnd for b32 {
3707 type Output = b32;
3708
3709 #[inline(always)]
3710 fn bitand(self, rhs: Self) -> Self::Output {
3711 b32(self.0 & rhs.0)
3712 }
3713}
3714impl core::ops::BitOr for b32 {
3715 type Output = b32;
3716
3717 #[inline(always)]
3718 fn bitor(self, rhs: Self) -> Self::Output {
3719 b32(self.0 | rhs.0)
3720 }
3721}
3722impl core::ops::BitXor for b32 {
3723 type Output = b32;
3724
3725 #[inline(always)]
3726 fn bitxor(self, rhs: Self) -> Self::Output {
3727 b32(self.0 ^ rhs.0)
3728 }
3729}
3730
3731impl core::ops::Not for b64 {
3732 type Output = b64;
3733
3734 #[inline(always)]
3735 fn not(self) -> Self::Output {
3736 b64(!self.0)
3737 }
3738}
3739impl core::ops::BitAnd for b64 {
3740 type Output = b64;
3741
3742 #[inline(always)]
3743 fn bitand(self, rhs: Self) -> Self::Output {
3744 b64(self.0 & rhs.0)
3745 }
3746}
3747impl core::ops::BitOr for b64 {
3748 type Output = b64;
3749
3750 #[inline(always)]
3751 fn bitor(self, rhs: Self) -> Self::Output {
3752 b64(self.0 | rhs.0)
3753 }
3754}
3755impl core::ops::BitXor for b64 {
3756 type Output = b64;
3757
3758 #[inline(always)]
3759 fn bitxor(self, rhs: Self) -> Self::Output {
3760 b64(self.0 ^ rhs.0)
3761 }
3762}
3763
3764impl Debug for b8 {
3765 fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
3766 #[allow(dead_code)]
3767 #[derive(Copy, Clone, Debug)]
3768 struct b8(bool, bool, bool, bool, bool, bool, bool, bool);
3769 b8(
3770 ((self.0 >> 0) & 1) == 1,
3771 ((self.0 >> 1) & 1) == 1,
3772 ((self.0 >> 2) & 1) == 1,
3773 ((self.0 >> 3) & 1) == 1,
3774 ((self.0 >> 4) & 1) == 1,
3775 ((self.0 >> 5) & 1) == 1,
3776 ((self.0 >> 6) & 1) == 1,
3777 ((self.0 >> 7) & 1) == 1,
3778 )
3779 .fmt(f)
3780 }
3781}
3782impl Debug for b16 {
3783 fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
3784 #[allow(dead_code)]
3785 #[derive(Copy, Clone, Debug)]
3786 struct b16(
3787 bool,
3788 bool,
3789 bool,
3790 bool,
3791 bool,
3792 bool,
3793 bool,
3794 bool,
3795 bool,
3796 bool,
3797 bool,
3798 bool,
3799 bool,
3800 bool,
3801 bool,
3802 bool,
3803 );
3804 b16(
3805 ((self.0 >> 00) & 1) == 1,
3806 ((self.0 >> 01) & 1) == 1,
3807 ((self.0 >> 02) & 1) == 1,
3808 ((self.0 >> 03) & 1) == 1,
3809 ((self.0 >> 04) & 1) == 1,
3810 ((self.0 >> 05) & 1) == 1,
3811 ((self.0 >> 06) & 1) == 1,
3812 ((self.0 >> 07) & 1) == 1,
3813 ((self.0 >> 08) & 1) == 1,
3814 ((self.0 >> 09) & 1) == 1,
3815 ((self.0 >> 10) & 1) == 1,
3816 ((self.0 >> 11) & 1) == 1,
3817 ((self.0 >> 12) & 1) == 1,
3818 ((self.0 >> 13) & 1) == 1,
3819 ((self.0 >> 14) & 1) == 1,
3820 ((self.0 >> 15) & 1) == 1,
3821 )
3822 .fmt(f)
3823 }
3824}
3825impl Debug for b32 {
3826 fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
3827 #[allow(dead_code)]
3828 #[derive(Copy, Clone, Debug)]
3829 struct b32(
3830 bool,
3831 bool,
3832 bool,
3833 bool,
3834 bool,
3835 bool,
3836 bool,
3837 bool,
3838 bool,
3839 bool,
3840 bool,
3841 bool,
3842 bool,
3843 bool,
3844 bool,
3845 bool,
3846 bool,
3847 bool,
3848 bool,
3849 bool,
3850 bool,
3851 bool,
3852 bool,
3853 bool,
3854 bool,
3855 bool,
3856 bool,
3857 bool,
3858 bool,
3859 bool,
3860 bool,
3861 bool,
3862 );
3863 b32(
3864 ((self.0 >> 00) & 1) == 1,
3865 ((self.0 >> 01) & 1) == 1,
3866 ((self.0 >> 02) & 1) == 1,
3867 ((self.0 >> 03) & 1) == 1,
3868 ((self.0 >> 04) & 1) == 1,
3869 ((self.0 >> 05) & 1) == 1,
3870 ((self.0 >> 06) & 1) == 1,
3871 ((self.0 >> 07) & 1) == 1,
3872 ((self.0 >> 08) & 1) == 1,
3873 ((self.0 >> 09) & 1) == 1,
3874 ((self.0 >> 10) & 1) == 1,
3875 ((self.0 >> 11) & 1) == 1,
3876 ((self.0 >> 12) & 1) == 1,
3877 ((self.0 >> 13) & 1) == 1,
3878 ((self.0 >> 14) & 1) == 1,
3879 ((self.0 >> 15) & 1) == 1,
3880 ((self.0 >> 16) & 1) == 1,
3881 ((self.0 >> 17) & 1) == 1,
3882 ((self.0 >> 18) & 1) == 1,
3883 ((self.0 >> 19) & 1) == 1,
3884 ((self.0 >> 20) & 1) == 1,
3885 ((self.0 >> 21) & 1) == 1,
3886 ((self.0 >> 22) & 1) == 1,
3887 ((self.0 >> 23) & 1) == 1,
3888 ((self.0 >> 24) & 1) == 1,
3889 ((self.0 >> 25) & 1) == 1,
3890 ((self.0 >> 26) & 1) == 1,
3891 ((self.0 >> 27) & 1) == 1,
3892 ((self.0 >> 28) & 1) == 1,
3893 ((self.0 >> 29) & 1) == 1,
3894 ((self.0 >> 30) & 1) == 1,
3895 ((self.0 >> 31) & 1) == 1,
3896 )
3897 .fmt(f)
3898 }
3899}
3900impl Debug for b64 {
3901 fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
3902 #[allow(dead_code)]
3903 #[derive(Copy, Clone, Debug)]
3904 struct b64(
3905 bool,
3906 bool,
3907 bool,
3908 bool,
3909 bool,
3910 bool,
3911 bool,
3912 bool,
3913 bool,
3914 bool,
3915 bool,
3916 bool,
3917 bool,
3918 bool,
3919 bool,
3920 bool,
3921 bool,
3922 bool,
3923 bool,
3924 bool,
3925 bool,
3926 bool,
3927 bool,
3928 bool,
3929 bool,
3930 bool,
3931 bool,
3932 bool,
3933 bool,
3934 bool,
3935 bool,
3936 bool,
3937 bool,
3938 bool,
3939 bool,
3940 bool,
3941 bool,
3942 bool,
3943 bool,
3944 bool,
3945 bool,
3946 bool,
3947 bool,
3948 bool,
3949 bool,
3950 bool,
3951 bool,
3952 bool,
3953 bool,
3954 bool,
3955 bool,
3956 bool,
3957 bool,
3958 bool,
3959 bool,
3960 bool,
3961 bool,
3962 bool,
3963 bool,
3964 bool,
3965 bool,
3966 bool,
3967 bool,
3968 bool,
3969 );
3970 b64(
3971 ((self.0 >> 00) & 1) == 1,
3972 ((self.0 >> 01) & 1) == 1,
3973 ((self.0 >> 02) & 1) == 1,
3974 ((self.0 >> 03) & 1) == 1,
3975 ((self.0 >> 04) & 1) == 1,
3976 ((self.0 >> 05) & 1) == 1,
3977 ((self.0 >> 06) & 1) == 1,
3978 ((self.0 >> 07) & 1) == 1,
3979 ((self.0 >> 08) & 1) == 1,
3980 ((self.0 >> 09) & 1) == 1,
3981 ((self.0 >> 10) & 1) == 1,
3982 ((self.0 >> 11) & 1) == 1,
3983 ((self.0 >> 12) & 1) == 1,
3984 ((self.0 >> 13) & 1) == 1,
3985 ((self.0 >> 14) & 1) == 1,
3986 ((self.0 >> 15) & 1) == 1,
3987 ((self.0 >> 16) & 1) == 1,
3988 ((self.0 >> 17) & 1) == 1,
3989 ((self.0 >> 18) & 1) == 1,
3990 ((self.0 >> 19) & 1) == 1,
3991 ((self.0 >> 20) & 1) == 1,
3992 ((self.0 >> 21) & 1) == 1,
3993 ((self.0 >> 22) & 1) == 1,
3994 ((self.0 >> 23) & 1) == 1,
3995 ((self.0 >> 24) & 1) == 1,
3996 ((self.0 >> 25) & 1) == 1,
3997 ((self.0 >> 26) & 1) == 1,
3998 ((self.0 >> 27) & 1) == 1,
3999 ((self.0 >> 28) & 1) == 1,
4000 ((self.0 >> 29) & 1) == 1,
4001 ((self.0 >> 30) & 1) == 1,
4002 ((self.0 >> 31) & 1) == 1,
4003 ((self.0 >> 32) & 1) == 1,
4004 ((self.0 >> 33) & 1) == 1,
4005 ((self.0 >> 34) & 1) == 1,
4006 ((self.0 >> 35) & 1) == 1,
4007 ((self.0 >> 36) & 1) == 1,
4008 ((self.0 >> 37) & 1) == 1,
4009 ((self.0 >> 38) & 1) == 1,
4010 ((self.0 >> 39) & 1) == 1,
4011 ((self.0 >> 40) & 1) == 1,
4012 ((self.0 >> 41) & 1) == 1,
4013 ((self.0 >> 42) & 1) == 1,
4014 ((self.0 >> 43) & 1) == 1,
4015 ((self.0 >> 44) & 1) == 1,
4016 ((self.0 >> 45) & 1) == 1,
4017 ((self.0 >> 46) & 1) == 1,
4018 ((self.0 >> 47) & 1) == 1,
4019 ((self.0 >> 48) & 1) == 1,
4020 ((self.0 >> 49) & 1) == 1,
4021 ((self.0 >> 50) & 1) == 1,
4022 ((self.0 >> 51) & 1) == 1,
4023 ((self.0 >> 52) & 1) == 1,
4024 ((self.0 >> 53) & 1) == 1,
4025 ((self.0 >> 54) & 1) == 1,
4026 ((self.0 >> 55) & 1) == 1,
4027 ((self.0 >> 56) & 1) == 1,
4028 ((self.0 >> 57) & 1) == 1,
4029 ((self.0 >> 58) & 1) == 1,
4030 ((self.0 >> 59) & 1) == 1,
4031 ((self.0 >> 60) & 1) == 1,
4032 ((self.0 >> 61) & 1) == 1,
4033 ((self.0 >> 62) & 1) == 1,
4034 ((self.0 >> 63) & 1) == 1,
4035 )
4036 .fmt(f)
4037 }
4038}
4039
4040impl Debug for m8 {
4041 #[inline]
4042 fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
4043 self.is_set().fmt(f)
4044 }
4045}
4046impl Debug for m16 {
4047 #[inline]
4048 fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
4049 self.is_set().fmt(f)
4050 }
4051}
4052impl Debug for m32 {
4053 #[inline]
4054 fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
4055 self.is_set().fmt(f)
4056 }
4057}
4058impl Debug for m64 {
4059 #[inline]
4060 fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
4061 self.is_set().fmt(f)
4062 }
4063}
4064
4065impl m8 {
4066 #[inline(always)]
4069 pub const fn new(flag: bool) -> Self {
4070 Self(if flag { u8::MAX } else { 0 })
4071 }
4072
4073 #[inline(always)]
4075 pub const fn is_set(self) -> bool {
4076 self.0 != 0
4077 }
4078}
4079impl m16 {
4080 #[inline(always)]
4083 pub const fn new(flag: bool) -> Self {
4084 Self(if flag { u16::MAX } else { 0 })
4085 }
4086
4087 #[inline(always)]
4089 pub const fn is_set(self) -> bool {
4090 self.0 != 0
4091 }
4092}
4093impl m32 {
4094 #[inline(always)]
4097 pub const fn new(flag: bool) -> Self {
4098 Self(if flag { u32::MAX } else { 0 })
4099 }
4100
4101 #[inline(always)]
4103 pub const fn is_set(self) -> bool {
4104 self.0 != 0
4105 }
4106}
4107impl m64 {
4108 #[inline(always)]
4111 pub const fn new(flag: bool) -> Self {
4112 Self(if flag { u64::MAX } else { 0 })
4113 }
4114
4115 #[inline(always)]
4117 pub const fn is_set(self) -> bool {
4118 self.0 != 0
4119 }
4120}
4121
4122#[derive(Debug, Copy, Clone, PartialEq, Eq)]
4124#[repr(C)]
4125pub struct i8x16(
4126 pub i8,
4127 pub i8,
4128 pub i8,
4129 pub i8,
4130 pub i8,
4131 pub i8,
4132 pub i8,
4133 pub i8,
4134 pub i8,
4135 pub i8,
4136 pub i8,
4137 pub i8,
4138 pub i8,
4139 pub i8,
4140 pub i8,
4141 pub i8,
4142);
4143#[derive(Debug, Copy, Clone, PartialEq, Eq)]
4145#[repr(C)]
4146pub struct i8x32(
4147 pub i8,
4148 pub i8,
4149 pub i8,
4150 pub i8,
4151 pub i8,
4152 pub i8,
4153 pub i8,
4154 pub i8,
4155 pub i8,
4156 pub i8,
4157 pub i8,
4158 pub i8,
4159 pub i8,
4160 pub i8,
4161 pub i8,
4162 pub i8,
4163 pub i8,
4164 pub i8,
4165 pub i8,
4166 pub i8,
4167 pub i8,
4168 pub i8,
4169 pub i8,
4170 pub i8,
4171 pub i8,
4172 pub i8,
4173 pub i8,
4174 pub i8,
4175 pub i8,
4176 pub i8,
4177 pub i8,
4178 pub i8,
4179);
4180#[derive(Debug, Copy, Clone, PartialEq, Eq)]
4182#[repr(C)]
4183pub struct i8x64(
4184 pub i8,
4185 pub i8,
4186 pub i8,
4187 pub i8,
4188 pub i8,
4189 pub i8,
4190 pub i8,
4191 pub i8,
4192 pub i8,
4193 pub i8,
4194 pub i8,
4195 pub i8,
4196 pub i8,
4197 pub i8,
4198 pub i8,
4199 pub i8,
4200 pub i8,
4201 pub i8,
4202 pub i8,
4203 pub i8,
4204 pub i8,
4205 pub i8,
4206 pub i8,
4207 pub i8,
4208 pub i8,
4209 pub i8,
4210 pub i8,
4211 pub i8,
4212 pub i8,
4213 pub i8,
4214 pub i8,
4215 pub i8,
4216 pub i8,
4217 pub i8,
4218 pub i8,
4219 pub i8,
4220 pub i8,
4221 pub i8,
4222 pub i8,
4223 pub i8,
4224 pub i8,
4225 pub i8,
4226 pub i8,
4227 pub i8,
4228 pub i8,
4229 pub i8,
4230 pub i8,
4231 pub i8,
4232 pub i8,
4233 pub i8,
4234 pub i8,
4235 pub i8,
4236 pub i8,
4237 pub i8,
4238 pub i8,
4239 pub i8,
4240 pub i8,
4241 pub i8,
4242 pub i8,
4243 pub i8,
4244 pub i8,
4245 pub i8,
4246 pub i8,
4247 pub i8,
4248);
4249
4250#[derive(Debug, Copy, Clone, PartialEq, Eq)]
4252#[repr(C)]
4253pub struct u8x16(
4254 pub u8,
4255 pub u8,
4256 pub u8,
4257 pub u8,
4258 pub u8,
4259 pub u8,
4260 pub u8,
4261 pub u8,
4262 pub u8,
4263 pub u8,
4264 pub u8,
4265 pub u8,
4266 pub u8,
4267 pub u8,
4268 pub u8,
4269 pub u8,
4270);
4271#[derive(Debug, Copy, Clone, PartialEq, Eq)]
4273#[repr(C)]
4274pub struct u8x32(
4275 pub u8,
4276 pub u8,
4277 pub u8,
4278 pub u8,
4279 pub u8,
4280 pub u8,
4281 pub u8,
4282 pub u8,
4283 pub u8,
4284 pub u8,
4285 pub u8,
4286 pub u8,
4287 pub u8,
4288 pub u8,
4289 pub u8,
4290 pub u8,
4291 pub u8,
4292 pub u8,
4293 pub u8,
4294 pub u8,
4295 pub u8,
4296 pub u8,
4297 pub u8,
4298 pub u8,
4299 pub u8,
4300 pub u8,
4301 pub u8,
4302 pub u8,
4303 pub u8,
4304 pub u8,
4305 pub u8,
4306 pub u8,
4307);
4308#[derive(Debug, Copy, Clone, PartialEq, Eq)]
4310#[repr(C)]
4311pub struct u8x64(
4312 pub u8,
4313 pub u8,
4314 pub u8,
4315 pub u8,
4316 pub u8,
4317 pub u8,
4318 pub u8,
4319 pub u8,
4320 pub u8,
4321 pub u8,
4322 pub u8,
4323 pub u8,
4324 pub u8,
4325 pub u8,
4326 pub u8,
4327 pub u8,
4328 pub u8,
4329 pub u8,
4330 pub u8,
4331 pub u8,
4332 pub u8,
4333 pub u8,
4334 pub u8,
4335 pub u8,
4336 pub u8,
4337 pub u8,
4338 pub u8,
4339 pub u8,
4340 pub u8,
4341 pub u8,
4342 pub u8,
4343 pub u8,
4344 pub u8,
4345 pub u8,
4346 pub u8,
4347 pub u8,
4348 pub u8,
4349 pub u8,
4350 pub u8,
4351 pub u8,
4352 pub u8,
4353 pub u8,
4354 pub u8,
4355 pub u8,
4356 pub u8,
4357 pub u8,
4358 pub u8,
4359 pub u8,
4360 pub u8,
4361 pub u8,
4362 pub u8,
4363 pub u8,
4364 pub u8,
4365 pub u8,
4366 pub u8,
4367 pub u8,
4368 pub u8,
4369 pub u8,
4370 pub u8,
4371 pub u8,
4372 pub u8,
4373 pub u8,
4374 pub u8,
4375 pub u8,
4376);
4377
4378#[derive(Debug, Copy, Clone, PartialEq, Eq)]
4380#[repr(C)]
4381pub struct m8x16(
4382 pub m8,
4383 pub m8,
4384 pub m8,
4385 pub m8,
4386 pub m8,
4387 pub m8,
4388 pub m8,
4389 pub m8,
4390 pub m8,
4391 pub m8,
4392 pub m8,
4393 pub m8,
4394 pub m8,
4395 pub m8,
4396 pub m8,
4397 pub m8,
4398);
4399#[derive(Debug, Copy, Clone, PartialEq, Eq)]
4401#[repr(C)]
4402pub struct m8x32(
4403 pub m8,
4404 pub m8,
4405 pub m8,
4406 pub m8,
4407 pub m8,
4408 pub m8,
4409 pub m8,
4410 pub m8,
4411 pub m8,
4412 pub m8,
4413 pub m8,
4414 pub m8,
4415 pub m8,
4416 pub m8,
4417 pub m8,
4418 pub m8,
4419 pub m8,
4420 pub m8,
4421 pub m8,
4422 pub m8,
4423 pub m8,
4424 pub m8,
4425 pub m8,
4426 pub m8,
4427 pub m8,
4428 pub m8,
4429 pub m8,
4430 pub m8,
4431 pub m8,
4432 pub m8,
4433 pub m8,
4434 pub m8,
4435);
4436
4437#[derive(Debug, Copy, Clone, PartialEq, Eq)]
4439#[repr(C)]
4440pub struct m8x64(
4441 pub m8,
4442 pub m8,
4443 pub m8,
4444 pub m8,
4445 pub m8,
4446 pub m8,
4447 pub m8,
4448 pub m8,
4449 pub m8,
4450 pub m8,
4451 pub m8,
4452 pub m8,
4453 pub m8,
4454 pub m8,
4455 pub m8,
4456 pub m8,
4457 pub m8,
4458 pub m8,
4459 pub m8,
4460 pub m8,
4461 pub m8,
4462 pub m8,
4463 pub m8,
4464 pub m8,
4465 pub m8,
4466 pub m8,
4467 pub m8,
4468 pub m8,
4469 pub m8,
4470 pub m8,
4471 pub m8,
4472 pub m8,
4473 pub m8,
4474 pub m8,
4475 pub m8,
4476 pub m8,
4477 pub m8,
4478 pub m8,
4479 pub m8,
4480 pub m8,
4481 pub m8,
4482 pub m8,
4483 pub m8,
4484 pub m8,
4485 pub m8,
4486 pub m8,
4487 pub m8,
4488 pub m8,
4489 pub m8,
4490 pub m8,
4491 pub m8,
4492 pub m8,
4493 pub m8,
4494 pub m8,
4495 pub m8,
4496 pub m8,
4497 pub m8,
4498 pub m8,
4499 pub m8,
4500 pub m8,
4501 pub m8,
4502 pub m8,
4503 pub m8,
4504 pub m8,
4505);
4506
4507#[derive(Debug, Copy, Clone, PartialEq, Eq)]
4509#[repr(C)]
4510pub struct i16x8(
4511 pub i16,
4512 pub i16,
4513 pub i16,
4514 pub i16,
4515 pub i16,
4516 pub i16,
4517 pub i16,
4518 pub i16,
4519);
4520#[derive(Debug, Copy, Clone, PartialEq, Eq)]
4522#[repr(C)]
4523pub struct i16x16(
4524 pub i16,
4525 pub i16,
4526 pub i16,
4527 pub i16,
4528 pub i16,
4529 pub i16,
4530 pub i16,
4531 pub i16,
4532 pub i16,
4533 pub i16,
4534 pub i16,
4535 pub i16,
4536 pub i16,
4537 pub i16,
4538 pub i16,
4539 pub i16,
4540);
4541#[derive(Debug, Copy, Clone, PartialEq, Eq)]
4543#[repr(C)]
4544pub struct i16x32(
4545 pub i16,
4546 pub i16,
4547 pub i16,
4548 pub i16,
4549 pub i16,
4550 pub i16,
4551 pub i16,
4552 pub i16,
4553 pub i16,
4554 pub i16,
4555 pub i16,
4556 pub i16,
4557 pub i16,
4558 pub i16,
4559 pub i16,
4560 pub i16,
4561 pub i16,
4562 pub i16,
4563 pub i16,
4564 pub i16,
4565 pub i16,
4566 pub i16,
4567 pub i16,
4568 pub i16,
4569 pub i16,
4570 pub i16,
4571 pub i16,
4572 pub i16,
4573 pub i16,
4574 pub i16,
4575 pub i16,
4576 pub i16,
4577);
4578
4579#[derive(Debug, Copy, Clone, PartialEq, Eq)]
4581#[repr(C)]
4582pub struct u16x8(
4583 pub u16,
4584 pub u16,
4585 pub u16,
4586 pub u16,
4587 pub u16,
4588 pub u16,
4589 pub u16,
4590 pub u16,
4591);
4592#[derive(Debug, Copy, Clone, PartialEq, Eq)]
4594#[repr(C)]
4595pub struct u16x16(
4596 pub u16,
4597 pub u16,
4598 pub u16,
4599 pub u16,
4600 pub u16,
4601 pub u16,
4602 pub u16,
4603 pub u16,
4604 pub u16,
4605 pub u16,
4606 pub u16,
4607 pub u16,
4608 pub u16,
4609 pub u16,
4610 pub u16,
4611 pub u16,
4612);
4613#[derive(Debug, Copy, Clone, PartialEq, Eq)]
4615#[repr(C)]
4616pub struct u16x32(
4617 pub u16,
4618 pub u16,
4619 pub u16,
4620 pub u16,
4621 pub u16,
4622 pub u16,
4623 pub u16,
4624 pub u16,
4625 pub u16,
4626 pub u16,
4627 pub u16,
4628 pub u16,
4629 pub u16,
4630 pub u16,
4631 pub u16,
4632 pub u16,
4633 pub u16,
4634 pub u16,
4635 pub u16,
4636 pub u16,
4637 pub u16,
4638 pub u16,
4639 pub u16,
4640 pub u16,
4641 pub u16,
4642 pub u16,
4643 pub u16,
4644 pub u16,
4645 pub u16,
4646 pub u16,
4647 pub u16,
4648 pub u16,
4649);
4650
4651#[derive(Debug, Copy, Clone, PartialEq, Eq)]
4653#[repr(C)]
4654pub struct m16x8(
4655 pub m16,
4656 pub m16,
4657 pub m16,
4658 pub m16,
4659 pub m16,
4660 pub m16,
4661 pub m16,
4662 pub m16,
4663);
4664#[derive(Debug, Copy, Clone, PartialEq, Eq)]
4666#[repr(C)]
4667pub struct m16x16(
4668 pub m16,
4669 pub m16,
4670 pub m16,
4671 pub m16,
4672 pub m16,
4673 pub m16,
4674 pub m16,
4675 pub m16,
4676 pub m16,
4677 pub m16,
4678 pub m16,
4679 pub m16,
4680 pub m16,
4681 pub m16,
4682 pub m16,
4683 pub m16,
4684);
4685#[derive(Debug, Copy, Clone, PartialEq, Eq)]
4687#[repr(C)]
4688pub struct m16x32(
4689 pub m16,
4690 pub m16,
4691 pub m16,
4692 pub m16,
4693 pub m16,
4694 pub m16,
4695 pub m16,
4696 pub m16,
4697 pub m16,
4698 pub m16,
4699 pub m16,
4700 pub m16,
4701 pub m16,
4702 pub m16,
4703 pub m16,
4704 pub m16,
4705 pub m16,
4706 pub m16,
4707 pub m16,
4708 pub m16,
4709 pub m16,
4710 pub m16,
4711 pub m16,
4712 pub m16,
4713 pub m16,
4714 pub m16,
4715 pub m16,
4716 pub m16,
4717 pub m16,
4718 pub m16,
4719 pub m16,
4720 pub m16,
4721);
4722
4723#[derive(Debug, Copy, Clone, PartialEq)]
4725#[repr(C)]
4726pub struct f32x4(pub f32, pub f32, pub f32, pub f32);
4727
4728#[derive(Debug, Copy, Clone, PartialEq)]
4730#[repr(C)]
4731pub struct f32x8(
4732 pub f32,
4733 pub f32,
4734 pub f32,
4735 pub f32,
4736 pub f32,
4737 pub f32,
4738 pub f32,
4739 pub f32,
4740);
4741#[derive(Debug, Copy, Clone, PartialEq)]
4743#[repr(C)]
4744pub struct f32x16(
4745 pub f32,
4746 pub f32,
4747 pub f32,
4748 pub f32,
4749 pub f32,
4750 pub f32,
4751 pub f32,
4752 pub f32,
4753 pub f32,
4754 pub f32,
4755 pub f32,
4756 pub f32,
4757 pub f32,
4758 pub f32,
4759 pub f32,
4760 pub f32,
4761);
4762
4763#[derive(Copy, Clone, PartialEq)]
4765#[repr(C)]
4766pub struct c32x2(pub c32, pub c32);
4767
4768impl Debug for c32x2 {
4769 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
4770 #[derive(Copy, Clone, Debug)]
4771 #[repr(C)]
4772 pub struct c32x2(pub DebugCplx<c32>, pub DebugCplx<c32>);
4773 unsafe impl Zeroable for c32x2 {}
4774 unsafe impl Pod for c32x2 {}
4775
4776 let this: c32x2 = cast!(*self);
4777 this.fmt(f)
4778 }
4779}
4780
4781#[derive(Copy, Clone, PartialEq)]
4783#[repr(C)]
4784pub struct c32x4(pub c32, pub c32, pub c32, pub c32);
4785
4786impl Debug for c32x4 {
4787 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
4788 #[derive(Copy, Clone, Debug)]
4789 #[repr(C)]
4790 pub struct c32x4(
4791 pub DebugCplx<c32>,
4792 pub DebugCplx<c32>,
4793 pub DebugCplx<c32>,
4794 pub DebugCplx<c32>,
4795 );
4796 unsafe impl Zeroable for c32x4 {}
4797 unsafe impl Pod for c32x4 {}
4798
4799 let this: c32x4 = cast!(*self);
4800 this.fmt(f)
4801 }
4802}
4803
4804#[derive(Copy, Clone, PartialEq)]
4806#[repr(C)]
4807pub struct c32x8(
4808 pub c32,
4809 pub c32,
4810 pub c32,
4811 pub c32,
4812 pub c32,
4813 pub c32,
4814 pub c32,
4815 pub c32,
4816);
4817
4818impl Debug for c32x8 {
4819 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
4820 #[derive(Copy, Clone, Debug)]
4821 #[repr(C)]
4822 pub struct c32x8(
4823 pub DebugCplx<c32>,
4824 pub DebugCplx<c32>,
4825 pub DebugCplx<c32>,
4826 pub DebugCplx<c32>,
4827 pub DebugCplx<c32>,
4828 pub DebugCplx<c32>,
4829 pub DebugCplx<c32>,
4830 pub DebugCplx<c32>,
4831 );
4832 unsafe impl Zeroable for c32x8 {}
4833 unsafe impl Pod for c32x8 {}
4834
4835 let this: c32x8 = cast!(*self);
4836 this.fmt(f)
4837 }
4838}
4839#[derive(Debug, Copy, Clone, PartialEq, Eq)]
4841#[repr(C)]
4842pub struct i32x4(pub i32, pub i32, pub i32, pub i32);
4843#[derive(Debug, Copy, Clone, PartialEq, Eq)]
4845#[repr(C)]
4846pub struct i32x8(
4847 pub i32,
4848 pub i32,
4849 pub i32,
4850 pub i32,
4851 pub i32,
4852 pub i32,
4853 pub i32,
4854 pub i32,
4855);
4856#[derive(Debug, Copy, Clone, PartialEq, Eq)]
4858#[repr(C)]
4859pub struct i32x16(
4860 pub i32,
4861 pub i32,
4862 pub i32,
4863 pub i32,
4864 pub i32,
4865 pub i32,
4866 pub i32,
4867 pub i32,
4868 pub i32,
4869 pub i32,
4870 pub i32,
4871 pub i32,
4872 pub i32,
4873 pub i32,
4874 pub i32,
4875 pub i32,
4876);
4877
4878#[derive(Debug, Copy, Clone, PartialEq, Eq)]
4880#[repr(C)]
4881pub struct u32x4(pub u32, pub u32, pub u32, pub u32);
4882#[derive(Debug, Copy, Clone, PartialEq, Eq)]
4884#[repr(C)]
4885pub struct u32x8(
4886 pub u32,
4887 pub u32,
4888 pub u32,
4889 pub u32,
4890 pub u32,
4891 pub u32,
4892 pub u32,
4893 pub u32,
4894);
4895#[derive(Debug, Copy, Clone, PartialEq, Eq)]
4897#[repr(C)]
4898pub struct u32x16(
4899 pub u32,
4900 pub u32,
4901 pub u32,
4902 pub u32,
4903 pub u32,
4904 pub u32,
4905 pub u32,
4906 pub u32,
4907 pub u32,
4908 pub u32,
4909 pub u32,
4910 pub u32,
4911 pub u32,
4912 pub u32,
4913 pub u32,
4914 pub u32,
4915);
4916
4917#[derive(Debug, Copy, Clone, PartialEq, Eq)]
4919#[repr(C)]
4920pub struct m32x4(pub m32, pub m32, pub m32, pub m32);
4921#[derive(Debug, Copy, Clone, PartialEq, Eq)]
4923#[repr(C)]
4924pub struct m32x8(
4925 pub m32,
4926 pub m32,
4927 pub m32,
4928 pub m32,
4929 pub m32,
4930 pub m32,
4931 pub m32,
4932 pub m32,
4933);
4934#[derive(Debug, Copy, Clone, PartialEq, Eq)]
4936#[repr(C)]
4937pub struct m32x16(
4938 pub m32,
4939 pub m32,
4940 pub m32,
4941 pub m32,
4942 pub m32,
4943 pub m32,
4944 pub m32,
4945 pub m32,
4946 pub m32,
4947 pub m32,
4948 pub m32,
4949 pub m32,
4950 pub m32,
4951 pub m32,
4952 pub m32,
4953 pub m32,
4954);
4955
4956#[derive(Debug, Copy, Clone, PartialEq)]
4958#[repr(C)]
4959pub struct f64x2(pub f64, pub f64);
4960#[derive(Debug, Copy, Clone, PartialEq)]
4962#[repr(C)]
4963pub struct f64x4(pub f64, pub f64, pub f64, pub f64);
4964#[derive(Debug, Copy, Clone, PartialEq)]
4966#[repr(C)]
4967pub struct f64x8(
4968 pub f64,
4969 pub f64,
4970 pub f64,
4971 pub f64,
4972 pub f64,
4973 pub f64,
4974 pub f64,
4975 pub f64,
4976);
4977
4978#[derive(Copy, Clone, PartialEq)]
4980#[repr(C)]
4981pub struct c64x1(pub c64);
4982
4983impl Debug for c64x1 {
4984 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
4985 #[derive(Copy, Clone, Debug)]
4986 #[repr(C)]
4987 pub struct c64x1(pub DebugCplx<c64>);
4988 unsafe impl Zeroable for c64x1 {}
4989 unsafe impl Pod for c64x1 {}
4990
4991 let this: c64x1 = cast!(*self);
4992 this.fmt(f)
4993 }
4994}
4995
4996#[derive(Copy, Clone, PartialEq)]
4998#[repr(C)]
4999pub struct c64x2(pub c64, pub c64);
5000
5001impl Debug for c64x2 {
5002 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
5003 #[derive(Copy, Clone, Debug)]
5004 #[repr(C)]
5005 pub struct c64x2(pub DebugCplx<c64>, pub DebugCplx<c64>);
5006 unsafe impl Zeroable for c64x2 {}
5007 unsafe impl Pod for c64x2 {}
5008
5009 let this: c64x2 = cast!(*self);
5010 this.fmt(f)
5011 }
5012}
5013
5014#[derive(Copy, Clone, PartialEq)]
5016#[repr(C)]
5017pub struct c64x4(pub c64, pub c64, pub c64, pub c64);
5018
5019impl Debug for c64x4 {
5020 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
5021 #[derive(Copy, Clone, Debug)]
5022 #[repr(C)]
5023 pub struct c64x4(
5024 pub DebugCplx<c64>,
5025 pub DebugCplx<c64>,
5026 pub DebugCplx<c64>,
5027 pub DebugCplx<c64>,
5028 );
5029 unsafe impl Zeroable for c64x4 {}
5030 unsafe impl Pod for c64x4 {}
5031
5032 let this: c64x4 = cast!(*self);
5033 this.fmt(f)
5034 }
5035}
5036
5037#[derive(Debug, Copy, Clone, PartialEq, Eq)]
5039#[repr(C)]
5040pub struct i64x2(pub i64, pub i64);
5041#[derive(Debug, Copy, Clone, PartialEq, Eq)]
5043#[repr(C)]
5044pub struct i64x4(pub i64, pub i64, pub i64, pub i64);
5045#[derive(Debug, Copy, Clone, PartialEq, Eq)]
5047#[repr(C)]
5048pub struct i64x8(
5049 pub i64,
5050 pub i64,
5051 pub i64,
5052 pub i64,
5053 pub i64,
5054 pub i64,
5055 pub i64,
5056 pub i64,
5057);
5058
5059#[derive(Debug, Copy, Clone, PartialEq, Eq)]
5061#[repr(C)]
5062pub struct u64x2(pub u64, pub u64);
5063#[derive(Debug, Copy, Clone, PartialEq, Eq)]
5065#[repr(C)]
5066pub struct u64x4(pub u64, pub u64, pub u64, pub u64);
5067#[derive(Debug, Copy, Clone, PartialEq, Eq)]
5069#[repr(C)]
5070pub struct u64x8(
5071 pub u64,
5072 pub u64,
5073 pub u64,
5074 pub u64,
5075 pub u64,
5076 pub u64,
5077 pub u64,
5078 pub u64,
5079);
5080
5081#[derive(Debug, Copy, Clone, PartialEq, Eq)]
5083#[repr(C)]
5084pub struct m64x2(pub m64, pub m64);
5085#[derive(Debug, Copy, Clone, PartialEq, Eq)]
5087#[repr(C)]
5088pub struct m64x4(pub m64, pub m64, pub m64, pub m64);
5089#[derive(Debug, Copy, Clone, PartialEq, Eq)]
5091#[repr(C)]
5092pub struct m64x8(
5093 pub m64,
5094 pub m64,
5095 pub m64,
5096 pub m64,
5097 pub m64,
5098 pub m64,
5099 pub m64,
5100 pub m64,
5101);
5102
5103unsafe impl Zeroable for m8 {}
5104unsafe impl Zeroable for m16 {}
5105unsafe impl Zeroable for m32 {}
5106unsafe impl Zeroable for m64 {}
5107unsafe impl Pod for m8 {}
5108unsafe impl Pod for m16 {}
5109unsafe impl Pod for m32 {}
5110unsafe impl Pod for m64 {}
5111
5112unsafe impl Zeroable for b8 {}
5113unsafe impl Pod for b8 {}
5114unsafe impl Zeroable for b16 {}
5115unsafe impl Pod for b16 {}
5116unsafe impl Zeroable for b32 {}
5117unsafe impl Pod for b32 {}
5118unsafe impl Zeroable for b64 {}
5119unsafe impl Pod for b64 {}
5120
5121unsafe impl Zeroable for i8x16 {}
5122unsafe impl Zeroable for i8x32 {}
5123unsafe impl Zeroable for i8x64 {}
5124unsafe impl Pod for i8x16 {}
5125unsafe impl Pod for i8x32 {}
5126unsafe impl Pod for i8x64 {}
5127unsafe impl Zeroable for u8x16 {}
5128unsafe impl Zeroable for u8x32 {}
5129unsafe impl Zeroable for u8x64 {}
5130unsafe impl Pod for u8x16 {}
5131unsafe impl Pod for u8x32 {}
5132unsafe impl Pod for u8x64 {}
5133unsafe impl Zeroable for m8x16 {}
5134unsafe impl Zeroable for m8x32 {}
5135unsafe impl Zeroable for m8x64 {}
5136unsafe impl Pod for m8x16 {}
5137unsafe impl Pod for m8x32 {}
5138unsafe impl Pod for m8x64 {}
5139
5140unsafe impl Zeroable for i16x8 {}
5141unsafe impl Zeroable for i16x16 {}
5142unsafe impl Zeroable for i16x32 {}
5143unsafe impl Pod for i16x8 {}
5144unsafe impl Pod for i16x16 {}
5145unsafe impl Pod for i16x32 {}
5146unsafe impl Zeroable for u16x8 {}
5147unsafe impl Zeroable for u16x16 {}
5148unsafe impl Zeroable for u16x32 {}
5149unsafe impl Pod for u16x8 {}
5150unsafe impl Pod for u16x16 {}
5151unsafe impl Pod for u16x32 {}
5152unsafe impl Zeroable for m16x8 {}
5153unsafe impl Zeroable for m16x16 {}
5154unsafe impl Zeroable for m16x32 {}
5155unsafe impl Pod for m16x8 {}
5156unsafe impl Pod for m16x16 {}
5157unsafe impl Pod for m16x32 {}
5158
5159unsafe impl Zeroable for f32x4 {}
5160unsafe impl Zeroable for f32x8 {}
5161unsafe impl Zeroable for f32x16 {}
5162unsafe impl Pod for f32x4 {}
5163unsafe impl Pod for f32x8 {}
5164unsafe impl Pod for f32x16 {}
5165unsafe impl Zeroable for c32x2 {}
5166unsafe impl Zeroable for c32x4 {}
5167unsafe impl Zeroable for c32x8 {}
5168unsafe impl Pod for c32x2 {}
5169unsafe impl Pod for c32x4 {}
5170unsafe impl Pod for c32x8 {}
5171unsafe impl Zeroable for i32x4 {}
5172unsafe impl Zeroable for i32x8 {}
5173unsafe impl Zeroable for i32x16 {}
5174unsafe impl Pod for i32x4 {}
5175unsafe impl Pod for i32x8 {}
5176unsafe impl Pod for i32x16 {}
5177unsafe impl Zeroable for u32x4 {}
5178unsafe impl Zeroable for u32x8 {}
5179unsafe impl Zeroable for u32x16 {}
5180unsafe impl Pod for u32x4 {}
5181unsafe impl Pod for u32x8 {}
5182unsafe impl Pod for u32x16 {}
5183unsafe impl Zeroable for m32x4 {}
5184unsafe impl Zeroable for m32x8 {}
5185unsafe impl Zeroable for m32x16 {}
5186unsafe impl Pod for m32x4 {}
5187unsafe impl Pod for m32x8 {}
5188unsafe impl Pod for m32x16 {}
5189
5190unsafe impl Zeroable for f64x2 {}
5191unsafe impl Zeroable for f64x4 {}
5192unsafe impl Zeroable for f64x8 {}
5193unsafe impl Pod for f64x2 {}
5194unsafe impl Pod for f64x4 {}
5195unsafe impl Pod for f64x8 {}
5196unsafe impl Zeroable for c64x1 {}
5197unsafe impl Zeroable for c64x2 {}
5198unsafe impl Zeroable for c64x4 {}
5199unsafe impl Pod for c64x1 {}
5200unsafe impl Pod for c64x2 {}
5201unsafe impl Pod for c64x4 {}
5202unsafe impl Zeroable for i64x2 {}
5203unsafe impl Zeroable for i64x4 {}
5204unsafe impl Zeroable for i64x8 {}
5205unsafe impl Pod for i64x2 {}
5206unsafe impl Pod for i64x4 {}
5207unsafe impl Pod for i64x8 {}
5208unsafe impl Zeroable for u64x2 {}
5209unsafe impl Zeroable for u64x4 {}
5210unsafe impl Zeroable for u64x8 {}
5211unsafe impl Pod for u64x2 {}
5212unsafe impl Pod for u64x4 {}
5213unsafe impl Pod for u64x8 {}
5214unsafe impl Zeroable for m64x2 {}
5215unsafe impl Zeroable for m64x4 {}
5216unsafe impl Zeroable for m64x8 {}
5217unsafe impl Pod for m64x2 {}
5218unsafe impl Pod for m64x4 {}
5219unsafe impl Pod for m64x8 {}
5220
5221macro_rules! iota {
5222 ($T: ty, $N: expr, $int: ty) => {
5223 const {
5224 unsafe {
5225 let mut iota = [const { core::mem::MaybeUninit::uninit() }; $N];
5226 {
5227 let mut i = 0;
5228 while i < $N {
5229 let v = (&raw mut iota[i]) as *mut $int;
5230
5231 let mut j = 0;
5232 while j < core::mem::size_of::<$T>() / core::mem::size_of::<$int>() {
5233 v.add(j).write_unaligned(i as $int);
5234 j += 1;
5235 }
5236
5237 i += 1;
5238 }
5239 }
5240 iota
5241 }
5242 }
5243 };
5244}
5245
5246pub const fn iota_8<T: Interleave, const N: usize>() -> [MaybeUninit<T>; N] {
5247 iota!(T, N, u8)
5248}
5249pub const fn iota_16<T: Interleave, const N: usize>() -> [MaybeUninit<T>; N] {
5250 iota!(T, N, u16)
5251}
5252pub const fn iota_32<T: Interleave, const N: usize>() -> [MaybeUninit<T>; N] {
5253 iota!(T, N, u32)
5254}
5255pub const fn iota_64<T: Interleave, const N: usize>() -> [MaybeUninit<T>; N] {
5256 iota!(T, N, u64)
5257}
5258
5259#[cfg(target_arch = "x86_64")]
5260#[cfg(test)]
5261mod tests {
5262 use super::*;
5263
5264 #[test]
5265 fn test_interleave() {
5266 if let Some(simd) = x86::V3::try_new() {
5267 {
5268 let src = [f64x4(0.0, 0.1, 1.0, 1.1), f64x4(2.0, 2.1, 3.0, 3.1)];
5269 let dst = unsafe { deinterleave_fallback::<f64, f64x4, [f64x4; 2]>(src) };
5270 assert_eq!(dst[1], simd.add_f64x4(dst[0], simd.splat_f64x4(0.1)));
5271 assert_eq!(src, unsafe {
5272 interleave_fallback::<f64, f64x4, [f64x4; 2]>(dst)
5273 });
5274 }
5275 {
5276 let src = [
5277 f64x4(0.0, 0.1, 0.2, 0.3),
5278 f64x4(1.0, 1.1, 1.2, 1.3),
5279 f64x4(2.0, 2.1, 2.2, 2.3),
5280 f64x4(3.0, 3.1, 3.2, 3.3),
5281 ];
5282 let dst = unsafe { deinterleave_fallback::<f64, f64x4, [f64x4; 4]>(src) };
5283 assert_eq!(dst[1], simd.add_f64x4(dst[0], simd.splat_f64x4(0.1)));
5284 assert_eq!(dst[2], simd.add_f64x4(dst[0], simd.splat_f64x4(0.2)));
5285 assert_eq!(dst[3], simd.add_f64x4(dst[0], simd.splat_f64x4(0.3)));
5286 assert_eq!(src, unsafe {
5287 interleave_fallback::<f64, f64x4, [f64x4; 4]>(dst)
5288 });
5289 }
5290 }
5291 }
5292}