1use std::iter::FusedIterator;
4use std::marker::PhantomData;
5use std::mem;
6
7use crate::base::dimension::{Dim, U1};
8use crate::base::storage::{RawStorage, RawStorageMut};
9use crate::base::{Matrix, MatrixSlice, MatrixSliceMut, Scalar};
10
11macro_rules! iterator {
12 (struct $Name:ident for $Storage:ident.$ptr: ident -> $Ptr:ty, $Ref:ty, $SRef: ty) => {
13 #[derive(Debug)]
15 pub struct $Name<'a, T, R: Dim, C: Dim, S: 'a + $Storage<T, R, C>> {
16 ptr: $Ptr,
17 inner_ptr: $Ptr,
18 inner_end: $Ptr,
19 size: usize, strides: (S::RStride, S::CStride),
21 _phantoms: PhantomData<($Ref, R, C, S)>,
22 }
23
24 impl<'a, T, R: Dim, C: Dim, S: 'a + $Storage<T, R, C>> $Name<'a, T, R, C, S> {
27 pub fn new(storage: $SRef) -> $Name<'a, T, R, C, S> {
29 let shape = storage.shape();
30 let strides = storage.strides();
31 let inner_offset = shape.0.value() * strides.0.value();
32 let size = shape.0.value() * shape.1.value();
33 let ptr = storage.$ptr();
34
35 let inner_end = if size == 0 {
43 ptr
44 } else {
45 unsafe { ptr.add(inner_offset) }
50 };
51
52 $Name {
53 ptr,
54 inner_ptr: ptr,
55 inner_end,
56 size: shape.0.value() * shape.1.value(),
57 strides,
58 _phantoms: PhantomData,
59 }
60 }
61 }
62
63 impl<'a, T, R: Dim, C: Dim, S: 'a + $Storage<T, R, C>> Iterator for $Name<'a, T, R, C, S> {
64 type Item = $Ref;
65
66 #[inline]
67 fn next(&mut self) -> Option<$Ref> {
68 unsafe {
69 if self.size == 0 {
70 None
71 } else {
72 self.size -= 1;
73
74 if self.ptr == self.inner_end {
76 let stride = self.strides.1.value() as isize;
77 self.inner_end = self.ptr.wrapping_offset(stride);
81 self.ptr = self.inner_ptr.offset(stride);
84 self.inner_ptr = self.ptr;
85 }
86
87 let old = self.ptr;
89
90 if self.size != 0 {
95 let stride = self.strides.0.value();
96 self.ptr = self.ptr.add(stride);
97 }
98
99 #[allow(clippy::transmute_ptr_to_ref)]
102 Some(mem::transmute(old))
103 }
104 }
105 }
106
107 #[inline]
108 fn size_hint(&self) -> (usize, Option<usize>) {
109 (self.size, Some(self.size))
110 }
111
112 #[inline]
113 fn count(self) -> usize {
114 self.size_hint().0
115 }
116 }
117
118 impl<'a, T, R: Dim, C: Dim, S: 'a + $Storage<T, R, C>> DoubleEndedIterator
119 for $Name<'a, T, R, C, S>
120 {
121 #[inline]
122 fn next_back(&mut self) -> Option<$Ref> {
123 unsafe {
124 if self.size == 0 {
125 None
126 } else {
127 self.size -= 1;
130
131 let inner_stride = self.strides.0.value();
133 let outer_stride = self.strides.1.value();
134
135 let inner_raw_size = self.inner_end.offset_from(self.inner_ptr) as usize;
138 let inner_size = inner_raw_size / inner_stride;
139
140 let outer_remaining = self.size / inner_size;
142 let inner_remaining = self.size % inner_size;
143
144 let last = self
146 .ptr
147 .add((outer_remaining * outer_stride + inner_remaining * inner_stride));
148
149 #[allow(clippy::transmute_ptr_to_ref)]
152 Some(mem::transmute(last))
153 }
154 }
155 }
156 }
157
158 impl<'a, T, R: Dim, C: Dim, S: 'a + $Storage<T, R, C>> ExactSizeIterator
159 for $Name<'a, T, R, C, S>
160 {
161 #[inline]
162 fn len(&self) -> usize {
163 self.size
164 }
165 }
166
167 impl<'a, T, R: Dim, C: Dim, S: 'a + $Storage<T, R, C>> FusedIterator
168 for $Name<'a, T, R, C, S>
169 {
170 }
171 };
172}
173
174iterator!(struct MatrixIter for RawStorage.ptr -> *const T, &'a T, &'a S);
175iterator!(struct MatrixIterMut for RawStorageMut.ptr_mut -> *mut T, &'a mut T, &'a mut S);
176
177#[derive(Clone, Debug)]
183pub struct RowIter<'a, T, R: Dim, C: Dim, S: RawStorage<T, R, C>> {
185 mat: &'a Matrix<T, R, C, S>,
186 curr: usize,
187}
188
189impl<'a, T, R: Dim, C: Dim, S: 'a + RawStorage<T, R, C>> RowIter<'a, T, R, C, S> {
190 pub(crate) fn new(mat: &'a Matrix<T, R, C, S>) -> Self {
191 RowIter { mat, curr: 0 }
192 }
193}
194
195impl<'a, T, R: Dim, C: Dim, S: 'a + RawStorage<T, R, C>> Iterator for RowIter<'a, T, R, C, S> {
196 type Item = MatrixSlice<'a, T, U1, C, S::RStride, S::CStride>;
197
198 #[inline]
199 fn next(&mut self) -> Option<Self::Item> {
200 if self.curr < self.mat.nrows() {
201 let res = self.mat.row(self.curr);
202 self.curr += 1;
203 Some(res)
204 } else {
205 None
206 }
207 }
208
209 #[inline]
210 fn size_hint(&self) -> (usize, Option<usize>) {
211 (
212 self.mat.nrows() - self.curr,
213 Some(self.mat.nrows() - self.curr),
214 )
215 }
216
217 #[inline]
218 fn count(self) -> usize {
219 self.mat.nrows() - self.curr
220 }
221}
222
223impl<'a, T: Scalar, R: Dim, C: Dim, S: 'a + RawStorage<T, R, C>> ExactSizeIterator
224 for RowIter<'a, T, R, C, S>
225{
226 #[inline]
227 fn len(&self) -> usize {
228 self.mat.nrows() - self.curr
229 }
230}
231
232#[derive(Debug)]
234pub struct RowIterMut<'a, T, R: Dim, C: Dim, S: RawStorageMut<T, R, C>> {
235 mat: *mut Matrix<T, R, C, S>,
236 curr: usize,
237 phantom: PhantomData<&'a mut Matrix<T, R, C, S>>,
238}
239
240impl<'a, T, R: Dim, C: Dim, S: 'a + RawStorageMut<T, R, C>> RowIterMut<'a, T, R, C, S> {
241 pub(crate) fn new(mat: &'a mut Matrix<T, R, C, S>) -> Self {
242 RowIterMut {
243 mat,
244 curr: 0,
245 phantom: PhantomData,
246 }
247 }
248
249 fn nrows(&self) -> usize {
250 unsafe { (*self.mat).nrows() }
251 }
252}
253
254impl<'a, T, R: Dim, C: Dim, S: 'a + RawStorageMut<T, R, C>> Iterator
255 for RowIterMut<'a, T, R, C, S>
256{
257 type Item = MatrixSliceMut<'a, T, U1, C, S::RStride, S::CStride>;
258
259 #[inline]
260 fn next(&mut self) -> Option<Self::Item> {
261 if self.curr < self.nrows() {
262 let res = unsafe { (*self.mat).row_mut(self.curr) };
263 self.curr += 1;
264 Some(res)
265 } else {
266 None
267 }
268 }
269
270 #[inline]
271 fn size_hint(&self) -> (usize, Option<usize>) {
272 (self.nrows() - self.curr, Some(self.nrows() - self.curr))
273 }
274
275 #[inline]
276 fn count(self) -> usize {
277 self.nrows() - self.curr
278 }
279}
280
281impl<'a, T: Scalar, R: Dim, C: Dim, S: 'a + RawStorageMut<T, R, C>> ExactSizeIterator
282 for RowIterMut<'a, T, R, C, S>
283{
284 #[inline]
285 fn len(&self) -> usize {
286 self.nrows() - self.curr
287 }
288}
289
290#[derive(Clone, Debug)]
296pub struct ColumnIter<'a, T, R: Dim, C: Dim, S: RawStorage<T, R, C>> {
298 mat: &'a Matrix<T, R, C, S>,
299 curr: usize,
300}
301
302impl<'a, T, R: Dim, C: Dim, S: 'a + RawStorage<T, R, C>> ColumnIter<'a, T, R, C, S> {
303 pub(crate) fn new(mat: &'a Matrix<T, R, C, S>) -> Self {
304 ColumnIter { mat, curr: 0 }
305 }
306}
307
308impl<'a, T, R: Dim, C: Dim, S: 'a + RawStorage<T, R, C>> Iterator for ColumnIter<'a, T, R, C, S> {
309 type Item = MatrixSlice<'a, T, R, U1, S::RStride, S::CStride>;
310
311 #[inline]
312 fn next(&mut self) -> Option<Self::Item> {
313 if self.curr < self.mat.ncols() {
314 let res = self.mat.column(self.curr);
315 self.curr += 1;
316 Some(res)
317 } else {
318 None
319 }
320 }
321
322 #[inline]
323 fn size_hint(&self) -> (usize, Option<usize>) {
324 (
325 self.mat.ncols() - self.curr,
326 Some(self.mat.ncols() - self.curr),
327 )
328 }
329
330 #[inline]
331 fn count(self) -> usize {
332 self.mat.ncols() - self.curr
333 }
334}
335
336impl<'a, T: Scalar, R: Dim, C: Dim, S: 'a + RawStorage<T, R, C>> ExactSizeIterator
337 for ColumnIter<'a, T, R, C, S>
338{
339 #[inline]
340 fn len(&self) -> usize {
341 self.mat.ncols() - self.curr
342 }
343}
344
345#[derive(Debug)]
347pub struct ColumnIterMut<'a, T, R: Dim, C: Dim, S: RawStorageMut<T, R, C>> {
348 mat: *mut Matrix<T, R, C, S>,
349 curr: usize,
350 phantom: PhantomData<&'a mut Matrix<T, R, C, S>>,
351}
352
353impl<'a, T, R: Dim, C: Dim, S: 'a + RawStorageMut<T, R, C>> ColumnIterMut<'a, T, R, C, S> {
354 pub(crate) fn new(mat: &'a mut Matrix<T, R, C, S>) -> Self {
355 ColumnIterMut {
356 mat,
357 curr: 0,
358 phantom: PhantomData,
359 }
360 }
361
362 fn ncols(&self) -> usize {
363 unsafe { (*self.mat).ncols() }
364 }
365}
366
367impl<'a, T, R: Dim, C: Dim, S: 'a + RawStorageMut<T, R, C>> Iterator
368 for ColumnIterMut<'a, T, R, C, S>
369{
370 type Item = MatrixSliceMut<'a, T, R, U1, S::RStride, S::CStride>;
371
372 #[inline]
373 fn next(&mut self) -> Option<Self::Item> {
374 if self.curr < self.ncols() {
375 let res = unsafe { (*self.mat).column_mut(self.curr) };
376 self.curr += 1;
377 Some(res)
378 } else {
379 None
380 }
381 }
382
383 #[inline]
384 fn size_hint(&self) -> (usize, Option<usize>) {
385 (self.ncols() - self.curr, Some(self.ncols() - self.curr))
386 }
387
388 #[inline]
389 fn count(self) -> usize {
390 self.ncols() - self.curr
391 }
392}
393
394impl<'a, T: Scalar, R: Dim, C: Dim, S: 'a + RawStorageMut<T, R, C>> ExactSizeIterator
395 for ColumnIterMut<'a, T, R, C, S>
396{
397 #[inline]
398 fn len(&self) -> usize {
399 self.ncols() - self.curr
400 }
401}