Merge pull request #1133 from dimforge/from_row_iterator

Sound implementation of from row iterator
This commit is contained in:
Sébastien Crozet 2022-07-31 09:31:49 +02:00 committed by GitHub
commit 74c4aa9c9f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 76 additions and 4 deletions

View File

@ -143,8 +143,6 @@
)] )]
pub extern crate nalgebra as na; pub extern crate nalgebra as na;
#[cfg(feature = "io")]
extern crate pest;
#[macro_use] #[macro_use]
#[cfg(feature = "io")] #[cfg(feature = "io")]
extern crate pest_derive; extern crate pest_derive;

View File

@ -41,6 +41,41 @@ pub trait Allocator<T, R: Dim, C: Dim = U1>: Any + Sized {
ncols: C, ncols: C,
iter: I, iter: I,
) -> Self::Buffer; ) -> Self::Buffer;
#[inline]
/// Allocates a buffer initialized with the content of the given row-major order iterator.
fn allocate_from_row_iterator<I: IntoIterator<Item = T>>(
nrows: R,
ncols: C,
iter: I,
) -> 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."
);
<Self as Allocator<T, R, C>>::assume_init(res)
}
}
} }
/// A matrix reallocator. Changes the size of the memory buffer that initially contains (`RFrom` × /// A matrix reallocator. Changes the size of the memory buffer that initially contains (`RFrom` ×

View File

@ -86,6 +86,17 @@ where
Self::from_data(DefaultAllocator::allocate_from_iterator(nrows, ncols, iter)) 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<I>(nrows: R, ncols: C, iter: I) -> Self
where
I: IntoIterator<Item = T>,
{
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 /// Creates a matrix with its elements filled with the components provided by a slice in
/// row-major order. /// row-major order.
/// ///
@ -479,6 +490,36 @@ macro_rules! impl_constructors(
Self::from_iterator_generic($($gargs, )* iter) 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<I>($($args: usize,)* iter: I) -> Self
where I: IntoIterator<Item = T> {
Self::from_row_iterator_generic($($gargs, )* iter)
}
/// Creates a matrix or vector filled with the results of a function applied to each of its /// Creates a matrix or vector filled with the results of a function applied to each of its
/// component coordinates. /// component coordinates.
/// ///

View File

@ -109,8 +109,6 @@ extern crate alloc;
#[cfg(not(feature = "std"))] #[cfg(not(feature = "std"))]
extern crate core as std; extern crate core as std;
#[cfg(feature = "io")]
extern crate pest;
#[macro_use] #[macro_use]
#[cfg(feature = "io")] #[cfg(feature = "io")]
extern crate pest_derive; extern crate pest_derive;