1#![allow(non_camel_case_types)]
4
5#[inline(always)]
6#[rustc_const_unstable(feature = "stdarch_const_helpers", issue = "none")]
7pub(crate) const unsafe fn simd_imax<T: Copy>(a: T, b: T) -> T {
8 let mask: T = crate::intrinsics::simd::simd_gt(a, b);
9 crate::intrinsics::simd::simd_select(mask, a, b)
10}
11
12#[inline(always)]
13#[rustc_const_unstable(feature = "stdarch_const_helpers", issue = "none")]
14pub(crate) const unsafe fn simd_imin<T: Copy>(a: T, b: T) -> T {
15 let mask: T = crate::intrinsics::simd::simd_lt(a, b);
16 crate::intrinsics::simd::simd_select(mask, a, b)
17}
18
19pub(crate) unsafe trait SimdElement:
21 Copy + const PartialEq + crate::fmt::Debug
22{
23 const ZERO: Self = unsafe { crate::mem::zeroed() };
25}
26
27unsafe impl SimdElement for u8 {}
28unsafe impl SimdElement for u16 {}
29unsafe impl SimdElement for u32 {}
30unsafe impl SimdElement for u64 {}
31unsafe impl SimdElement for u128 {}
32
33unsafe impl SimdElement for i8 {}
34unsafe impl SimdElement for i16 {}
35unsafe impl SimdElement for i32 {}
36unsafe impl SimdElement for i64 {}
37unsafe impl SimdElement for i128 {}
38
39unsafe impl SimdElement for f16 {}
40unsafe impl SimdElement for f32 {}
41unsafe impl SimdElement for f64 {}
42
43#[repr(simd)]
44#[derive(Copy)]
45pub(crate) struct Simd<T: SimdElement, const N: usize>([T; N]);
46
47impl<T: SimdElement, const N: usize> Simd<T, N> {
48 pub(crate) const ZERO: Self = Self::splat(T::ZERO);
50
51 #[inline(always)]
52 pub(crate) const fn from_array(elements: [T; N]) -> Self {
53 Self(elements)
54 }
55
56 #[inline]
57 #[rustc_const_unstable(feature = "stdarch_const_helpers", issue = "none")]
58 pub(crate) const fn splat(value: T) -> Self {
59 unsafe { crate::intrinsics::simd::simd_splat(value) }
60 }
61
62 #[inline]
65 #[rustc_const_unstable(feature = "stdarch_const_helpers", issue = "none")]
66 pub(crate) const fn extract_dyn(&self, index: usize) -> T {
67 assert!(index < N);
68 unsafe { crate::intrinsics::simd::simd_extract_dyn(*self, index as u32) }
70 }
71
72 #[inline]
73 pub(crate) const fn as_array(&self) -> &[T; N] {
74 let simd_ptr: *const Self = self;
75 let array_ptr: *const [T; N] = simd_ptr.cast();
76 unsafe { &*array_ptr }
80 }
81}
82
83impl<T: SimdElement, const N: usize> Clone for Simd<T, N> {
85 #[inline]
86 fn clone(&self) -> Self {
87 *self
88 }
89}
90
91#[rustc_const_unstable(feature = "stdarch_const_helpers", issue = "none")]
92#[rustfmt::skip] const impl<T: SimdElement, const N: usize> crate::cmp::PartialEq for Simd<T, N> {
94 #[inline]
95 fn eq(&self, other: &Self) -> bool {
96 self.as_array() == other.as_array()
97 }
98}
99
100impl<T: SimdElement, const N: usize> crate::fmt::Debug for Simd<T, N> {
101 #[inline]
102 fn fmt(&self, f: &mut crate::fmt::Formatter<'_>) -> crate::fmt::Result {
103 debug_simd_finish(f, "Simd", self.as_array())
104 }
105}
106
107impl<T: SimdElement> Simd<T, 1> {
108 #[inline]
109 pub(crate) const fn new(x0: T) -> Self {
110 Self([x0])
111 }
112}
113
114impl<T: SimdElement> Simd<T, 2> {
115 #[inline]
116 pub(crate) const fn new(x0: T, x1: T) -> Self {
117 Self([x0, x1])
118 }
119}
120
121impl<T: SimdElement> Simd<T, 4> {
122 #[inline]
123 pub(crate) const fn new(x0: T, x1: T, x2: T, x3: T) -> Self {
124 Self([x0, x1, x2, x3])
125 }
126}
127
128impl<T: SimdElement> Simd<T, 8> {
129 #[inline]
130 pub(crate) const fn new(x0: T, x1: T, x2: T, x3: T, x4: T, x5: T, x6: T, x7: T) -> Self {
131 Self([x0, x1, x2, x3, x4, x5, x6, x7])
132 }
133}
134
135impl<T: SimdElement> Simd<T, 16> {
136 #[inline]
137 pub(crate) const fn new(
138 x0: T,
139 x1: T,
140 x2: T,
141 x3: T,
142 x4: T,
143 x5: T,
144 x6: T,
145 x7: T,
146 x8: T,
147 x9: T,
148 x10: T,
149 x11: T,
150 x12: T,
151 x13: T,
152 x14: T,
153 x15: T,
154 ) -> Self {
155 Self([
156 x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15,
157 ])
158 }
159}
160
161impl<T: SimdElement> Simd<T, 32> {
162 #[inline]
163 pub(crate) const fn new(
164 x0: T,
165 x1: T,
166 x2: T,
167 x3: T,
168 x4: T,
169 x5: T,
170 x6: T,
171 x7: T,
172 x8: T,
173 x9: T,
174 x10: T,
175 x11: T,
176 x12: T,
177 x13: T,
178 x14: T,
179 x15: T,
180 x16: T,
181 x17: T,
182 x18: T,
183 x19: T,
184 x20: T,
185 x21: T,
186 x22: T,
187 x23: T,
188 x24: T,
189 x25: T,
190 x26: T,
191 x27: T,
192 x28: T,
193 x29: T,
194 x30: T,
195 x31: T,
196 ) -> Self {
197 Self([
198 x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18,
199 x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31,
200 ])
201 }
202}
203
204impl<const N: usize> Simd<f16, N> {
205 #[inline]
206 pub(crate) const fn to_bits(self) -> Simd<u16, N> {
207 assert!(size_of::<Self>() == size_of::<Simd<u16, N>>());
208 unsafe { crate::mem::transmute_copy(&self) }
209 }
210
211 #[inline]
212 pub(crate) const fn from_bits(bits: Simd<u16, N>) -> Self {
213 assert!(size_of::<Self>() == size_of::<Simd<u16, N>>());
214 unsafe { crate::mem::transmute_copy(&bits) }
215 }
216}
217
218impl<const N: usize> Simd<f32, N> {
219 #[inline]
220 pub(crate) const fn to_bits(self) -> Simd<u32, N> {
221 assert!(size_of::<Self>() == size_of::<Simd<u32, N>>());
222 unsafe { crate::mem::transmute_copy(&self) }
223 }
224
225 #[inline]
226 pub(crate) const fn from_bits(bits: Simd<u32, N>) -> Self {
227 assert!(size_of::<Self>() == size_of::<Simd<u32, N>>());
228 unsafe { crate::mem::transmute_copy(&bits) }
229 }
230}
231
232impl<const N: usize> Simd<f64, N> {
233 #[inline]
234 pub(crate) const fn to_bits(self) -> Simd<u64, N> {
235 assert!(size_of::<Self>() == size_of::<Simd<u64, N>>());
236 unsafe { crate::mem::transmute_copy(&self) }
237 }
238
239 #[inline]
240 pub(crate) const fn from_bits(bits: Simd<u64, N>) -> Self {
241 assert!(size_of::<Self>() == size_of::<Simd<u64, N>>());
242 unsafe { crate::mem::transmute_copy(&bits) }
243 }
244}
245
246#[repr(simd)]
247#[derive(Copy)]
248pub(crate) struct SimdM<T: SimdElement, const N: usize>([T; N]);
249
250impl<T: SimdElement, const N: usize> SimdM<T, N> {
251 #[inline(always)]
252 const fn bool_to_internal(x: bool) -> T {
253 let ones = const {
255 let mut r = crate::mem::MaybeUninit::<T>::uninit();
258 let mut i = 0;
259 while i < crate::mem::size_of::<T>() {
260 r.as_bytes_mut()[i] = crate::mem::MaybeUninit::new(0xFF);
261 i += 1;
262 }
263 unsafe { r.assume_init() }
264 };
265 [T::ZERO, ones][x as usize]
266 }
267
268 #[inline]
269 pub(crate) const fn from_array(elements: [bool; N]) -> Self {
270 let mut internal = [T::ZERO; N];
271 let mut i = 0;
272 while i < N {
273 internal[i] = Self::bool_to_internal(elements[i]);
274 i += 1;
275 }
276 Self(internal)
277 }
278
279 #[inline]
280 #[rustc_const_unstable(feature = "stdarch_const_helpers", issue = "none")]
281 pub(crate) const fn splat(value: bool) -> Self {
282 unsafe { crate::intrinsics::simd::simd_splat(Self::bool_to_internal(value)) }
283 }
284
285 #[inline]
286 pub(crate) const fn as_array(&self) -> &[T; N] {
287 let simd_ptr: *const Self = self;
288 let array_ptr: *const [T; N] = simd_ptr.cast();
289 unsafe { &*array_ptr }
293 }
294}
295
296impl<T: SimdElement, const N: usize> Clone for SimdM<T, N> {
298 #[inline]
299 fn clone(&self) -> Self {
300 *self
301 }
302}
303
304#[rustc_const_unstable(feature = "stdarch_const_helpers", issue = "none")]
305#[rustfmt::skip] const impl<T: SimdElement, const N: usize> crate::cmp::PartialEq for SimdM<T, N> {
307 #[inline]
308 fn eq(&self, other: &Self) -> bool {
309 self.as_array() == other.as_array()
310 }
311}
312
313impl<T: SimdElement, const N: usize> crate::fmt::Debug for SimdM<T, N> {
314 #[inline]
315 fn fmt(&self, f: &mut crate::fmt::Formatter<'_>) -> crate::fmt::Result {
316 debug_simd_finish(f, "SimdM", self.as_array())
317 }
318}
319
320pub(crate) type u8x2 = Simd<u8, 2>;
323pub(crate) type i8x2 = Simd<i8, 2>;
324
325pub(crate) type u8x4 = Simd<u8, 4>;
328pub(crate) type u16x2 = Simd<u16, 2>;
329
330pub(crate) type i8x4 = Simd<i8, 4>;
331pub(crate) type i16x2 = Simd<i16, 2>;
332
333pub(crate) type u8x8 = Simd<u8, 8>;
336pub(crate) type u16x4 = Simd<u16, 4>;
337pub(crate) type u32x2 = Simd<u32, 2>;
338pub(crate) type u64x1 = Simd<u64, 1>;
339
340pub(crate) type i8x8 = Simd<i8, 8>;
341pub(crate) type i16x4 = Simd<i16, 4>;
342pub(crate) type i32x2 = Simd<i32, 2>;
343pub(crate) type i64x1 = Simd<i64, 1>;
344
345pub(crate) type f16x4 = Simd<f16, 4>;
346pub(crate) type f32x2 = Simd<f32, 2>;
347pub(crate) type f64x1 = Simd<f64, 1>;
348
349pub(crate) type u8x16 = Simd<u8, 16>;
352pub(crate) type u16x8 = Simd<u16, 8>;
353pub(crate) type u32x4 = Simd<u32, 4>;
354pub(crate) type u64x2 = Simd<u64, 2>;
355
356pub(crate) type i8x16 = Simd<i8, 16>;
357pub(crate) type i16x8 = Simd<i16, 8>;
358pub(crate) type i32x4 = Simd<i32, 4>;
359pub(crate) type i64x2 = Simd<i64, 2>;
360
361pub(crate) type f16x8 = Simd<f16, 8>;
362pub(crate) type f32x4 = Simd<f32, 4>;
363pub(crate) type f64x2 = Simd<f64, 2>;
364
365pub(crate) type m8x16 = SimdM<i8, 16>;
366pub(crate) type m16x8 = SimdM<i16, 8>;
367pub(crate) type m32x4 = SimdM<i32, 4>;
368pub(crate) type m64x2 = SimdM<i64, 2>;
369
370pub(crate) type u8x32 = Simd<u8, 32>;
373pub(crate) type u16x16 = Simd<u16, 16>;
374pub(crate) type u32x8 = Simd<u32, 8>;
375pub(crate) type u64x4 = Simd<u64, 4>;
376pub(crate) type u128x2 = Simd<u128, 2>;
377
378pub(crate) type i8x32 = Simd<i8, 32>;
379pub(crate) type i16x16 = Simd<i16, 16>;
380pub(crate) type i32x8 = Simd<i32, 8>;
381pub(crate) type i64x4 = Simd<i64, 4>;
382pub(crate) type i128x2 = Simd<i128, 2>;
383
384pub(crate) type f16x16 = Simd<f16, 16>;
385pub(crate) type f32x8 = Simd<f32, 8>;
386pub(crate) type f64x4 = Simd<f64, 4>;
387
388pub(crate) type m8x32 = SimdM<i8, 32>;
389pub(crate) type m16x16 = SimdM<i16, 16>;
390pub(crate) type m32x8 = SimdM<i32, 8>;
391
392pub(crate) type u8x64 = Simd<u8, 64>;
395pub(crate) type u16x32 = Simd<u16, 32>;
396pub(crate) type u32x16 = Simd<u32, 16>;
397pub(crate) type u64x8 = Simd<u64, 8>;
398pub(crate) type u128x4 = Simd<u128, 4>;
399
400pub(crate) type i8x64 = Simd<i8, 64>;
401pub(crate) type i16x32 = Simd<i16, 32>;
402pub(crate) type i32x16 = Simd<i32, 16>;
403pub(crate) type i64x8 = Simd<i64, 8>;
404pub(crate) type i128x4 = Simd<i128, 4>;
405
406pub(crate) type f16x32 = Simd<f16, 32>;
407pub(crate) type f32x16 = Simd<f32, 16>;
408pub(crate) type f64x8 = Simd<f64, 8>;
409
410pub(crate) type u16x64 = Simd<u16, 64>;
413pub(crate) type u32x32 = Simd<u32, 32>;
414
415pub(crate) type i32x32 = Simd<i32, 32>;
416
417#[inline]
420pub(crate) fn debug_simd_finish<T: crate::fmt::Debug, const N: usize>(
421 formatter: &mut crate::fmt::Formatter<'_>,
422 type_name: &str,
423 array: &[T; N],
424) -> crate::fmt::Result {
425 crate::fmt::Formatter::debug_tuple_fields_finish(
426 formatter,
427 type_name,
428 &crate::array::from_fn::<&dyn crate::fmt::Debug, N, _>(|i| &array[i]),
429 )
430}