macerator/backend/x86/
mod.rs

1#![allow(
2    clippy::missing_transmute_annotations,
3    clippy::useless_transmute,
4    clippy::transmute_int_to_float,
5    unused_unsafe
6)]
7// Lint can't detect the build script version check
8#![cfg_attr(all(avx512, not(avx512_nightly)), allow(incompatible_msrv))]
9
10pub mod v2;
11pub mod v3;
12#[cfg(avx512)]
13pub mod v4;
14
15pub use v2::V2;
16pub use v3::V3;
17#[cfg(avx512)]
18pub use v4::V4;
19#[cfg(fp16)]
20pub use v4::V4FP16;
21
22macro_rules! lanes {
23    ($($bits: literal),*) => {
24        $(paste! {
25            #[inline(always)]
26            fn [<lanes $bits>]() -> usize {
27                WIDTH / $bits
28            }
29        })*
30    };
31}
32pub(crate) use lanes;
33
34macro_rules! impl_binop_scalar {
35    ($func: ident, $intrinsic: path, $($ty: ty),*) => {
36        $(paste! {
37            #[inline(always)]
38            fn [<$func _ $ty>](a: Self::Register, b: Self::Register) -> Self::Register {
39                const LANES: usize = WIDTH / (8 * size_of::<$ty>());
40                let a: [$ty; LANES] = cast!(a);
41                let b: [$ty; LANES] = cast!(b);
42                let mut out = [$ty::default(); LANES];
43
44                for i in 0..LANES {
45                    out[i] = $intrinsic(a[i], b[i]);
46                }
47                cast!(out)
48            }
49            #[inline(always)]
50            fn [<$func _ $ty _supported>]() -> bool {
51                false
52            }
53        })*
54    };
55}
56pub(crate) use impl_binop_scalar;
57
58macro_rules! impl_unop_scalar {
59    ($func: ident, $intrinsic: path, $($ty: ty),*) => {
60        $(paste! {
61            #[inline(always)]
62            fn [<$func _ $ty>](a: Self::Register) -> Self::Register {
63                const LANES: usize = WIDTH / (8 * size_of::<$ty>());
64                let a: [$ty; LANES] = cast!(a);
65                let mut out = [$ty::default(); LANES];
66
67                for i in 0..LANES {
68                    out[i] = a[i].$intrinsic();
69                }
70                cast!(out)
71            }
72            #[inline(always)]
73            fn [<$func _ $ty _supported>]() -> bool {
74                false
75            }
76        })*
77    };
78}
79pub(crate) use impl_unop_scalar;
80
81macro_rules! with_ty {
82    ($func: ident, f16) => {
83        paste!([<$func _ph>])
84    };
85    ($func: ident, f32) => {
86        paste!([<$func _ps>])
87    };
88    ($func: ident, f64) => {
89        paste!([<$func _pd>])
90    };
91    ($func: ident, $ty: ident) => {
92        paste!([<$func _ep $ty>])
93    }
94}
95pub(crate) use with_ty;
96
97macro_rules! with_ty_signless {
98    ($func: ident, u8) => {
99        with_ty!($func, i8)
100    };
101    ($func: ident, u16) => {
102        with_ty!($func, i16)
103    };
104    ($func: ident, u32) => {
105        with_ty!($func, i32)
106    };
107    ($func: ident, u64) => {
108        with_ty!($func, i64)
109    };
110    ($func: ident, $ty: ident) => {
111        with_ty!($func, $ty)
112    };
113}
114pub(crate) use with_ty_signless;
115
116macro_rules! impl_binop_signless {
117    ($func: ident, $intrinsic: ident, $($ty: ty),*) => {
118        $(paste! {
119            #[inline(always)]
120            fn [<$func _ $ty>](a: Self::Register, b: Self::Register) -> Self::Register {
121                cast!(with_ty_signless!($intrinsic, $ty)(cast!(a), cast!(b)))
122            }
123            #[inline(always)]
124            fn [<$func _ $ty _supported>]() -> bool {
125                true
126            }
127        })*
128    };
129}
130pub(crate) use impl_binop_signless;
131
132macro_rules! impl_binop {
133    ($func: ident, $intrinsic: ident, $($ty: ty),*) => {
134        $(paste! {
135            #[inline(always)]
136            fn [<$func _ $ty>](a: Self::Register, b: Self::Register) -> Self::Register {
137                cast!(with_ty!($intrinsic, $ty)(cast!(a), cast!(b)))
138            }
139            #[inline(always)]
140            fn [<$func _ $ty _supported>]() -> bool {
141                true
142            }
143        })*
144    };
145}
146pub(crate) use impl_binop;
147
148macro_rules! impl_binop_untyped {
149    ($func: ident, $intrinsic: ident) => {
150        paste! {
151            #[inline(always)]
152            fn $func(a: Self::Register, b: Self::Register) -> Self::Register {
153                cast!($intrinsic(cast!(a), cast!(b)))
154            }
155            #[inline(always)]
156            fn [<$func _supported>]() -> bool {
157                true
158            }
159        }
160    };
161}
162pub(crate) use impl_binop_untyped;
163
164macro_rules! impl_unop {
165    ($func: ident, $intrinsic: ident, $($ty: ty),*) => {
166        $(paste! {
167            #[inline(always)]
168            fn [<$func _ $ty>](a: Self::Register) -> Self::Register {
169                cast!(with_ty!($intrinsic, $ty)(cast!(a)))
170            }
171            #[inline(always)]
172            fn [<$func _ $ty _supported>]() -> bool {
173                true
174            }
175        })*
176    };
177}
178pub(crate) use impl_unop;
179
180macro_rules! impl_cmp {
181    ($func: ident, $intrinsic: ident, $($ty: ty),*) => {
182        $(paste! {
183            #[inline(always)]
184            fn [<$func _ $ty>](a: Self::Register, b: Self::Register) -> <$ty as Scalar>::Mask<Self> {
185                cast!(with_ty_signless!($intrinsic, $ty)(cast!(a), cast!(b)))
186            }
187            #[inline(always)]
188            fn [<$func _ $ty _supported>]() -> bool {
189                true
190            }
191        })*
192    };
193}
194pub(crate) use impl_cmp;