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