1use crate::arch::Token;
4use crate::{
5 scalar::Scalar,
6 vector::{width, Native, NativeWidth, Vector},
7};
8use core::marker::PhantomData;
9
10pub trait Slice<Token, Width>
12where
13 Token: crate::arch::Token,
14 Width: width::Width,
15{
16 type Vector: Vector<Token = Token, Width = Width>;
17
18 unsafe fn read_unchecked(&self, token: Token) -> Self::Vector;
23
24 fn read(&self, token: Token) -> Self::Vector;
28
29 #[allow(clippy::type_complexity)]
33 fn align(
34 &self,
35 #[allow(unused_variables)] token: Token,
36 ) -> (
37 &[<Self::Vector as Vector>::Scalar],
38 &[Self::Vector],
39 &[<Self::Vector as Vector>::Scalar],
40 );
41
42 #[allow(clippy::type_complexity)]
46 fn align_mut(
47 &mut self,
48 #[allow(unused_variables)] token: Token,
49 ) -> (
50 &mut [<Self::Vector as Vector>::Scalar],
51 &mut [Self::Vector],
52 &mut [<Self::Vector as Vector>::Scalar],
53 );
54
55 fn overlapping(&self, token: Token) -> Overlapping<'_, Self::Vector>;
57
58 fn overlapping_mut(&mut self, token: Token) -> OverlappingMut<'_, Self::Vector>;
60}
61
62impl<T, Token, Width> Slice<Token, Width> for [T]
63where
64 T: Scalar<Token, Width>,
65 Token: crate::arch::Token,
66 Width: width::Width,
67{
68 type Vector = T::Vector;
69
70 #[inline]
71 unsafe fn read_unchecked(&self, token: Token) -> Self::Vector {
72 Self::Vector::read_unchecked(token, self)
73 }
74
75 #[inline]
76 fn read(&self, token: Token) -> Self::Vector {
77 Self::Vector::read(token, self)
78 }
79
80 #[allow(clippy::type_complexity)]
81 #[inline]
82 fn align(
83 &self,
84 #[allow(unused_variables)] token: Token,
85 ) -> (
86 &[<Self::Vector as Vector>::Scalar],
87 &[Self::Vector],
88 &[<Self::Vector as Vector>::Scalar],
89 ) {
90 unsafe { self.align_to() }
91 }
92
93 #[allow(clippy::type_complexity)]
94 #[inline]
95 fn align_mut(
96 &mut self,
97 #[allow(unused_variables)] token: Token,
98 ) -> (
99 &mut [<Self::Vector as Vector>::Scalar],
100 &mut [Self::Vector],
101 &mut [<Self::Vector as Vector>::Scalar],
102 ) {
103 unsafe { self.align_to_mut() }
104 }
105
106 #[inline]
107 fn overlapping(&self, token: Token) -> Overlapping<'_, Self::Vector> {
108 Overlapping::new(token, self)
109 }
110
111 #[inline]
112 fn overlapping_mut(&mut self, token: Token) -> OverlappingMut<'_, Self::Vector> {
113 OverlappingMut::new(token, self)
114 }
115}
116
117macro_rules! slice_impl {
118 {
119 $width:literal,
120 $width_type:ty,
121 $read_unchecked:ident,
122 $read:ident,
123 $align:ident,
124 $align_mut:ident,
125 $overlapping:ident,
126 $overlapping_mut:ident
127 } => {
128 #[doc = "Read a vector with "]
129 #[doc = $width]
130 #[doc = " from a slice without checking the length.\n\nSee [`read_unchecked`](../vector/trait.Vector.html#method.read_ptr)."]
131 #[inline]
132 unsafe fn $read_unchecked(&self, token: Token) -> <Self as Slice<Token, $width_type>>::Vector {
133 <Self as Slice<Token, $width_type>>::read_unchecked(self, token)
134 }
135
136 #[doc = "Read a vector with "]
137 #[doc = $width]
138 #[doc = " from a slice.\n\nSee [`read`](../vector/trait.Vector.html#method.read)."]
139 #[inline]
140 fn $read(&self, token: Token) -> <Self as Slice<Token, $width_type>>::Vector {
141 <Self as Slice<Token, $width_type>>::read(self, token)
142 }
143
144 #[doc = "Align a slice of scalars to vectors with "]
145 #[doc = $width]
146 #[doc = ".\n\nSee [`align`](trait.Slice.html#tymethod.align)."]
147 #[allow(clippy::type_complexity)]
148 #[inline]
149 fn $align(&self, token: Token) ->
150 (
151 &[<<Self as Slice<Token, $width_type>>::Vector as Vector>::Scalar],
152 &[<Self as Slice<Token, $width_type>>::Vector],
153 &[<<Self as Slice<Token, $width_type>>::Vector as Vector>::Scalar],
154 ) {
155 <Self as Slice<Token, $width_type>>::align(self, token)
156 }
157
158 #[doc = "Align a slice of scalars to vectors with "]
159 #[doc = $width]
160 #[doc = ".\n\nSee [`align_mut`](trait.Slice.html#tymethod.align_mut)."]
161 #[allow(clippy::type_complexity)]
162 #[inline]
163 fn $align_mut(&mut self, token: Token) ->
164 (
165 &mut [<<Self as Slice<Token, $width_type>>::Vector as Vector>::Scalar],
166 &mut [<Self as Slice<Token, $width_type>>::Vector],
167 &mut [<<Self as Slice<Token, $width_type>>::Vector as Vector>::Scalar],
168 ){
169 <Self as Slice<Token, $width_type>>::align_mut(self, token)
170 }
171
172 #[doc = "Create a slice of overlapping vectors of "]
173 #[doc = $width]
174 #[doc = "from a slice of scalars.\n\nSee [`overlapping`](trait.Slice.html#tymethod.overlapping)."]
175 #[inline]
176 fn $overlapping(&self, token: Token) -> Overlapping<'_, <Self as Slice<Token, $width_type>>::Vector> {
177 <Self as Slice<Token, $width_type>>::overlapping(self, token)
178 }
179
180 #[doc = "Create a mutable slice of overlapping vectors of "]
181 #[doc = $width]
182 #[doc = "from a slice of scalars.\n\nSee [`overlapping_mut`](trait.Slice.html#tymethod.overlapping_mut)."]
183 #[inline]
184 fn $overlapping_mut(
185 &mut self,
186 token: Token,
187 ) -> OverlappingMut<'_, <Self as Slice<Token, $width_type>>::Vector> {
188 <Self as Slice<Token, $width_type>>::overlapping_mut(self, token)
189 }
190 }
191}
192
193impl<T, Token> Native<Token> for [T]
194where
195 T: Native<Token>,
196{
197 type Width = T::Width;
198}
199
200pub trait SliceExt<Token>:
202 Native<Token>
203 + Slice<Token, width::W1>
204 + Slice<Token, width::W2>
205 + Slice<Token, width::W4>
206 + Slice<Token, width::W8>
207 + Slice<Token, NativeWidth<Self, Token>>
208where
209 Token: crate::arch::Token,
210{
211 slice_impl! { "the native number of lanes", <Self as Native<Token>>::Width, read_unchecked_native, read_native, align_native, align_native_mut, overlapping_native, overlapping_native_mut }
212 slice_impl! { "1 lane", width::W1, read_unchecked1, read1, align1, align1_mut, overlapping1, overlapping1_mut }
213 slice_impl! { "2 lanes", width::W2, read_unchecked2, read2, align2, align2_mut, overlapping2, overlapping2_mut }
214 slice_impl! { "4 lanes", width::W4, read_unchecked4, read4, align4, align4_mut, overlapping4, overlapping4_mut }
215 slice_impl! { "8 lanes", width::W8, read_unchecked8, read8, align8, align8_mut, overlapping8, overlapping8_mut }
216}
217
218impl<T, Token> SliceExt<Token> for T
219where
220 T: ?Sized
221 + Native<Token>
222 + Slice<Token, width::W1>
223 + Slice<Token, width::W2>
224 + Slice<Token, width::W4>
225 + Slice<Token, width::W8>
226 + Slice<Token, NativeWidth<Self, Token>>,
227 Token: crate::arch::Token,
228{
229}
230
231pub struct RefMut<'a, V>
233where
234 V: Vector,
235{
236 source: *mut V::Scalar,
237 temp: V,
238 lifetime: PhantomData<&'a V::Scalar>,
239}
240
241impl<'a, V> RefMut<'a, V>
242where
243 V: Vector,
244{
245 #[inline]
246 fn new(token: V::Token, source: *mut V::Scalar) -> Self {
247 Self {
248 source,
249 temp: V::zeroed(token),
250 lifetime: PhantomData,
251 }
252 }
253}
254
255impl<'a, V> core::ops::Deref for RefMut<'a, V>
256where
257 V: Vector,
258{
259 type Target = V;
260
261 #[inline]
262 fn deref(&self) -> &V {
263 &self.temp
264 }
265}
266
267impl<'a, V> core::ops::DerefMut for RefMut<'a, V>
268where
269 V: Vector,
270{
271 #[inline]
272 fn deref_mut(&mut self) -> &mut V {
273 &mut self.temp
274 }
275}
276
277impl<'a, V> core::ops::Drop for RefMut<'a, V>
278where
279 V: Vector,
280{
281 #[inline]
282 fn drop(&mut self) {
283 unsafe {
284 self.temp.write_ptr(self.source);
285 }
286 }
287}
288
289pub struct Overlapping<'a, V>
291where
292 V: Vector,
293{
294 slice: &'a [V::Scalar],
295 phantom: PhantomData<V>,
296}
297
298#[allow(clippy::len_without_is_empty)]
299impl<'a, V> Overlapping<'a, V>
300where
301 V: Vector,
302{
303 #[inline]
305 pub fn new(
306 #[allow(unused_variables)] token: impl Into<V::Token>,
307 slice: &'a [V::Scalar],
308 ) -> Self {
309 assert!(
310 slice.len() >= V::width(),
311 "slice must be at least as wide as the vector"
312 );
313 Self {
314 slice,
315 phantom: PhantomData,
316 }
317 }
318
319 #[inline]
323 pub fn len(&self) -> usize {
324 self.slice.len() - V::width() + 1
325 }
326
327 #[inline]
329 pub fn get(&self, index: usize) -> Option<V> {
330 if index < self.len() {
331 Some(unsafe { self.get_unchecked(index) })
332 } else {
333 None
334 }
335 }
336
337 #[inline]
343 pub unsafe fn get_unchecked(&self, index: usize) -> V
344 where
345 V: Vector,
346 {
347 V::read_ptr(V::Token::new_unchecked(), self.slice.as_ptr().add(index))
348 }
349}
350
351pub struct OverlappingMut<'a, V>
353where
354 V: Vector,
355{
356 slice: &'a mut [V::Scalar],
357 phantom: PhantomData<V>,
358}
359
360#[allow(clippy::len_without_is_empty)]
361impl<'a, V> OverlappingMut<'a, V>
362where
363 V: Vector,
364{
365 #[inline]
367 pub fn new(
368 #[allow(unused_variables)] token: impl Into<V::Token>,
369 slice: &'a mut [V::Scalar],
370 ) -> Self {
371 assert!(
372 slice.len() >= V::width(),
373 "slice must be at least as wide as the vector"
374 );
375 Self {
376 slice,
377 phantom: PhantomData,
378 }
379 }
380
381 #[inline]
385 pub fn len(&self) -> usize {
386 self.slice.len() - V::width() + 1
387 }
388
389 #[inline]
391 pub fn get(&self, index: usize) -> Option<V> {
392 if index < self.len() {
393 Some(unsafe { self.get_unchecked(index) })
394 } else {
395 None
396 }
397 }
398
399 #[inline]
405 pub unsafe fn get_unchecked(&self, index: usize) -> V {
406 V::read_ptr(V::Token::new_unchecked(), self.slice.as_ptr().add(index))
407 }
408
409 #[inline]
411 pub fn get_mut(&'a mut self, index: usize) -> Option<RefMut<'a, V>> {
412 if index < self.len() {
413 Some(unsafe { self.get_unchecked_mut(index) })
414 } else {
415 None
416 }
417 }
418
419 #[inline]
425 pub unsafe fn get_unchecked_mut(&'a mut self, index: usize) -> RefMut<'a, V> {
426 RefMut::new(
427 V::Token::new_unchecked(),
428 self.slice.as_mut_ptr().add(index),
429 )
430 }
431}