From 267eb01fe58ac0693bb2f0fe59e79fab0fa52302 Mon Sep 17 00:00:00 2001 From: Linus Behrbohm Date: Mon, 22 Feb 2021 00:47:33 +0100 Subject: [PATCH] Initial draft for into_row_iter and into_column_iter https://github.com/dimforge/nalgebra/issues/834 --- src/base/allocator.rs | 2 +- src/base/array_storage.rs | 14 +++++ src/base/conversion.rs | 13 ++++- src/base/iter.rs | 114 +++++++++++++++++++++++++++++++++++++- src/base/matrix.rs | 45 ++++++++++++++- src/base/vec_storage.rs | 12 ++++ 6 files changed, 192 insertions(+), 8 deletions(-) diff --git a/src/base/allocator.rs b/src/base/allocator.rs index ebd55553..d2ef3bc0 100644 --- a/src/base/allocator.rs +++ b/src/base/allocator.rs @@ -18,7 +18,7 @@ use crate::base::{DefaultAllocator, Scalar}; /// same `Buffer` type. pub trait Allocator: Any + Sized { /// The type of buffer this allocator can instanciate. - type Buffer: ContiguousStorageMut + Clone; + type Buffer: ContiguousStorageMut + Clone + IntoIterator; /// Allocates a buffer with the given number of rows and columns without initializing its content. unsafe fn allocate_uninitialized(nrows: R, ncols: C) -> Self::Buffer; diff --git a/src/base/array_storage.rs b/src/base/array_storage.rs index 4fdd3e73..302ba175 100644 --- a/src/base/array_storage.rs +++ b/src/base/array_storage.rs @@ -46,6 +46,20 @@ where data: GenericArray>, } +impl IntoIterator for ArrayStorage +where + R: DimName, + C: DimName, + R::Value: Mul, + Prod: ArrayLength, +{ + type Item = N; + type IntoIter = > as IntoIterator>::IntoIter; + fn into_iter(self) -> Self::IntoIter { + self.data.into_iter() + } +} + #[deprecated(note = "renamed to `ArrayStorage`")] /// Renamed to [ArrayStorage]. pub type MatrixArray = ArrayStorage; diff --git a/src/base/conversion.rs b/src/base/conversion.rs index 77bf4005..db949c13 100644 --- a/src/base/conversion.rs +++ b/src/base/conversion.rs @@ -21,7 +21,7 @@ use crate::base::dimension::{ Dim, DimName, U1, U10, U11, U12, U13, U14, U15, U16, U2, U3, U4, U5, U6, U7, U8, U9, }; use crate::base::iter::{MatrixIter, MatrixIterMut}; -use crate::base::storage::{ContiguousStorage, ContiguousStorageMut, Storage, StorageMut}; +use crate::base::storage::{ContiguousStorage, ContiguousStorageMut, Storage, StorageMut, Owned}; use crate::base::{ ArrayStorage, DVectorSlice, DVectorSliceMut, DefaultAllocator, Matrix, MatrixMN, MatrixSlice, MatrixSliceMut, Scalar, @@ -86,6 +86,17 @@ where } } +impl IntoIterator for Matrix> + where DefaultAllocator: Allocator +{ + type Item = N; + type IntoIter = as IntoIterator>::IntoIter; + + #[inline] + fn into_iter(self) -> Self::IntoIter { + as IntoIterator>::into_iter(self.data) + } +} impl<'a, N: Scalar, R: Dim, C: Dim, S: Storage> IntoIterator for &'a Matrix { type Item = &'a N; type IntoIter = MatrixIter<'a, N, R, C, S>; diff --git a/src/base/iter.rs b/src/base/iter.rs index 1f330d95..f9300c80 100644 --- a/src/base/iter.rs +++ b/src/base/iter.rs @@ -3,9 +3,9 @@ use std::marker::PhantomData; use std::mem; -use crate::base::dimension::{Dim, U1}; -use crate::base::storage::{Storage, StorageMut}; -use crate::base::{Matrix, MatrixSlice, MatrixSliceMut, Scalar}; +use crate::base::dimension::{Dim, U1, Dynamic}; +use crate::base::storage::{Storage, StorageMut, Owned}; +use crate::base::{Matrix, MatrixSlice, MatrixSliceMut, Scalar, Vector, RowVector}; macro_rules! iterator { (struct $Name:ident for $Storage:ident.$ptr: ident -> $Ptr:ty, $Ref:ty, $SRef: ty) => { @@ -237,6 +237,58 @@ impl<'a, N: Scalar, R: Dim, C: Dim, S: 'a + StorageMut> ExactSizeIterat } } +/// An owned iterator through the rows of a matrix. +pub struct OwnedRowIter { + rows: std::vec::IntoIter>>, +} + +impl OwnedRowIter { + pub(crate) fn new(mat: Matrix>) -> Self { + let ncols = mat.ncols(); + let nrows = mat.nrows(); + let mut rows: Vec> = vec![Vec::with_capacity(ncols); nrows]; + let mut i = 0; + for item in mat.into_iter() { + rows[i % nrows].push(item); + i += 1; + } + let rows: Vec>> = + rows.into_iter() + .map(|row| RowVector::>::from_iterator_generic( + U1::from_usize(1), Dynamic::from_usize(ncols), row.into_iter())) + .collect(); + OwnedRowIter { rows: rows.into_iter() } + } +} + +impl Iterator for OwnedRowIter { + type Item = RowVector>; + + #[inline] + fn next(&mut self) -> Option { + self.rows.next() + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + self.rows.size_hint() + } + + #[inline] + fn count(self) -> usize { + self.rows.count() + } +} + +impl ExactSizeIterator + for OwnedRowIter +{ + #[inline] + fn len(&self) -> usize { + self.rows.len() + } +} + /* * * Column iterators. @@ -350,3 +402,59 @@ impl<'a, N: Scalar, R: Dim, C: Dim, S: 'a + StorageMut> ExactSizeIterat self.ncols() - self.curr } } + +/// An owned iterator through the rows of a matrix. +pub struct OwnedColumnIter { + cols: std::vec::IntoIter>>, +} + +impl OwnedColumnIter { + pub(crate) fn new(mat: Matrix>) -> Self { + let ncols = mat.ncols(); + let nrows = mat.nrows(); + let mut cols: Vec> = vec![Vec::with_capacity(nrows); ncols]; + let mut i = 0; + for item in mat.into_iter() { + cols[i / nrows].push(item); + i += 1; + } + let cols: Vec>> = + cols.into_iter() + .map(|col| + Vector::>::from_iterator_generic( + Dynamic::from_usize(nrows), + U1::from_usize(1), + col.into_iter() + ) + ) + .collect(); + OwnedColumnIter { cols: cols.into_iter() } + } +} + +impl Iterator for OwnedColumnIter { + type Item = Vector>; + + #[inline] + fn next(&mut self) -> Option { + self.cols.next() + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + self.cols.size_hint() + } + + #[inline] + fn count(self) -> usize { + self.cols.count() + } +} + +impl ExactSizeIterator + for OwnedColumnIter { + #[inline] + fn len(&self) -> usize { + self.cols.len() + } +} diff --git a/src/base/matrix.rs b/src/base/matrix.rs index 8035d2f8..4b3b2d5b 100644 --- a/src/base/matrix.rs +++ b/src/base/matrix.rs @@ -21,12 +21,12 @@ use simba::simd::SimdPartialOrd; use crate::base::allocator::{Allocator, SameShapeAllocator, SameShapeC, SameShapeR}; use crate::base::constraint::{DimEq, SameNumberOfColumns, SameNumberOfRows, ShapeConstraint}; -use crate::base::dimension::{Dim, DimAdd, DimSum, IsNotStaticOne, U1, U2, U3}; +use crate::base::dimension::{Dim, DimAdd, DimSum, IsNotStaticOne, U1, U2, U3, Dynamic}; use crate::base::iter::{ - ColumnIter, ColumnIterMut, MatrixIter, MatrixIterMut, RowIter, RowIterMut, + ColumnIter, ColumnIterMut, OwnedColumnIter, MatrixIter, MatrixIterMut, RowIter, RowIterMut, OwnedRowIter, }; use crate::base::storage::{ - ContiguousStorage, ContiguousStorageMut, Owned, SameShapeStorage, Storage, StorageMut, + ContiguousStorage, ContiguousStorageMut, SameShapeStorage, Storage, StorageMut, Owned }; use crate::base::{DefaultAllocator, MatrixMN, MatrixN, Scalar, Unit, VectorN}; use crate::SimdComplexField; @@ -859,6 +859,45 @@ impl> Matrix { } } +impl Matrix> { + /// Move rows of this matrix into an owned iterator. + /// + /// # Example + /// ``` + /// # use nalgebra::DMatrix; + /// let values = vec![1, 4, 2, 5, 3, 6].into_iter(); + /// let mut a = DMatrix::from_iterator(2, 3, values); + /// let c = a.clone(); + /// for (i, row) in a.into_row_iter().enumerate() { + /// for (v1, &v2) in row.into_iter().zip(c.row(i).iter()) { + /// assert_eq!(v1, v2) + /// } + /// } + /// ``` + #[inline] + pub fn into_row_iter(self) -> OwnedRowIter { + OwnedRowIter::new(self) + } + + /// Move columns of this matrix into an owned iterator. + /// # Example + /// ``` + /// # use nalgebra::DMatrix; + /// let values = vec![1, 4, 2, 5, 3, 6].into_iter(); + /// let mut a = DMatrix::from_iterator(2, 3, values); + /// let c = a.clone(); + /// for (i, column) in a.into_column_iter().enumerate() { + /// for (v1, &v2) in column.into_iter().zip(c.column(i).iter()) { + /// assert_eq!(v1, v2) + /// } + /// } + /// ``` + #[inline] + pub fn into_column_iter(self) -> OwnedColumnIter { + OwnedColumnIter::new(self) + } +} + /// # Iteration on components, rows, and columns impl> Matrix { /// Iterates through this matrix coordinates in column-major order. diff --git a/src/base/vec_storage.rs b/src/base/vec_storage.rs index 03f032e8..e65673fb 100644 --- a/src/base/vec_storage.rs +++ b/src/base/vec_storage.rs @@ -31,6 +31,18 @@ pub struct VecStorage { ncols: C, } +impl IntoIterator for VecStorage +where + R: Dim, + C: Dim, +{ + type Item = N; + type IntoIter = as IntoIterator>::IntoIter; + fn into_iter(self) -> Self::IntoIter { + self.data.into_iter() + } +} + #[deprecated(note = "renamed to `VecStorage`")] /// Renamed to [VecStorage]. pub type MatrixVec = VecStorage;