From 008511d96eed1adfdb1b3cacda5ff8cf76a4d075 Mon Sep 17 00:00:00 2001 From: Chammika Mannakkara Date: Tue, 4 May 2021 22:23:49 +0900 Subject: [PATCH 1/6] from_row_iterator added --- src/base/allocator.rs | 7 +++ src/base/construction.rs | 41 +++++++++++++++++ src/base/default_allocator.rs | 86 +++++++++++++++++++++++++++++++++++ 3 files changed, 134 insertions(+) diff --git a/src/base/allocator.rs b/src/base/allocator.rs index 29286420..ccbcca37 100644 --- a/src/base/allocator.rs +++ b/src/base/allocator.rs @@ -41,6 +41,13 @@ pub trait Allocator: Any + Sized { ncols: C, iter: I, ) -> Self::Buffer; + + /// Allocates a buffer initialized with the content of the given row-major order iterator. + fn allocate_from_row_iterator>( + nrows: R, + ncols: C, + iter: I, + ) -> Self::Buffer; } /// A matrix reallocator. Changes the size of the memory buffer that initially contains (`RFrom` × diff --git a/src/base/construction.rs b/src/base/construction.rs index fe4e4b08..009d8c76 100644 --- a/src/base/construction.rs +++ b/src/base/construction.rs @@ -86,6 +86,17 @@ where Self::from_data(DefaultAllocator::allocate_from_iterator(nrows, ncols, iter)) } + /// Creates a matrix with all its elements filled by an row-major order iterator. + #[inline] + pub fn from_row_iterator_generic(nrows: R, ncols: C, iter: I) -> Self + where + I: IntoIterator, + { + Self::from_data(DefaultAllocator::allocate_from_row_iterator( + nrows, ncols, iter, + )) + } + /// Creates a matrix with its elements filled with the components provided by a slice in /// row-major order. /// @@ -479,6 +490,36 @@ macro_rules! impl_constructors( Self::from_iterator_generic($($gargs, )* iter) } + /// Creates a matrix or vector with all its elements filled by a row-major iterator. + /// + /// The output matrix is filled row-by-row. + /// + /// ## Example + /// ``` + /// # use nalgebra::{Matrix2x3, Vector3, DVector, DMatrix}; + /// # use std::iter; + /// + /// let v = Vector3::from_row_iterator((0..3).into_iter()); + /// // The additional argument represents the vector dimension. + /// let dv = DVector::from_row_iterator(3, (0..3).into_iter()); + /// let m = Matrix2x3::from_row_iterator((0..6).into_iter()); + /// // The two additional arguments represent the matrix dimensions. + /// let dm = DMatrix::from_row_iterator(2, 3, (0..6).into_iter()); + /// + /// // For Vectors from_row_iterator is identical to from_iterator + /// assert!(v.x == 0 && v.y == 1 && v.z == 2); + /// assert!(dv[0] == 0 && dv[1] == 1 && dv[2] == 2); + /// assert!(m.m11 == 0 && m.m12 == 1 && m.m13 == 2 && + /// m.m21 == 3 && m.m22 == 4 && m.m23 == 5); + /// assert!(dm[(0, 0)] == 0 && dm[(0, 1)] == 1 && dm[(0, 2)] == 2 && + /// dm[(1, 0)] == 3 && dm[(1, 1)] == 4 && dm[(1, 2)] == 5); + /// ``` + #[inline] + pub fn from_row_iterator($($args: usize,)* iter: I) -> Self + where I: IntoIterator { + Self::from_row_iterator_generic($($gargs, )* iter) + } + /// Creates a matrix or vector filled with the results of a function applied to each of its /// component coordinates. /// diff --git a/src/base/default_allocator.rs b/src/base/default_allocator.rs index 09197bbd..e055604c 100644 --- a/src/base/default_allocator.rs +++ b/src/base/default_allocator.rs @@ -80,6 +80,40 @@ impl Allocator, Const> // yielded enough elements to initialize our matrix. unsafe { , Const>>::assume_init(res) } } + + #[inline] + fn allocate_from_row_iterator>( + nrows: Const, + ncols: Const, + iter: I, + ) -> Self::Buffer { + #[cfg(feature = "no_unsound_assume_init")] + let mut res: Self::Buffer = unimplemented!(); + #[cfg(not(feature = "no_unsound_assume_init"))] + let mut res = unsafe { Self::allocate_uninitialized(nrows, ncols).assume_init() }; + let mut count = 0; + let res_ptr = res.as_mut_slice(); + + for (i, e) in iter + .into_iter() + .take(ncols.value() * nrows.value()) + .enumerate() + { + unsafe { + *res_ptr + .get_unchecked_mut((i % ncols.value()) * nrows.value() + i / ncols.value()) = e; + } + // res_ptr[(i % ncols.value()) * nrows.value() + i / ncols.value()] = e; + count += 1; + } + + assert!( + count == nrows.value() * ncols.value(), + "Matrix init. from row iterator: iterator not long enough." + ); + + res + } } // Dynamic - Static @@ -128,6 +162,32 @@ impl Allocator for DefaultAllocator { VecStorage::new(nrows, ncols, res) } + + #[inline] + fn allocate_from_row_iterator>( + nrows: Dynamic, + ncols: C, + iter: I, + ) -> Self::Buffer { + let it = iter.into_iter().take(nrows.value() * ncols.value()); + let mut res: Vec = Vec::with_capacity(nrows.value() * ncols.value()); + let res_ptr = res.as_mut_ptr(); + let mut count = 0; + + unsafe { + for (i, e) in it.enumerate() { + *res_ptr.add((i % ncols.value()) * nrows.value() + i / ncols.value()) = e; + count += 1; + } + res.set_len(nrows.value() * ncols.value()); + } + assert!( + count == nrows.value() * ncols.value(), + "Matrix init. from row iterator: iterator not long enough." + ); + + VecStorage::new(nrows, ncols, res) + } } // Static - Dynamic @@ -176,6 +236,32 @@ impl Allocator for DefaultAllocator { VecStorage::new(nrows, ncols, res) } + + #[inline] + fn allocate_from_row_iterator>( + nrows: R, + ncols: Dynamic, + iter: I, + ) -> Self::Buffer { + let it = iter.into_iter().take(nrows.value() * ncols.value()); + let mut res: Vec = Vec::with_capacity(nrows.value() * ncols.value()); + let res_ptr = res.as_mut_ptr(); + let mut count = 0; + + unsafe { + for (i, e) in it.enumerate() { + *res_ptr.add((i % ncols.value()) * nrows.value() + i / ncols.value()) = e; + count += 1; + } + res.set_len(nrows.value() * ncols.value()); + } + assert!( + count == nrows.value() * ncols.value(), + "Matrix init. from row iterator: iterator not long enough." + ); + + VecStorage::new(nrows, ncols, res) + } } /* From 8588ef8fb20f6e3fb0f3dbbf99f32e850638a451 Mon Sep 17 00:00:00 2001 From: Gianluca Oldani Date: Wed, 2 Mar 2022 00:52:01 +0100 Subject: [PATCH 2/6] Sound implementation for from_row_iterator --- src/base/default_allocator.rs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/base/default_allocator.rs b/src/base/default_allocator.rs index e055604c..b048ba24 100644 --- a/src/base/default_allocator.rs +++ b/src/base/default_allocator.rs @@ -87,10 +87,7 @@ impl Allocator, Const> ncols: Const, iter: I, ) -> Self::Buffer { - #[cfg(feature = "no_unsound_assume_init")] - let mut res: Self::Buffer = unimplemented!(); - #[cfg(not(feature = "no_unsound_assume_init"))] - let mut res = unsafe { Self::allocate_uninitialized(nrows, ncols).assume_init() }; + let mut res = Self::allocate_uninit(nrows, ncols); let mut count = 0; let res_ptr = res.as_mut_slice(); @@ -101,7 +98,7 @@ impl Allocator, Const> { unsafe { *res_ptr - .get_unchecked_mut((i % ncols.value()) * nrows.value() + i / ncols.value()) = e; + .get_unchecked_mut((i % ncols.value()) * nrows.value() + i / ncols.value()) = MaybeUninit::new(e); } // res_ptr[(i % ncols.value()) * nrows.value() + i / ncols.value()] = e; count += 1; @@ -112,7 +109,7 @@ impl Allocator, Const> "Matrix init. from row iterator: iterator not long enough." ); - res + unsafe { , Const>>::assume_init(res) } } } @@ -250,7 +247,7 @@ impl Allocator for DefaultAllocator { unsafe { for (i, e) in it.enumerate() { - *res_ptr.add((i % ncols.value()) * nrows.value() + i / ncols.value()) = e; + *res_ptr.add((i % ncols.value()) * nrows.value() + i / ncols.value()) = MaybeUninit::new(e).assume_init(); count += 1; } res.set_len(nrows.value() * ncols.value()); From 59b01e955f2d6901eba972c58c2ffcb4c9b5781d Mon Sep 17 00:00:00 2001 From: Gianluca Oldani Date: Thu, 3 Mar 2022 13:33:04 +0100 Subject: [PATCH 3/6] Fixed formatting --- src/base/default_allocator.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/base/default_allocator.rs b/src/base/default_allocator.rs index b048ba24..d9bc2c6b 100644 --- a/src/base/default_allocator.rs +++ b/src/base/default_allocator.rs @@ -98,7 +98,8 @@ impl Allocator, Const> { unsafe { *res_ptr - .get_unchecked_mut((i % ncols.value()) * nrows.value() + i / ncols.value()) = MaybeUninit::new(e); + .get_unchecked_mut((i % ncols.value()) * nrows.value() + i / ncols.value()) = + MaybeUninit::new(e); } // res_ptr[(i % ncols.value()) * nrows.value() + i / ncols.value()] = e; count += 1; @@ -247,7 +248,8 @@ impl Allocator for DefaultAllocator { unsafe { for (i, e) in it.enumerate() { - *res_ptr.add((i % ncols.value()) * nrows.value() + i / ncols.value()) = MaybeUninit::new(e).assume_init(); + *res_ptr.add((i % ncols.value()) * nrows.value() + i / ncols.value()) = + MaybeUninit::new(e).assume_init(); count += 1; } res.set_len(nrows.value() * ncols.value()); From 89767ee9f33106f874127fd2ee018dc259ad070b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Crozet?= Date: Sat, 30 Jul 2022 18:06:47 +0200 Subject: [PATCH 4/6] Reduce code duplication for allocating a storage from a raw iterator. --- src/base/allocator.rs | 30 ++++++++++++- src/base/default_allocator.rs | 85 ----------------------------------- 2 files changed, 29 insertions(+), 86 deletions(-) diff --git a/src/base/allocator.rs b/src/base/allocator.rs index ccbcca37..bb227d3b 100644 --- a/src/base/allocator.rs +++ b/src/base/allocator.rs @@ -42,12 +42,40 @@ pub trait Allocator: Any + Sized { iter: I, ) -> Self::Buffer; + #[inline] /// Allocates a buffer initialized with the content of the given row-major order iterator. fn allocate_from_row_iterator>( nrows: R, ncols: C, iter: I, - ) -> Self::Buffer; + ) -> Self::Buffer { + let mut res = Self::allocate_uninit(nrows, ncols); + let mut count = 0; + + unsafe { + // OK because the allocated buffer is guaranteed to be contiguous. + let res_ptr = res.as_mut_slice_unchecked(); + + for (k, e) in iter + .into_iter() + .take(ncols.value() * nrows.value()) + .enumerate() + { + let i = k / ncols.value(); + let j = k % ncols.value(); + // result[(i, j)] = e; + *res_ptr.get_unchecked_mut(i + j * nrows.value()) = MaybeUninit::new(e); + count += 1; + } + + assert!( + count == nrows.value() * ncols.value(), + "Matrix init. from row iterator: iterator not long enough." + ); + + >::assume_init(res) + } + } } /// A matrix reallocator. Changes the size of the memory buffer that initially contains (`RFrom` × diff --git a/src/base/default_allocator.rs b/src/base/default_allocator.rs index d9bc2c6b..09197bbd 100644 --- a/src/base/default_allocator.rs +++ b/src/base/default_allocator.rs @@ -80,38 +80,6 @@ impl Allocator, Const> // yielded enough elements to initialize our matrix. unsafe { , Const>>::assume_init(res) } } - - #[inline] - fn allocate_from_row_iterator>( - nrows: Const, - ncols: Const, - iter: I, - ) -> Self::Buffer { - let mut res = Self::allocate_uninit(nrows, ncols); - let mut count = 0; - let res_ptr = res.as_mut_slice(); - - for (i, e) in iter - .into_iter() - .take(ncols.value() * nrows.value()) - .enumerate() - { - unsafe { - *res_ptr - .get_unchecked_mut((i % ncols.value()) * nrows.value() + i / ncols.value()) = - MaybeUninit::new(e); - } - // res_ptr[(i % ncols.value()) * nrows.value() + i / ncols.value()] = e; - count += 1; - } - - assert!( - count == nrows.value() * ncols.value(), - "Matrix init. from row iterator: iterator not long enough." - ); - - unsafe { , Const>>::assume_init(res) } - } } // Dynamic - Static @@ -160,32 +128,6 @@ impl Allocator for DefaultAllocator { VecStorage::new(nrows, ncols, res) } - - #[inline] - fn allocate_from_row_iterator>( - nrows: Dynamic, - ncols: C, - iter: I, - ) -> Self::Buffer { - let it = iter.into_iter().take(nrows.value() * ncols.value()); - let mut res: Vec = Vec::with_capacity(nrows.value() * ncols.value()); - let res_ptr = res.as_mut_ptr(); - let mut count = 0; - - unsafe { - for (i, e) in it.enumerate() { - *res_ptr.add((i % ncols.value()) * nrows.value() + i / ncols.value()) = e; - count += 1; - } - res.set_len(nrows.value() * ncols.value()); - } - assert!( - count == nrows.value() * ncols.value(), - "Matrix init. from row iterator: iterator not long enough." - ); - - VecStorage::new(nrows, ncols, res) - } } // Static - Dynamic @@ -234,33 +176,6 @@ impl Allocator for DefaultAllocator { VecStorage::new(nrows, ncols, res) } - - #[inline] - fn allocate_from_row_iterator>( - nrows: R, - ncols: Dynamic, - iter: I, - ) -> Self::Buffer { - let it = iter.into_iter().take(nrows.value() * ncols.value()); - let mut res: Vec = Vec::with_capacity(nrows.value() * ncols.value()); - let res_ptr = res.as_mut_ptr(); - let mut count = 0; - - unsafe { - for (i, e) in it.enumerate() { - *res_ptr.add((i % ncols.value()) * nrows.value() + i / ncols.value()) = - MaybeUninit::new(e).assume_init(); - count += 1; - } - res.set_len(nrows.value() * ncols.value()); - } - assert!( - count == nrows.value() * ncols.value(), - "Matrix init. from row iterator: iterator not long enough." - ); - - VecStorage::new(nrows, ncols, res) - } } /* From d5284a2a86ac05d40720d14ecf71896abdcb7241 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Crozet?= Date: Sat, 30 Jul 2022 18:16:18 +0200 Subject: [PATCH 5/6] Remove unused extern crate. --- src/lib.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 1ee1a3ba..8da86531 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -109,8 +109,6 @@ extern crate alloc; #[cfg(not(feature = "std"))] extern crate core as std; -#[cfg(feature = "io")] -extern crate pest; #[macro_use] #[cfg(feature = "io")] extern crate pest_derive; From 54ab62d9715831384a4ea618f1cf641bd8f4c6fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Crozet?= Date: Sat, 30 Jul 2022 18:19:17 +0200 Subject: [PATCH 6/6] Remove another unused extern crate. --- nalgebra-sparse/src/lib.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/nalgebra-sparse/src/lib.rs b/nalgebra-sparse/src/lib.rs index 8567261a..c62677c3 100644 --- a/nalgebra-sparse/src/lib.rs +++ b/nalgebra-sparse/src/lib.rs @@ -143,8 +143,6 @@ )] pub extern crate nalgebra as na; -#[cfg(feature = "io")] -extern crate pest; #[macro_use] #[cfg(feature = "io")] extern crate pest_derive;