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