1use std::iter::FusedIterator;
2use std::ops::Range;
3use std::ptr::{slice_from_raw_parts, slice_from_raw_parts_mut};
4use imgref::Img;
5use crate::iter::{IterPtr, IterPtrMut, SimdIterPtr, SimdIterPtrMut};
6use crate::{slice_ptr_len, slice_ptr_len_mut};
7
8#[derive(Clone, Eq, PartialEq, Debug)]
9pub struct SimdIterWindowsPtr<T, const LANES: usize>(*const [T], usize, usize, Range<usize>);
10
11unsafe impl<T: Sync, const LANES: usize> Send for SimdIterWindowsPtr<T, LANES> {}
12
13unsafe impl<T, const LANES: usize> Sync for SimdIterWindowsPtr<T, LANES> {}
14
15impl<T, const LANES: usize> SimdIterWindowsPtr<T, LANES> {
16 #[inline]
47 pub unsafe fn new(slice: *const [T], slice_stride: usize, iter_stride: usize, len: usize) -> Self {
48 assert!(IterPtr::is_slice_perfect(slice_ptr_len(slice), slice_stride));
49 Self::new_unchecked(slice, slice_stride, iter_stride, len)
50 }
51
52 #[inline]
59 pub unsafe fn new_unchecked(slice: *const [T], slice_stride: usize, iter_stride: usize, len: usize) -> Self {
60 Self(slice, slice_stride, iter_stride, 0..len)
61 }
62
63 #[inline]
74 pub unsafe fn rows<S: AsRef<[T]>>(buf: &Img<S>) -> Self {
75 let (width, height, stride) = (buf.width(), buf.height(), buf.stride());
76 let buf = buf.buf().as_ref() as *const [T];
77 Self::rows_ptr(Img::new_stride(buf, width, height, stride))
78 }
79
80 #[inline]
91 pub unsafe fn rows_ptr(buf: Img<*const [T]>) -> Self {
92 IterPtr::assert_slice_enough(buf);
93 let (width, height, stride) = (buf.width(), buf.height(), buf.stride());
94 let first_row = slice_from_raw_parts(buf.buf().cast::<T>(), width);
95 Self::new_unchecked(first_row, 1, stride, height)
96 }
97
98 #[inline]
109 pub unsafe fn cols<S: AsRef<[T]>>(buf: &Img<S>) -> Self {
110 let (width, height, stride) = (buf.width(), buf.height(), buf.stride());
111 let buf = buf.buf().as_ref() as *const [T];
112 Self::cols_ptr(Img::new_stride(buf, width, height, stride))
113 }
114
115 #[inline]
126 pub unsafe fn cols_ptr(buf: Img<*const [T]>) -> Self {
127 IterPtr::assert_slice_enough(buf);
128 let (width, height, stride) = (buf.width(), buf.height(), buf.stride());
129 let first_col = slice_from_raw_parts(buf.buf().cast::<T>(), stride * (height - 1) + 1);
130 Self::new_unchecked(first_col, buf.stride(), 1, width)
131 }
132
133 #[inline]
134 unsafe fn window(&self, offset: usize) -> *const [T] {
135 let data = self.0.cast::<T>().add(offset);
136 let len = slice_ptr_len(self.0);
137 slice_from_raw_parts(data, len)
138 }
139}
140
141#[derive(Copy, Clone, Eq, PartialEq, Debug)]
142pub enum SimdIterWindowPtr<T, const LANES: usize> {
143 Simd(SimdIterPtr<T, LANES>),
144 Single(IterPtr<T>)
145}
146
147impl<T, const LANES: usize> Iterator for SimdIterWindowsPtr<T, LANES> {
148 type Item = SimdIterWindowPtr<T, LANES>;
149
150 #[inline]
151 fn next(&mut self) -> Option<Self::Item> {
152 let (simd, index) = if self.3.len() >= LANES {
153 let index = self.3.next().unwrap();
154 for _ in 0..LANES - 1 { self.3.next().unwrap(); }
155 (true, index)
156 } else {
157 (false, self.3.next()?)
158 };
159
160 let iter = unsafe { IterPtr::new(self.window(index * self.2), self.1) };
161
162 Some(if simd {
163 SimdIterWindowPtr::Simd(unsafe { SimdIterPtr::new(iter, self.2) })
164 } else {
165 SimdIterWindowPtr::Single(iter)
166 })
167 }
168
169 #[inline]
170 fn size_hint(&self) -> (usize, Option<usize>) {
171 let len = self.len();
172 (len, Some(len))
173 }
174}
175
176impl<T, const LANES: usize> DoubleEndedIterator for SimdIterWindowsPtr<T, LANES> {
177 #[inline]
178 fn next_back(&mut self) -> Option<Self::Item> {
179 let (simd, index) = if self.3.len() >= LANES {
180 (true, self.3.nth_back(LANES - 1).unwrap())
181 } else {
182 (false, self.3.next_back()?)
183 };
184
185 let iter = unsafe { IterPtr::new(self.window(index * self.2), self.1) };
186
187 Some(if simd {
188 SimdIterWindowPtr::Simd(unsafe { SimdIterPtr::new(iter, self.2) })
189 } else {
190 SimdIterWindowPtr::Single(iter)
191 })
192 }
193}
194
195impl<T, const LANES: usize> ExactSizeIterator for SimdIterWindowsPtr<T, LANES> {
196 #[inline]
197 fn len(&self) -> usize {
198 self.3.len() / LANES + self.3.len() % LANES
199 }
200}
201
202impl<T, const LANES: usize> FusedIterator for SimdIterWindowsPtr<T, LANES> {}
203
204
205#[derive(Clone, Eq, PartialEq, Debug)]
206pub struct SimdIterWindowsPtrMut<T, const LANES: usize>(*mut [T], usize, usize, Range<usize>);
207
208unsafe impl<T: Sync, const LANES: usize> Send for SimdIterWindowsPtrMut<T, LANES> {}
209
210unsafe impl<T, const LANES: usize> Sync for SimdIterWindowsPtrMut<T, LANES> {}
211
212impl<T, const LANES: usize> SimdIterWindowsPtrMut<T, LANES> {
213 #[inline]
244 pub unsafe fn new(slice: *mut [T], slice_stride: usize, iter_stride: usize, len: usize) -> Self {
245 assert!(IterPtr::is_slice_perfect(slice_ptr_len_mut(slice), slice_stride));
246 Self::new_unchecked(slice, slice_stride, iter_stride, len)
247 }
248
249 #[inline]
256 pub unsafe fn new_unchecked(slice: *mut [T], slice_stride: usize, iter_stride: usize, len: usize) -> Self {
257 Self(slice, slice_stride, iter_stride, 0..len)
258 }
259
260 #[inline]
271 pub unsafe fn rows<S: AsMut<[T]>>(buf: &mut Img<S>) -> Self {
272 let (width, height, stride) = (buf.width(), buf.height(), buf.stride());
273 let buf = buf.buf_mut().as_mut() as *mut [T];
274 Self::rows_ptr(Img::new_stride(buf, width, height, stride))
275 }
276
277 #[inline]
288 pub unsafe fn rows_ptr(buf: Img<*mut [T]>) -> Self {
289 IterPtrMut::assert_slice_enough(buf);
290 let (width, height, stride) = (buf.width(), buf.height(), buf.stride());
291 let first_row = slice_from_raw_parts_mut(buf.buf().cast::<T>(), width);
292 Self::new_unchecked(first_row, 1, stride, height)
293 }
294
295 #[inline]
306 pub unsafe fn cols<S: AsMut<[T]>>(buf: &mut Img<S>) -> Self {
307 let (width, height, stride) = (buf.width(), buf.height(), buf.stride());
308 let buf = buf.buf_mut().as_mut() as *mut [T];
309 Self::cols_ptr(Img::new_stride(buf, width, height, stride))
310 }
311
312 #[inline]
323 pub unsafe fn cols_ptr(buf: Img<*mut [T]>) -> Self {
324 IterPtrMut::assert_slice_enough(buf);
325 let (width, height, stride) = (buf.width(), buf.height(), buf.stride());
326 let first_col = slice_from_raw_parts_mut(buf.buf().cast::<T>(), stride * (height - 1) + 1);
327 Self::new_unchecked(first_col, buf.stride(), 1, width)
328 }
329
330 #[inline]
331 unsafe fn window(&self, offset: usize) -> *mut [T] {
332 let data = self.0.cast::<T>().add(offset);
333 let len = slice_ptr_len_mut(self.0);
334 slice_from_raw_parts_mut(data, len)
335 }
336}
337
338#[derive(Copy, Clone, Eq, PartialEq, Debug)]
339pub enum SimdIterWindowPtrMut<T, const LANES: usize> {
340 Simd(SimdIterPtrMut<T, LANES>),
341 Single(IterPtrMut<T>)
342}
343
344impl<T, const LANES: usize> Iterator for SimdIterWindowsPtrMut<T, LANES> {
345 type Item = SimdIterWindowPtrMut<T, LANES>;
346
347 #[inline]
348 fn next(&mut self) -> Option<Self::Item> {
349 let (simd, index) = if self.3.len() >= LANES {
350 let index = self.3.next().unwrap();
351 for _ in 0..LANES - 1 { self.3.next().unwrap(); }
352 (true, index)
353 } else {
354 (false, self.3.next()?)
355 };
356
357 let iter = unsafe { IterPtrMut::new(self.window(index * self.2), self.1) };
358
359 Some(if simd {
360 SimdIterWindowPtrMut::Simd(unsafe { SimdIterPtrMut::new(iter, self.2) })
361 } else {
362 SimdIterWindowPtrMut::Single(iter)
363 })
364 }
365
366 #[inline]
367 fn size_hint(&self) -> (usize, Option<usize>) {
368 let len = self.len();
369 (len, Some(len))
370 }
371}
372
373impl<T, const LANES: usize> DoubleEndedIterator for SimdIterWindowsPtrMut<T, LANES> {
374 #[inline]
375 fn next_back(&mut self) -> Option<Self::Item> {
376 let (simd, index) = if self.3.len() >= LANES {
377 (true, self.3.nth_back(LANES - 1).unwrap())
378 } else {
379 (false, self.3.next_back()?)
380 };
381
382 let iter = unsafe { IterPtrMut::new(self.window(index * self.2), self.1) };
383
384 Some(if simd {
385 SimdIterWindowPtrMut::Simd(unsafe { SimdIterPtrMut::new(iter, self.2) })
386 } else {
387 SimdIterWindowPtrMut::Single(iter)
388 })
389 }
390}
391
392impl<T, const LANES: usize> ExactSizeIterator for SimdIterWindowsPtrMut<T, LANES> {
393 #[inline]
394 fn len(&self) -> usize {
395 self.3.len() / LANES + self.3.len() % LANES
396 }
397}
398
399impl<T, const LANES: usize> FusedIterator for SimdIterWindowsPtrMut<T, LANES> {}