2018-02-02 19:26:35 +08:00
|
|
|
|
use num::{One, Zero};
|
2017-08-03 01:37:44 +08:00
|
|
|
|
use std::cmp;
|
2019-02-03 22:16:50 +08:00
|
|
|
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
2018-12-09 19:22:10 +08:00
|
|
|
|
use std::iter::ExactSizeIterator;
|
2019-02-03 22:16:50 +08:00
|
|
|
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
2019-01-29 19:03:48 +08:00
|
|
|
|
use std::mem;
|
2021-07-16 12:56:58 +08:00
|
|
|
|
use std::mem::MaybeUninit;
|
2019-04-08 23:29:32 +08:00
|
|
|
|
use std::ptr;
|
2017-08-03 01:37:44 +08:00
|
|
|
|
|
2019-03-23 21:29:07 +08:00
|
|
|
|
use crate::base::allocator::{Allocator, Reallocator};
|
|
|
|
|
use crate::base::constraint::{DimEq, SameNumberOfColumns, SameNumberOfRows, ShapeConstraint};
|
2019-04-08 23:29:32 +08:00
|
|
|
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
|
|
|
|
use crate::base::dimension::Dynamic;
|
2021-04-11 17:00:38 +08:00
|
|
|
|
use crate::base::dimension::{Const, Dim, DimAdd, DimDiff, DimMin, DimMinimum, DimSub, DimSum, U1};
|
2021-06-17 15:46:49 +08:00
|
|
|
|
use crate::base::storage::{ContiguousStorageMut, ReshapableStorage, Storage, StorageMut};
|
2021-04-12 16:34:15 +08:00
|
|
|
|
use crate::base::{DefaultAllocator, Matrix, OMatrix, RowVector, Scalar, Vector};
|
2017-08-03 01:37:44 +08:00
|
|
|
|
|
2020-11-15 23:57:49 +08:00
|
|
|
|
/// # Rows and columns extraction
|
2021-04-11 17:00:38 +08:00
|
|
|
|
impl<T: Scalar + Zero, R: Dim, C: Dim, S: Storage<T, R, C>> Matrix<T, R, C, S> {
|
2017-08-03 01:37:44 +08:00
|
|
|
|
/// Extracts the upper triangular part of this matrix (including the diagonal).
|
|
|
|
|
#[inline]
|
2021-06-07 22:34:03 +08:00
|
|
|
|
#[must_use]
|
2021-04-11 17:00:38 +08:00
|
|
|
|
pub fn upper_triangle(&self) -> OMatrix<T, R, C>
|
2020-04-06 00:49:48 +08:00
|
|
|
|
where
|
2021-04-11 17:00:38 +08:00
|
|
|
|
DefaultAllocator: Allocator<T, R, C>,
|
2020-04-06 00:49:48 +08:00
|
|
|
|
{
|
2017-08-03 01:37:44 +08:00
|
|
|
|
let mut res = self.clone_owned();
|
2021-04-11 17:00:38 +08:00
|
|
|
|
res.fill_lower_triangle(T::zero(), 1);
|
2017-08-03 01:37:44 +08:00
|
|
|
|
|
|
|
|
|
res
|
|
|
|
|
}
|
|
|
|
|
|
2019-01-30 15:42:28 +08:00
|
|
|
|
/// Extracts the lower triangular part of this matrix (including the diagonal).
|
2017-08-03 01:37:44 +08:00
|
|
|
|
#[inline]
|
2021-06-07 22:34:03 +08:00
|
|
|
|
#[must_use]
|
2021-04-11 17:00:38 +08:00
|
|
|
|
pub fn lower_triangle(&self) -> OMatrix<T, R, C>
|
2020-04-06 00:49:48 +08:00
|
|
|
|
where
|
2021-04-11 17:00:38 +08:00
|
|
|
|
DefaultAllocator: Allocator<T, R, C>,
|
2020-04-06 00:49:48 +08:00
|
|
|
|
{
|
2017-08-03 01:37:44 +08:00
|
|
|
|
let mut res = self.clone_owned();
|
2021-04-11 17:00:38 +08:00
|
|
|
|
res.fill_upper_triangle(T::zero(), 1);
|
2017-08-03 01:37:44 +08:00
|
|
|
|
|
|
|
|
|
res
|
|
|
|
|
}
|
2018-12-09 19:22:10 +08:00
|
|
|
|
|
|
|
|
|
/// Creates a new matrix by extracting the given set of rows from `self`.
|
2019-02-03 22:16:50 +08:00
|
|
|
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
2021-06-07 22:34:03 +08:00
|
|
|
|
#[must_use]
|
2021-04-11 17:00:38 +08:00
|
|
|
|
pub fn select_rows<'a, I>(&self, irows: I) -> OMatrix<T, Dynamic, C>
|
2019-04-08 23:29:32 +08:00
|
|
|
|
where
|
|
|
|
|
I: IntoIterator<Item = &'a usize>,
|
|
|
|
|
I::IntoIter: ExactSizeIterator + Clone,
|
|
|
|
|
{
|
2019-02-03 15:33:07 +08:00
|
|
|
|
let irows = irows.into_iter();
|
2018-12-09 19:22:10 +08:00
|
|
|
|
let ncols = self.data.shape().1;
|
2021-07-16 13:27:16 +08:00
|
|
|
|
let mut res =
|
|
|
|
|
OMatrix::<T, Dynamic, C>::new_uninitialized_generic(Dynamic::new(irows.len()), ncols);
|
2018-12-09 19:22:10 +08:00
|
|
|
|
|
|
|
|
|
// First, check that all the indices from irows are valid.
|
|
|
|
|
// This will allow us to use unchecked access in the inner loop.
|
|
|
|
|
for i in irows.clone() {
|
2018-12-09 23:56:27 +08:00
|
|
|
|
assert!(*i < self.nrows(), "Row index out of bounds.")
|
2018-12-09 19:22:10 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for j in 0..ncols.value() {
|
2020-11-15 23:57:49 +08:00
|
|
|
|
// TODO: use unchecked column indexing
|
2018-12-09 19:22:10 +08:00
|
|
|
|
let mut res = res.column_mut(j);
|
2019-03-31 19:32:26 +08:00
|
|
|
|
let src = self.column(j);
|
2018-12-09 19:22:10 +08:00
|
|
|
|
|
|
|
|
|
for (destination, source) in irows.clone().enumerate() {
|
2020-04-06 00:49:48 +08:00
|
|
|
|
unsafe {
|
|
|
|
|
*res.vget_unchecked_mut(destination) =
|
2021-07-17 12:17:56 +08:00
|
|
|
|
MaybeUninit::new(src.vget_unchecked(*source).clone());
|
2020-04-06 00:49:48 +08:00
|
|
|
|
}
|
2018-12-09 19:22:10 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-07-16 12:56:58 +08:00
|
|
|
|
unsafe { res.assume_init() }
|
2018-12-09 19:22:10 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Creates a new matrix by extracting the given set of columns from `self`.
|
2019-02-03 22:16:50 +08:00
|
|
|
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
2021-06-07 22:34:03 +08:00
|
|
|
|
#[must_use]
|
2021-04-11 17:00:38 +08:00
|
|
|
|
pub fn select_columns<'a, I>(&self, icols: I) -> OMatrix<T, R, Dynamic>
|
2019-04-08 23:29:32 +08:00
|
|
|
|
where
|
|
|
|
|
I: IntoIterator<Item = &'a usize>,
|
|
|
|
|
I::IntoIter: ExactSizeIterator,
|
2021-04-11 17:00:38 +08:00
|
|
|
|
DefaultAllocator: Allocator<T, R, Dynamic>,
|
2019-04-08 23:29:32 +08:00
|
|
|
|
{
|
2019-02-03 15:33:07 +08:00
|
|
|
|
let icols = icols.into_iter();
|
2018-12-09 19:22:10 +08:00
|
|
|
|
let nrows = self.data.shape().0;
|
2021-07-16 12:56:58 +08:00
|
|
|
|
let mut res = Matrix::new_uninitialized_generic(nrows, Dynamic::new(icols.len()));
|
2018-12-09 19:22:10 +08:00
|
|
|
|
|
|
|
|
|
for (destination, source) in icols.enumerate() {
|
2021-07-16 12:56:58 +08:00
|
|
|
|
for (d, s) in res
|
|
|
|
|
.column_mut(destination)
|
|
|
|
|
.iter_mut()
|
|
|
|
|
.zip(self.column(*source).iter())
|
|
|
|
|
{
|
|
|
|
|
*d = MaybeUninit::new(s.clone());
|
|
|
|
|
}
|
2018-12-09 19:22:10 +08:00
|
|
|
|
}
|
|
|
|
|
|
2021-07-16 12:56:58 +08:00
|
|
|
|
unsafe { res.assume_init() }
|
2018-12-09 19:22:10 +08:00
|
|
|
|
}
|
2017-08-03 01:37:44 +08:00
|
|
|
|
}
|
|
|
|
|
|
2020-11-15 23:57:49 +08:00
|
|
|
|
/// # Set rows, columns, and diagonal
|
2021-07-17 12:17:56 +08:00
|
|
|
|
impl<T, R: Dim, C: Dim, S: StorageMut<T, R, C>> Matrix<T, R, C, S> {
|
2017-08-03 01:37:44 +08:00
|
|
|
|
/// Fills the diagonal of this matrix with the content of the given vector.
|
|
|
|
|
#[inline]
|
2021-04-11 17:00:38 +08:00
|
|
|
|
pub fn set_diagonal<R2: Dim, S2>(&mut self, diag: &Vector<T, R2, S2>)
|
2019-04-08 23:29:32 +08:00
|
|
|
|
where
|
2021-07-17 12:17:56 +08:00
|
|
|
|
T: Clone,
|
2019-04-08 23:29:32 +08:00
|
|
|
|
R: DimMin<C>,
|
2021-04-11 17:00:38 +08:00
|
|
|
|
S2: Storage<T, R2>,
|
2019-04-08 23:29:32 +08:00
|
|
|
|
ShapeConstraint: DimEq<DimMinimum<R, C>, R2>,
|
2018-02-02 19:26:35 +08:00
|
|
|
|
{
|
|
|
|
|
let (nrows, ncols) = self.shape();
|
2017-08-03 01:37:44 +08:00
|
|
|
|
let min_nrows_ncols = cmp::min(nrows, ncols);
|
|
|
|
|
assert_eq!(diag.len(), min_nrows_ncols, "Mismatched dimensions.");
|
|
|
|
|
|
2018-02-02 19:26:35 +08:00
|
|
|
|
for i in 0..min_nrows_ncols {
|
2021-07-17 12:17:56 +08:00
|
|
|
|
unsafe { *self.get_unchecked_mut((i, i)) = diag.vget_unchecked(i).clone() }
|
2017-08-03 01:37:44 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-23 21:13:00 +08:00
|
|
|
|
/// Fills the diagonal of this matrix with the content of the given iterator.
|
|
|
|
|
///
|
|
|
|
|
/// This will fill as many diagonal elements as the iterator yields, up to the
|
|
|
|
|
/// minimum of the number of rows and columns of `self`, and starting with the
|
|
|
|
|
/// diagonal element at index (0, 0).
|
|
|
|
|
#[inline]
|
2021-04-11 17:00:38 +08:00
|
|
|
|
pub fn set_partial_diagonal(&mut self, diag: impl Iterator<Item = T>) {
|
2019-03-23 21:13:00 +08:00
|
|
|
|
let (nrows, ncols) = self.shape();
|
|
|
|
|
let min_nrows_ncols = cmp::min(nrows, ncols);
|
|
|
|
|
|
|
|
|
|
for (i, val) in diag.enumerate().take(min_nrows_ncols) {
|
|
|
|
|
unsafe { *self.get_unchecked_mut((i, i)) = val }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-08-15 23:04:17 +08:00
|
|
|
|
/// Fills the selected row of this matrix with the content of the given vector.
|
|
|
|
|
#[inline]
|
2021-04-11 17:00:38 +08:00
|
|
|
|
pub fn set_row<C2: Dim, S2>(&mut self, i: usize, row: &RowVector<T, C2, S2>)
|
2018-02-02 19:26:35 +08:00
|
|
|
|
where
|
2021-07-17 12:17:56 +08:00
|
|
|
|
T: Clone,
|
2021-04-11 17:00:38 +08:00
|
|
|
|
S2: Storage<T, U1, C2>,
|
2018-02-02 19:26:35 +08:00
|
|
|
|
ShapeConstraint: SameNumberOfColumns<C, C2>,
|
|
|
|
|
{
|
2017-08-15 23:04:17 +08:00
|
|
|
|
self.row_mut(i).copy_from(row);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Fills the selected column of this matrix with the content of the given vector.
|
|
|
|
|
#[inline]
|
2021-04-11 17:00:38 +08:00
|
|
|
|
pub fn set_column<R2: Dim, S2>(&mut self, i: usize, column: &Vector<T, R2, S2>)
|
2018-02-02 19:26:35 +08:00
|
|
|
|
where
|
2021-07-17 12:17:56 +08:00
|
|
|
|
T: Clone,
|
2021-04-11 17:00:38 +08:00
|
|
|
|
S2: Storage<T, R2, U1>,
|
2018-02-02 19:26:35 +08:00
|
|
|
|
ShapeConstraint: SameNumberOfRows<R, R2>,
|
|
|
|
|
{
|
2017-08-15 23:04:17 +08:00
|
|
|
|
self.column_mut(i).copy_from(column);
|
|
|
|
|
}
|
2020-11-15 23:57:49 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// # In-place filling
|
2021-07-15 12:30:31 +08:00
|
|
|
|
impl<T, R: Dim, C: Dim, S: StorageMut<T, R, C>> Matrix<T, R, C, S> {
|
2020-11-15 23:57:49 +08:00
|
|
|
|
/// Sets all the elements of this matrix to `val`.
|
|
|
|
|
#[inline]
|
2021-07-15 12:30:31 +08:00
|
|
|
|
pub fn fill(&mut self, val: T)
|
|
|
|
|
where
|
|
|
|
|
T: Clone,
|
|
|
|
|
{
|
|
|
|
|
for e in self.iter_mut() {
|
|
|
|
|
*e = val.clone()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Sets all the elements of this matrix to `f()`.
|
|
|
|
|
#[inline]
|
|
|
|
|
pub fn fill_fn<F: FnMut() -> T>(&mut self, f: F) {
|
2020-11-15 23:57:49 +08:00
|
|
|
|
for e in self.iter_mut() {
|
2021-07-15 12:30:31 +08:00
|
|
|
|
*e = f();
|
2020-11-15 23:57:49 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Fills `self` with the identity matrix.
|
|
|
|
|
#[inline]
|
|
|
|
|
pub fn fill_with_identity(&mut self)
|
|
|
|
|
where
|
2021-07-15 12:30:31 +08:00
|
|
|
|
T: Zero + One + Scalar,
|
2020-11-15 23:57:49 +08:00
|
|
|
|
{
|
2021-04-11 17:00:38 +08:00
|
|
|
|
self.fill(T::zero());
|
|
|
|
|
self.fill_diagonal(T::one());
|
2020-11-15 23:57:49 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Sets all the diagonal elements of this matrix to `val`.
|
|
|
|
|
#[inline]
|
2021-07-16 12:56:58 +08:00
|
|
|
|
pub fn fill_diagonal(&mut self, val: T)
|
|
|
|
|
where
|
|
|
|
|
T: Clone,
|
|
|
|
|
{
|
2020-11-15 23:57:49 +08:00
|
|
|
|
let (nrows, ncols) = self.shape();
|
|
|
|
|
let n = cmp::min(nrows, ncols);
|
|
|
|
|
|
|
|
|
|
for i in 0..n {
|
2021-07-15 12:30:31 +08:00
|
|
|
|
unsafe { *self.get_unchecked_mut((i, i)) = val.clone() }
|
2020-11-15 23:57:49 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Sets all the elements of the selected row to `val`.
|
|
|
|
|
#[inline]
|
2021-07-16 12:56:58 +08:00
|
|
|
|
pub fn fill_row(&mut self, i: usize, val: T)
|
|
|
|
|
where
|
|
|
|
|
T: Clone,
|
|
|
|
|
{
|
2020-11-15 23:57:49 +08:00
|
|
|
|
assert!(i < self.nrows(), "Row index out of bounds.");
|
|
|
|
|
for j in 0..self.ncols() {
|
2021-07-16 12:56:58 +08:00
|
|
|
|
unsafe { *self.get_unchecked_mut((i, j)) = val.clone() }
|
2020-11-15 23:57:49 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Sets all the elements of the selected column to `val`.
|
|
|
|
|
#[inline]
|
2021-07-16 12:56:58 +08:00
|
|
|
|
pub fn fill_column(&mut self, j: usize, val: T)
|
|
|
|
|
where
|
|
|
|
|
T: Clone,
|
|
|
|
|
{
|
2020-11-15 23:57:49 +08:00
|
|
|
|
assert!(j < self.ncols(), "Row index out of bounds.");
|
|
|
|
|
for i in 0..self.nrows() {
|
2021-07-16 12:56:58 +08:00
|
|
|
|
unsafe { *self.get_unchecked_mut((i, j)) = val.clone() }
|
2020-11-15 23:57:49 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
2017-08-15 23:04:17 +08:00
|
|
|
|
|
2017-08-03 01:37:44 +08:00
|
|
|
|
/// Sets all the elements of the lower-triangular part of this matrix to `val`.
|
|
|
|
|
///
|
|
|
|
|
/// The parameter `shift` allows some subdiagonals to be left untouched:
|
|
|
|
|
/// * If `shift = 0` then the diagonal is overwritten as well.
|
|
|
|
|
/// * If `shift = 1` then the diagonal is left untouched.
|
|
|
|
|
/// * If `shift > 1`, then the diagonal and the first `shift - 1` subdiagonals are left
|
|
|
|
|
/// untouched.
|
|
|
|
|
#[inline]
|
2021-07-16 12:56:58 +08:00
|
|
|
|
pub fn fill_lower_triangle(&mut self, val: T, shift: usize)
|
|
|
|
|
where
|
|
|
|
|
T: Clone,
|
|
|
|
|
{
|
2018-02-02 19:26:35 +08:00
|
|
|
|
for j in 0..self.ncols() {
|
|
|
|
|
for i in (j + shift)..self.nrows() {
|
2021-07-16 12:56:58 +08:00
|
|
|
|
unsafe { *self.get_unchecked_mut((i, j)) = val.clone() }
|
2017-08-03 01:37:44 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Sets all the elements of the lower-triangular part of this matrix to `val`.
|
|
|
|
|
///
|
|
|
|
|
/// The parameter `shift` allows some superdiagonals to be left untouched:
|
|
|
|
|
/// * If `shift = 0` then the diagonal is overwritten as well.
|
|
|
|
|
/// * If `shift = 1` then the diagonal is left untouched.
|
|
|
|
|
/// * If `shift > 1`, then the diagonal and the first `shift - 1` superdiagonals are left
|
|
|
|
|
/// untouched.
|
|
|
|
|
#[inline]
|
2021-07-16 12:56:58 +08:00
|
|
|
|
pub fn fill_upper_triangle(&mut self, val: T, shift: usize)
|
|
|
|
|
where
|
|
|
|
|
T: Clone,
|
|
|
|
|
{
|
2018-02-02 19:26:35 +08:00
|
|
|
|
for j in shift..self.ncols() {
|
2020-11-15 23:57:49 +08:00
|
|
|
|
// TODO: is there a more efficient way to avoid the min ?
|
2017-08-03 01:37:44 +08:00
|
|
|
|
// (necessary for rectangular matrices)
|
2018-02-02 19:26:35 +08:00
|
|
|
|
for i in 0..cmp::min(j + 1 - shift, self.nrows()) {
|
2021-07-16 12:56:58 +08:00
|
|
|
|
unsafe { *self.get_unchecked_mut((i, j)) = val.clone() }
|
2017-08-03 01:37:44 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-07-17 12:17:56 +08:00
|
|
|
|
impl<T: Clone, D: Dim, S: StorageMut<T, D, D>> Matrix<T, D, D, S> {
|
2017-08-03 01:37:44 +08:00
|
|
|
|
/// Copies the upper-triangle of this matrix to its lower-triangular part.
|
|
|
|
|
///
|
|
|
|
|
/// This makes the matrix symmetric. Panics if the matrix is not square.
|
|
|
|
|
pub fn fill_lower_triangle_with_upper_triangle(&mut self) {
|
|
|
|
|
assert!(self.is_square(), "The input matrix should be square.");
|
|
|
|
|
|
|
|
|
|
let dim = self.nrows();
|
2018-02-02 19:26:35 +08:00
|
|
|
|
for j in 0..dim {
|
|
|
|
|
for i in j + 1..dim {
|
2017-08-03 01:37:44 +08:00
|
|
|
|
unsafe {
|
2021-07-17 12:17:56 +08:00
|
|
|
|
*self.get_unchecked_mut((i, j)) = self.get_unchecked((j, i)).clone();
|
2017-08-03 01:37:44 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Copies the upper-triangle of this matrix to its upper-triangular part.
|
|
|
|
|
///
|
|
|
|
|
/// This makes the matrix symmetric. Panics if the matrix is not square.
|
|
|
|
|
pub fn fill_upper_triangle_with_lower_triangle(&mut self) {
|
|
|
|
|
assert!(self.is_square(), "The input matrix should be square.");
|
|
|
|
|
|
2018-02-02 19:26:35 +08:00
|
|
|
|
for j in 1..self.ncols() {
|
|
|
|
|
for i in 0..j {
|
2017-08-03 01:37:44 +08:00
|
|
|
|
unsafe {
|
2021-07-17 12:17:56 +08:00
|
|
|
|
*self.get_unchecked_mut((i, j)) = self.get_unchecked((j, i)).clone();
|
2017-08-03 01:37:44 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-15 23:57:49 +08:00
|
|
|
|
/// # In-place swapping
|
2021-07-17 12:17:56 +08:00
|
|
|
|
impl<T, R: Dim, C: Dim, S: StorageMut<T, R, C>> Matrix<T, R, C, S> {
|
2020-11-15 23:57:49 +08:00
|
|
|
|
/// Swaps two rows in-place.
|
|
|
|
|
#[inline]
|
|
|
|
|
pub fn swap_rows(&mut self, irow1: usize, irow2: usize) {
|
|
|
|
|
assert!(irow1 < self.nrows() && irow2 < self.nrows());
|
|
|
|
|
|
|
|
|
|
if irow1 != irow2 {
|
|
|
|
|
// TODO: optimize that.
|
|
|
|
|
for i in 0..self.ncols() {
|
|
|
|
|
unsafe { self.swap_unchecked((irow1, i), (irow2, i)) }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// Otherwise do nothing.
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Swaps two columns in-place.
|
|
|
|
|
#[inline]
|
|
|
|
|
pub fn swap_columns(&mut self, icol1: usize, icol2: usize) {
|
|
|
|
|
assert!(icol1 < self.ncols() && icol2 < self.ncols());
|
|
|
|
|
|
|
|
|
|
if icol1 != icol2 {
|
|
|
|
|
// TODO: optimize that.
|
|
|
|
|
for i in 0..self.nrows() {
|
|
|
|
|
unsafe { self.swap_unchecked((i, icol1), (i, icol2)) }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// Otherwise do nothing.
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-08-03 01:37:44 +08:00
|
|
|
|
/*
|
|
|
|
|
*
|
2020-11-15 23:57:49 +08:00
|
|
|
|
* TODO: specialize all the following for slices.
|
2017-08-03 01:37:44 +08:00
|
|
|
|
*
|
|
|
|
|
*/
|
2020-11-15 23:57:49 +08:00
|
|
|
|
/// # Rows and columns removal
|
2021-07-17 12:17:56 +08:00
|
|
|
|
impl<T: Clone, R: Dim, C: Dim, S: Storage<T, R, C>> Matrix<T, R, C, S> {
|
2017-08-03 01:37:44 +08:00
|
|
|
|
/*
|
|
|
|
|
*
|
|
|
|
|
* Column removal.
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
/// Removes the `i`-th column from this matrix.
|
|
|
|
|
#[inline]
|
2021-04-11 17:00:38 +08:00
|
|
|
|
pub fn remove_column(self, i: usize) -> OMatrix<T, R, DimDiff<C, U1>>
|
2018-02-02 19:26:35 +08:00
|
|
|
|
where
|
|
|
|
|
C: DimSub<U1>,
|
2021-04-11 17:00:38 +08:00
|
|
|
|
DefaultAllocator: Reallocator<T, R, C, R, DimDiff<C, U1>>,
|
2018-02-02 19:26:35 +08:00
|
|
|
|
{
|
2021-04-11 17:00:38 +08:00
|
|
|
|
self.remove_fixed_columns::<1>(i)
|
2017-08-03 01:37:44 +08:00
|
|
|
|
}
|
|
|
|
|
|
2019-04-08 23:29:32 +08:00
|
|
|
|
/// Removes all columns in `indices`
|
2019-04-09 04:32:26 +08:00
|
|
|
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
2021-04-11 17:00:38 +08:00
|
|
|
|
pub fn remove_columns_at(self, indices: &[usize]) -> OMatrix<T, R, Dynamic>
|
2019-04-08 23:29:32 +08:00
|
|
|
|
where
|
|
|
|
|
C: DimSub<Dynamic, Output = Dynamic>,
|
2021-04-11 17:00:38 +08:00
|
|
|
|
DefaultAllocator: Reallocator<T, R, C, R, Dynamic>,
|
2019-04-08 23:29:32 +08:00
|
|
|
|
{
|
|
|
|
|
let mut m = self.into_owned();
|
|
|
|
|
let (nrows, ncols) = m.data.shape();
|
|
|
|
|
let mut offset: usize = 0;
|
|
|
|
|
let mut target: usize = 0;
|
|
|
|
|
while offset + target < ncols.value() {
|
2019-04-09 05:10:27 +08:00
|
|
|
|
if indices.contains(&(target + offset)) {
|
2019-04-08 23:29:32 +08:00
|
|
|
|
offset += 1;
|
|
|
|
|
} else {
|
|
|
|
|
unsafe {
|
2020-11-16 21:59:53 +08:00
|
|
|
|
let ptr_source = m.data.ptr().add((target + offset) * nrows.value());
|
|
|
|
|
let ptr_target = m.data.ptr_mut().add(target * nrows.value());
|
2019-04-08 23:29:32 +08:00
|
|
|
|
|
|
|
|
|
ptr::copy(ptr_source, ptr_target, nrows.value());
|
|
|
|
|
target += 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
unsafe {
|
|
|
|
|
Matrix::from_data(DefaultAllocator::reallocate_copy(
|
|
|
|
|
nrows,
|
2019-04-09 05:10:27 +08:00
|
|
|
|
ncols.sub(Dynamic::from_usize(offset)),
|
2019-04-08 23:29:32 +08:00
|
|
|
|
m.data,
|
|
|
|
|
))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-04-09 05:10:27 +08:00
|
|
|
|
/// Removes all rows in `indices`
|
2019-04-09 04:32:26 +08:00
|
|
|
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
2021-04-11 17:00:38 +08:00
|
|
|
|
pub fn remove_rows_at(self, indices: &[usize]) -> OMatrix<T, Dynamic, C>
|
2019-04-08 23:29:32 +08:00
|
|
|
|
where
|
|
|
|
|
R: DimSub<Dynamic, Output = Dynamic>,
|
2021-04-11 17:00:38 +08:00
|
|
|
|
DefaultAllocator: Reallocator<T, R, C, Dynamic, C>,
|
2020-04-06 00:49:48 +08:00
|
|
|
|
{
|
2019-04-08 23:29:32 +08:00
|
|
|
|
let mut m = self.into_owned();
|
|
|
|
|
let (nrows, ncols) = m.data.shape();
|
|
|
|
|
let mut offset: usize = 0;
|
|
|
|
|
let mut target: usize = 0;
|
|
|
|
|
while offset + target < nrows.value() * ncols.value() {
|
2019-04-09 05:10:27 +08:00
|
|
|
|
if indices.contains(&((target + offset) % nrows.value())) {
|
2019-04-08 23:29:32 +08:00
|
|
|
|
offset += 1;
|
|
|
|
|
} else {
|
|
|
|
|
unsafe {
|
2020-11-16 21:59:53 +08:00
|
|
|
|
let ptr_source = m.data.ptr().add(target + offset);
|
|
|
|
|
let ptr_target = m.data.ptr_mut().add(target);
|
2019-04-08 23:29:32 +08:00
|
|
|
|
|
|
|
|
|
ptr::copy(ptr_source, ptr_target, 1);
|
|
|
|
|
target += 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
unsafe {
|
|
|
|
|
Matrix::from_data(DefaultAllocator::reallocate_copy(
|
2020-04-06 00:49:48 +08:00
|
|
|
|
nrows.sub(Dynamic::from_usize(offset / ncols.value())),
|
2019-04-08 23:29:32 +08:00
|
|
|
|
ncols,
|
|
|
|
|
m.data,
|
|
|
|
|
))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-08-14 01:53:04 +08:00
|
|
|
|
/// Removes `D::dim()` consecutive columns from this matrix, starting with the `i`-th
|
|
|
|
|
/// (included).
|
2017-08-03 01:37:44 +08:00
|
|
|
|
#[inline]
|
2021-04-11 17:00:38 +08:00
|
|
|
|
pub fn remove_fixed_columns<const D: usize>(
|
|
|
|
|
self,
|
|
|
|
|
i: usize,
|
|
|
|
|
) -> OMatrix<T, R, DimDiff<C, Const<D>>>
|
2018-02-02 19:26:35 +08:00
|
|
|
|
where
|
2021-04-11 17:00:38 +08:00
|
|
|
|
C: DimSub<Const<D>>,
|
|
|
|
|
DefaultAllocator: Reallocator<T, R, C, R, DimDiff<C, Const<D>>>,
|
2018-02-02 19:26:35 +08:00
|
|
|
|
{
|
2021-04-11 17:00:38 +08:00
|
|
|
|
self.remove_columns_generic(i, Const::<D>)
|
2017-08-03 01:37:44 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Removes `n` consecutive columns from this matrix, starting with the `i`-th (included).
|
|
|
|
|
#[inline]
|
2019-02-03 22:16:50 +08:00
|
|
|
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
2021-04-11 17:00:38 +08:00
|
|
|
|
pub fn remove_columns(self, i: usize, n: usize) -> OMatrix<T, R, Dynamic>
|
2018-02-02 19:26:35 +08:00
|
|
|
|
where
|
|
|
|
|
C: DimSub<Dynamic, Output = Dynamic>,
|
2021-04-11 17:00:38 +08:00
|
|
|
|
DefaultAllocator: Reallocator<T, R, C, R, Dynamic>,
|
2018-02-02 19:26:35 +08:00
|
|
|
|
{
|
2017-08-03 01:37:44 +08:00
|
|
|
|
self.remove_columns_generic(i, Dynamic::new(n))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Removes `nremove.value()` columns from this matrix, starting with the `i`-th (included).
|
|
|
|
|
///
|
|
|
|
|
/// This is the generic implementation of `.remove_columns(...)` and
|
|
|
|
|
/// `.remove_fixed_columns(...)` which have nicer API interfaces.
|
|
|
|
|
#[inline]
|
2021-04-11 17:00:38 +08:00
|
|
|
|
pub fn remove_columns_generic<D>(self, i: usize, nremove: D) -> OMatrix<T, R, DimDiff<C, D>>
|
2018-02-02 19:26:35 +08:00
|
|
|
|
where
|
|
|
|
|
D: Dim,
|
|
|
|
|
C: DimSub<D>,
|
2021-04-11 17:00:38 +08:00
|
|
|
|
DefaultAllocator: Reallocator<T, R, C, R, DimDiff<C, D>>,
|
2018-02-02 19:26:35 +08:00
|
|
|
|
{
|
2017-08-03 01:37:44 +08:00
|
|
|
|
let mut m = self.into_owned();
|
|
|
|
|
let (nrows, ncols) = m.data.shape();
|
2018-02-02 19:26:35 +08:00
|
|
|
|
assert!(
|
|
|
|
|
i + nremove.value() <= ncols.value(),
|
|
|
|
|
"Column index out of range."
|
|
|
|
|
);
|
2017-08-03 01:37:44 +08:00
|
|
|
|
|
|
|
|
|
if nremove.value() != 0 && i + nremove.value() < ncols.value() {
|
|
|
|
|
// The first `deleted_i * nrows` are left untouched.
|
|
|
|
|
let copied_value_start = i + nremove.value();
|
|
|
|
|
|
|
|
|
|
unsafe {
|
2020-11-16 21:59:53 +08:00
|
|
|
|
let ptr_in = m.data.ptr().add(copied_value_start * nrows.value());
|
|
|
|
|
let ptr_out = m.data.ptr_mut().add(i * nrows.value());
|
2017-08-03 01:37:44 +08:00
|
|
|
|
|
2018-02-02 19:26:35 +08:00
|
|
|
|
ptr::copy(
|
|
|
|
|
ptr_in,
|
|
|
|
|
ptr_out,
|
|
|
|
|
(ncols.value() - copied_value_start) * nrows.value(),
|
|
|
|
|
);
|
2017-08-03 01:37:44 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
unsafe {
|
2018-02-02 19:26:35 +08:00
|
|
|
|
Matrix::from_data(DefaultAllocator::reallocate_copy(
|
|
|
|
|
nrows,
|
|
|
|
|
ncols.sub(nremove),
|
|
|
|
|
m.data,
|
|
|
|
|
))
|
2017-08-03 01:37:44 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
*
|
|
|
|
|
* Row removal.
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
/// Removes the `i`-th row from this matrix.
|
|
|
|
|
#[inline]
|
2021-04-11 17:00:38 +08:00
|
|
|
|
pub fn remove_row(self, i: usize) -> OMatrix<T, DimDiff<R, U1>, C>
|
2018-02-02 19:26:35 +08:00
|
|
|
|
where
|
|
|
|
|
R: DimSub<U1>,
|
2021-04-11 17:00:38 +08:00
|
|
|
|
DefaultAllocator: Reallocator<T, R, C, DimDiff<R, U1>, C>,
|
2018-02-02 19:26:35 +08:00
|
|
|
|
{
|
2021-04-11 17:00:38 +08:00
|
|
|
|
self.remove_fixed_rows::<1>(i)
|
2017-08-03 01:37:44 +08:00
|
|
|
|
}
|
|
|
|
|
|
2017-08-14 01:53:04 +08:00
|
|
|
|
/// Removes `D::dim()` consecutive rows from this matrix, starting with the `i`-th (included).
|
2017-08-03 01:37:44 +08:00
|
|
|
|
#[inline]
|
2021-04-11 17:00:38 +08:00
|
|
|
|
pub fn remove_fixed_rows<const D: usize>(self, i: usize) -> OMatrix<T, DimDiff<R, Const<D>>, C>
|
2018-02-02 19:26:35 +08:00
|
|
|
|
where
|
2021-04-11 17:00:38 +08:00
|
|
|
|
R: DimSub<Const<D>>,
|
|
|
|
|
DefaultAllocator: Reallocator<T, R, C, DimDiff<R, Const<D>>, C>,
|
2018-02-02 19:26:35 +08:00
|
|
|
|
{
|
2021-04-11 17:00:38 +08:00
|
|
|
|
self.remove_rows_generic(i, Const::<D>)
|
2017-08-03 01:37:44 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Removes `n` consecutive rows from this matrix, starting with the `i`-th (included).
|
|
|
|
|
#[inline]
|
2019-02-03 22:16:50 +08:00
|
|
|
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
2021-04-11 17:00:38 +08:00
|
|
|
|
pub fn remove_rows(self, i: usize, n: usize) -> OMatrix<T, Dynamic, C>
|
2018-02-02 19:26:35 +08:00
|
|
|
|
where
|
|
|
|
|
R: DimSub<Dynamic, Output = Dynamic>,
|
2021-04-11 17:00:38 +08:00
|
|
|
|
DefaultAllocator: Reallocator<T, R, C, Dynamic, C>,
|
2018-02-02 19:26:35 +08:00
|
|
|
|
{
|
2017-08-03 01:37:44 +08:00
|
|
|
|
self.remove_rows_generic(i, Dynamic::new(n))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Removes `nremove.value()` rows from this matrix, starting with the `i`-th (included).
|
|
|
|
|
///
|
|
|
|
|
/// This is the generic implementation of `.remove_rows(...)` and `.remove_fixed_rows(...)`
|
|
|
|
|
/// which have nicer API interfaces.
|
|
|
|
|
#[inline]
|
2021-04-11 17:00:38 +08:00
|
|
|
|
pub fn remove_rows_generic<D>(self, i: usize, nremove: D) -> OMatrix<T, DimDiff<R, D>, C>
|
2018-02-02 19:26:35 +08:00
|
|
|
|
where
|
|
|
|
|
D: Dim,
|
|
|
|
|
R: DimSub<D>,
|
2021-04-11 17:00:38 +08:00
|
|
|
|
DefaultAllocator: Reallocator<T, R, C, DimDiff<R, D>, C>,
|
2018-02-02 19:26:35 +08:00
|
|
|
|
{
|
2017-08-03 01:37:44 +08:00
|
|
|
|
let mut m = self.into_owned();
|
|
|
|
|
let (nrows, ncols) = m.data.shape();
|
2018-02-02 19:26:35 +08:00
|
|
|
|
assert!(
|
|
|
|
|
i + nremove.value() <= nrows.value(),
|
|
|
|
|
"Row index out of range."
|
|
|
|
|
);
|
2017-08-03 01:37:44 +08:00
|
|
|
|
|
|
|
|
|
if nremove.value() != 0 {
|
|
|
|
|
unsafe {
|
2018-02-02 19:26:35 +08:00
|
|
|
|
compress_rows(
|
|
|
|
|
&mut m.data.as_mut_slice(),
|
|
|
|
|
nrows.value(),
|
|
|
|
|
ncols.value(),
|
|
|
|
|
i,
|
|
|
|
|
nremove.value(),
|
|
|
|
|
);
|
2017-08-03 01:37:44 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
unsafe {
|
2018-02-02 19:26:35 +08:00
|
|
|
|
Matrix::from_data(DefaultAllocator::reallocate_copy(
|
|
|
|
|
nrows.sub(nremove),
|
|
|
|
|
ncols,
|
|
|
|
|
m.data,
|
|
|
|
|
))
|
2017-08-03 01:37:44 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
2020-11-15 23:57:49 +08:00
|
|
|
|
}
|
2017-08-03 01:37:44 +08:00
|
|
|
|
|
2020-11-15 23:57:49 +08:00
|
|
|
|
/// # Rows and columns insertion
|
2021-07-17 12:17:56 +08:00
|
|
|
|
impl<T: Clone, R: Dim, C: Dim, S: Storage<T, R, C>> Matrix<T, R, C, S> {
|
2017-08-03 01:37:44 +08:00
|
|
|
|
/*
|
|
|
|
|
*
|
|
|
|
|
* Columns insertion.
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
/// Inserts a column filled with `val` at the `i-th` position.
|
|
|
|
|
#[inline]
|
2021-04-11 17:00:38 +08:00
|
|
|
|
pub fn insert_column(self, i: usize, val: T) -> OMatrix<T, R, DimSum<C, U1>>
|
2018-02-02 19:26:35 +08:00
|
|
|
|
where
|
|
|
|
|
C: DimAdd<U1>,
|
2021-04-11 17:00:38 +08:00
|
|
|
|
DefaultAllocator: Reallocator<T, R, C, R, DimSum<C, U1>>,
|
2018-02-02 19:26:35 +08:00
|
|
|
|
{
|
2021-04-11 17:00:38 +08:00
|
|
|
|
self.insert_fixed_columns::<1>(i, val)
|
2017-08-03 01:37:44 +08:00
|
|
|
|
}
|
|
|
|
|
|
2021-04-11 17:00:38 +08:00
|
|
|
|
/// Inserts `D` columns filled with `val` starting at the `i-th` position.
|
2017-08-03 01:37:44 +08:00
|
|
|
|
#[inline]
|
2021-04-11 17:00:38 +08:00
|
|
|
|
pub fn insert_fixed_columns<const D: usize>(
|
|
|
|
|
self,
|
|
|
|
|
i: usize,
|
|
|
|
|
val: T,
|
|
|
|
|
) -> OMatrix<T, R, DimSum<C, Const<D>>>
|
2018-02-02 19:26:35 +08:00
|
|
|
|
where
|
2021-04-11 17:00:38 +08:00
|
|
|
|
C: DimAdd<Const<D>>,
|
|
|
|
|
DefaultAllocator: Reallocator<T, R, C, R, DimSum<C, Const<D>>>,
|
2018-02-02 19:26:35 +08:00
|
|
|
|
{
|
2021-04-11 17:00:38 +08:00
|
|
|
|
let mut res = unsafe { self.insert_columns_generic_uninitialized(i, Const::<D>) };
|
2017-08-03 01:37:44 +08:00
|
|
|
|
res.fixed_columns_mut::<D>(i).fill(val);
|
|
|
|
|
res
|
|
|
|
|
}
|
|
|
|
|
|
2017-08-14 01:53:04 +08:00
|
|
|
|
/// Inserts `n` columns filled with `val` starting at the `i-th` position.
|
2017-08-03 01:37:44 +08:00
|
|
|
|
#[inline]
|
2019-02-03 22:16:50 +08:00
|
|
|
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
2021-04-11 17:00:38 +08:00
|
|
|
|
pub fn insert_columns(self, i: usize, n: usize, val: T) -> OMatrix<T, R, Dynamic>
|
2018-02-02 19:26:35 +08:00
|
|
|
|
where
|
|
|
|
|
C: DimAdd<Dynamic, Output = Dynamic>,
|
2021-04-11 17:00:38 +08:00
|
|
|
|
DefaultAllocator: Reallocator<T, R, C, R, Dynamic>,
|
2018-02-02 19:26:35 +08:00
|
|
|
|
{
|
2017-08-03 01:37:44 +08:00
|
|
|
|
let mut res = unsafe { self.insert_columns_generic_uninitialized(i, Dynamic::new(n)) };
|
|
|
|
|
res.columns_mut(i, n).fill(val);
|
|
|
|
|
res
|
|
|
|
|
}
|
|
|
|
|
|
2017-08-14 01:53:04 +08:00
|
|
|
|
/// Inserts `ninsert.value()` columns starting at the `i-th` place of this matrix.
|
2017-08-03 01:37:44 +08:00
|
|
|
|
///
|
2021-07-04 11:19:07 +08:00
|
|
|
|
/// # Safety
|
2017-08-03 01:37:44 +08:00
|
|
|
|
/// The added column values are not initialized.
|
|
|
|
|
#[inline]
|
2018-02-02 19:26:35 +08:00
|
|
|
|
pub unsafe fn insert_columns_generic_uninitialized<D>(
|
|
|
|
|
self,
|
|
|
|
|
i: usize,
|
|
|
|
|
ninsert: D,
|
2021-04-11 17:00:38 +08:00
|
|
|
|
) -> OMatrix<T, R, DimSum<C, D>>
|
2018-02-02 19:26:35 +08:00
|
|
|
|
where
|
|
|
|
|
D: Dim,
|
|
|
|
|
C: DimAdd<D>,
|
2021-04-11 17:00:38 +08:00
|
|
|
|
DefaultAllocator: Reallocator<T, R, C, R, DimSum<C, D>>,
|
2018-02-02 19:26:35 +08:00
|
|
|
|
{
|
2017-08-03 01:37:44 +08:00
|
|
|
|
let m = self.into_owned();
|
|
|
|
|
let (nrows, ncols) = m.data.shape();
|
2018-02-02 19:26:35 +08:00
|
|
|
|
let mut res = Matrix::from_data(DefaultAllocator::reallocate_copy(
|
|
|
|
|
nrows,
|
|
|
|
|
ncols.add(ninsert),
|
|
|
|
|
m.data,
|
|
|
|
|
));
|
2017-08-03 01:37:44 +08:00
|
|
|
|
|
|
|
|
|
assert!(i <= ncols.value(), "Column insertion index out of range.");
|
|
|
|
|
|
|
|
|
|
if ninsert.value() != 0 && i != ncols.value() {
|
2020-11-16 21:59:53 +08:00
|
|
|
|
let ptr_in = res.data.ptr().add(i * nrows.value());
|
2018-10-21 04:26:44 +08:00
|
|
|
|
let ptr_out = res
|
|
|
|
|
.data
|
2018-02-02 19:26:35 +08:00
|
|
|
|
.ptr_mut()
|
2020-11-16 21:59:53 +08:00
|
|
|
|
.add((i + ninsert.value()) * nrows.value());
|
2017-08-03 01:37:44 +08:00
|
|
|
|
|
|
|
|
|
ptr::copy(ptr_in, ptr_out, (ncols.value() - i) * nrows.value())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
res
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
*
|
|
|
|
|
* Rows insertion.
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
/// Inserts a row filled with `val` at the `i-th` position.
|
|
|
|
|
#[inline]
|
2021-04-11 17:00:38 +08:00
|
|
|
|
pub fn insert_row(self, i: usize, val: T) -> OMatrix<T, DimSum<R, U1>, C>
|
2018-02-02 19:26:35 +08:00
|
|
|
|
where
|
|
|
|
|
R: DimAdd<U1>,
|
2021-04-11 17:00:38 +08:00
|
|
|
|
DefaultAllocator: Reallocator<T, R, C, DimSum<R, U1>, C>,
|
2018-02-02 19:26:35 +08:00
|
|
|
|
{
|
2021-04-11 17:00:38 +08:00
|
|
|
|
self.insert_fixed_rows::<1>(i, val)
|
2017-08-03 01:37:44 +08:00
|
|
|
|
}
|
|
|
|
|
|
2017-08-14 01:53:04 +08:00
|
|
|
|
/// Inserts `D::dim()` rows filled with `val` starting at the `i-th` position.
|
2017-08-03 01:37:44 +08:00
|
|
|
|
#[inline]
|
2021-04-11 17:00:38 +08:00
|
|
|
|
pub fn insert_fixed_rows<const D: usize>(
|
|
|
|
|
self,
|
|
|
|
|
i: usize,
|
|
|
|
|
val: T,
|
|
|
|
|
) -> OMatrix<T, DimSum<R, Const<D>>, C>
|
2018-02-02 19:26:35 +08:00
|
|
|
|
where
|
2021-04-11 17:00:38 +08:00
|
|
|
|
R: DimAdd<Const<D>>,
|
|
|
|
|
DefaultAllocator: Reallocator<T, R, C, DimSum<R, Const<D>>, C>,
|
2018-02-02 19:26:35 +08:00
|
|
|
|
{
|
2021-04-11 17:00:38 +08:00
|
|
|
|
let mut res = unsafe { self.insert_rows_generic_uninitialized(i, Const::<D>) };
|
2017-08-03 01:37:44 +08:00
|
|
|
|
res.fixed_rows_mut::<D>(i).fill(val);
|
|
|
|
|
res
|
|
|
|
|
}
|
|
|
|
|
|
2017-08-14 01:53:04 +08:00
|
|
|
|
/// Inserts `n` rows filled with `val` starting at the `i-th` position.
|
2017-08-03 01:37:44 +08:00
|
|
|
|
#[inline]
|
2019-02-03 22:16:50 +08:00
|
|
|
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
2021-04-11 17:00:38 +08:00
|
|
|
|
pub fn insert_rows(self, i: usize, n: usize, val: T) -> OMatrix<T, Dynamic, C>
|
2018-02-02 19:26:35 +08:00
|
|
|
|
where
|
|
|
|
|
R: DimAdd<Dynamic, Output = Dynamic>,
|
2021-04-11 17:00:38 +08:00
|
|
|
|
DefaultAllocator: Reallocator<T, R, C, Dynamic, C>,
|
2018-02-02 19:26:35 +08:00
|
|
|
|
{
|
2017-08-03 01:37:44 +08:00
|
|
|
|
let mut res = unsafe { self.insert_rows_generic_uninitialized(i, Dynamic::new(n)) };
|
|
|
|
|
res.rows_mut(i, n).fill(val);
|
|
|
|
|
res
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Inserts `ninsert.value()` rows at the `i-th` place of this matrix.
|
|
|
|
|
///
|
2021-07-04 11:19:07 +08:00
|
|
|
|
/// # Safety
|
2017-08-03 01:37:44 +08:00
|
|
|
|
/// The added rows values are not initialized.
|
2017-08-14 01:53:04 +08:00
|
|
|
|
/// This is the generic implementation of `.insert_rows(...)` and
|
|
|
|
|
/// `.insert_fixed_rows(...)` which have nicer API interfaces.
|
2017-08-03 01:37:44 +08:00
|
|
|
|
#[inline]
|
2018-02-02 19:26:35 +08:00
|
|
|
|
pub unsafe fn insert_rows_generic_uninitialized<D>(
|
|
|
|
|
self,
|
|
|
|
|
i: usize,
|
|
|
|
|
ninsert: D,
|
2021-04-11 17:00:38 +08:00
|
|
|
|
) -> OMatrix<T, DimSum<R, D>, C>
|
2018-02-02 19:26:35 +08:00
|
|
|
|
where
|
|
|
|
|
D: Dim,
|
|
|
|
|
R: DimAdd<D>,
|
2021-04-11 17:00:38 +08:00
|
|
|
|
DefaultAllocator: Reallocator<T, R, C, DimSum<R, D>, C>,
|
2018-02-02 19:26:35 +08:00
|
|
|
|
{
|
2017-08-03 01:37:44 +08:00
|
|
|
|
let m = self.into_owned();
|
|
|
|
|
let (nrows, ncols) = m.data.shape();
|
2018-02-02 19:26:35 +08:00
|
|
|
|
let mut res = Matrix::from_data(DefaultAllocator::reallocate_copy(
|
|
|
|
|
nrows.add(ninsert),
|
|
|
|
|
ncols,
|
|
|
|
|
m.data,
|
|
|
|
|
));
|
2017-08-03 01:37:44 +08:00
|
|
|
|
|
|
|
|
|
assert!(i <= nrows.value(), "Row insertion index out of range.");
|
|
|
|
|
|
|
|
|
|
if ninsert.value() != 0 {
|
2018-02-02 19:26:35 +08:00
|
|
|
|
extend_rows(
|
|
|
|
|
&mut res.data.as_mut_slice(),
|
|
|
|
|
nrows.value(),
|
|
|
|
|
ncols.value(),
|
|
|
|
|
i,
|
|
|
|
|
ninsert.value(),
|
|
|
|
|
);
|
2017-08-03 01:37:44 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
res
|
|
|
|
|
}
|
2020-11-15 23:57:49 +08:00
|
|
|
|
}
|
2017-08-03 01:37:44 +08:00
|
|
|
|
|
2020-11-15 23:57:49 +08:00
|
|
|
|
/// # Resizing and reshaping
|
2021-07-17 12:17:56 +08:00
|
|
|
|
impl<T: Clone, R: Dim, C: Dim, S: Storage<T, R, C>> Matrix<T, R, C, S> {
|
2017-08-14 01:52:57 +08:00
|
|
|
|
/// Resizes this matrix so that it contains `new_nrows` rows and `new_ncols` columns.
|
|
|
|
|
///
|
|
|
|
|
/// The values are copied such that `self[(i, j)] == result[(i, j)]`. If the result has more
|
|
|
|
|
/// rows and/or columns than `self`, then the extra rows or columns are filled with `val`.
|
2018-05-19 23:15:15 +08:00
|
|
|
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
2021-04-12 16:34:15 +08:00
|
|
|
|
pub fn resize(self, new_nrows: usize, new_ncols: usize, val: T) -> OMatrix<T, Dynamic, Dynamic>
|
2020-04-06 00:49:48 +08:00
|
|
|
|
where
|
2021-04-11 17:00:38 +08:00
|
|
|
|
DefaultAllocator: Reallocator<T, R, C, Dynamic, Dynamic>,
|
2020-04-06 00:49:48 +08:00
|
|
|
|
{
|
2017-08-03 01:37:44 +08:00
|
|
|
|
self.resize_generic(Dynamic::new(new_nrows), Dynamic::new(new_ncols), val)
|
|
|
|
|
}
|
|
|
|
|
|
2019-01-29 19:03:48 +08:00
|
|
|
|
/// Resizes this matrix vertically, i.e., so that it contains `new_nrows` rows while keeping the same number of columns.
|
|
|
|
|
///
|
|
|
|
|
/// The values are copied such that `self[(i, j)] == result[(i, j)]`. If the result has more
|
|
|
|
|
/// rows than `self`, then the extra rows are filled with `val`.
|
|
|
|
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
2021-04-11 17:00:38 +08:00
|
|
|
|
pub fn resize_vertically(self, new_nrows: usize, val: T) -> OMatrix<T, Dynamic, C>
|
2020-04-06 00:49:48 +08:00
|
|
|
|
where
|
2021-04-11 17:00:38 +08:00
|
|
|
|
DefaultAllocator: Reallocator<T, R, C, Dynamic, C>,
|
2020-04-06 00:49:48 +08:00
|
|
|
|
{
|
2019-01-29 19:03:48 +08:00
|
|
|
|
let ncols = self.data.shape().1;
|
|
|
|
|
self.resize_generic(Dynamic::new(new_nrows), ncols, val)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Resizes this matrix horizontally, i.e., so that it contains `new_ncolumns` columns while keeping the same number of columns.
|
|
|
|
|
///
|
|
|
|
|
/// The values are copied such that `self[(i, j)] == result[(i, j)]`. If the result has more
|
|
|
|
|
/// columns than `self`, then the extra columns are filled with `val`.
|
|
|
|
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
2021-04-11 17:00:38 +08:00
|
|
|
|
pub fn resize_horizontally(self, new_ncols: usize, val: T) -> OMatrix<T, R, Dynamic>
|
2020-04-06 00:49:48 +08:00
|
|
|
|
where
|
2021-04-11 17:00:38 +08:00
|
|
|
|
DefaultAllocator: Reallocator<T, R, C, R, Dynamic>,
|
2020-04-06 00:49:48 +08:00
|
|
|
|
{
|
2019-01-29 19:03:48 +08:00
|
|
|
|
let nrows = self.data.shape().0;
|
|
|
|
|
self.resize_generic(nrows, Dynamic::new(new_ncols), val)
|
|
|
|
|
}
|
|
|
|
|
|
2017-08-14 01:52:57 +08:00
|
|
|
|
/// Resizes this matrix so that it contains `R2::value()` rows and `C2::value()` columns.
|
|
|
|
|
///
|
|
|
|
|
/// The values are copied such that `self[(i, j)] == result[(i, j)]`. If the result has more
|
|
|
|
|
/// rows and/or columns than `self`, then the extra rows or columns are filled with `val`.
|
2021-04-12 16:34:15 +08:00
|
|
|
|
pub fn fixed_resize<const R2: usize, const C2: usize>(
|
|
|
|
|
self,
|
|
|
|
|
val: T,
|
|
|
|
|
) -> OMatrix<T, Const<R2>, Const<C2>>
|
2020-04-06 00:49:48 +08:00
|
|
|
|
where
|
2021-04-11 17:00:38 +08:00
|
|
|
|
DefaultAllocator: Reallocator<T, R, C, Const<R2>, Const<C2>>,
|
2020-04-06 00:49:48 +08:00
|
|
|
|
{
|
2021-04-11 17:00:38 +08:00
|
|
|
|
self.resize_generic(Const::<R2>, Const::<C2>, val)
|
2017-08-03 01:37:44 +08:00
|
|
|
|
}
|
|
|
|
|
|
2020-08-19 13:52:26 +08:00
|
|
|
|
/// Resizes `self` such that it has dimensions `new_nrows × new_ncols`.
|
2017-08-14 01:52:57 +08:00
|
|
|
|
///
|
|
|
|
|
/// The values are copied such that `self[(i, j)] == result[(i, j)]`. If the result has more
|
|
|
|
|
/// rows and/or columns than `self`, then the extra rows or columns are filled with `val`.
|
2017-08-03 01:37:44 +08:00
|
|
|
|
#[inline]
|
2018-02-02 19:26:35 +08:00
|
|
|
|
pub fn resize_generic<R2: Dim, C2: Dim>(
|
|
|
|
|
self,
|
|
|
|
|
new_nrows: R2,
|
|
|
|
|
new_ncols: C2,
|
2021-04-11 17:00:38 +08:00
|
|
|
|
val: T,
|
|
|
|
|
) -> OMatrix<T, R2, C2>
|
2018-02-02 19:26:35 +08:00
|
|
|
|
where
|
2021-04-11 17:00:38 +08:00
|
|
|
|
DefaultAllocator: Reallocator<T, R, C, R2, C2>,
|
2018-02-02 19:26:35 +08:00
|
|
|
|
{
|
2017-08-03 01:37:44 +08:00
|
|
|
|
let (nrows, ncols) = self.shape();
|
|
|
|
|
let mut data = self.data.into_owned();
|
|
|
|
|
|
|
|
|
|
if new_nrows.value() == nrows {
|
|
|
|
|
let res = unsafe { DefaultAllocator::reallocate_copy(new_nrows, new_ncols, data) };
|
2018-05-19 23:15:15 +08:00
|
|
|
|
let mut res = Matrix::from_data(res);
|
2018-02-03 17:46:04 +08:00
|
|
|
|
if new_ncols.value() > ncols {
|
|
|
|
|
res.columns_range_mut(ncols..).fill(val);
|
|
|
|
|
}
|
2017-08-03 01:37:44 +08:00
|
|
|
|
|
2018-02-03 17:46:04 +08:00
|
|
|
|
res
|
2018-02-02 19:26:35 +08:00
|
|
|
|
} else {
|
2017-08-03 01:37:44 +08:00
|
|
|
|
let mut res;
|
|
|
|
|
|
|
|
|
|
unsafe {
|
|
|
|
|
if new_nrows.value() < nrows {
|
2018-02-02 19:26:35 +08:00
|
|
|
|
compress_rows(
|
|
|
|
|
&mut data.as_mut_slice(),
|
|
|
|
|
nrows,
|
|
|
|
|
ncols,
|
|
|
|
|
new_nrows.value(),
|
|
|
|
|
nrows - new_nrows.value(),
|
|
|
|
|
);
|
|
|
|
|
res = Matrix::from_data(DefaultAllocator::reallocate_copy(
|
2018-05-19 23:15:15 +08:00
|
|
|
|
new_nrows, new_ncols, data,
|
2018-02-02 19:26:35 +08:00
|
|
|
|
));
|
|
|
|
|
} else {
|
|
|
|
|
res = Matrix::from_data(DefaultAllocator::reallocate_copy(
|
2018-05-19 23:15:15 +08:00
|
|
|
|
new_nrows, new_ncols, data,
|
2018-02-02 19:26:35 +08:00
|
|
|
|
));
|
|
|
|
|
extend_rows(
|
|
|
|
|
&mut res.data.as_mut_slice(),
|
|
|
|
|
nrows,
|
2018-02-03 17:46:04 +08:00
|
|
|
|
new_ncols.value(),
|
2018-02-02 19:26:35 +08:00
|
|
|
|
nrows,
|
|
|
|
|
new_nrows.value() - nrows,
|
|
|
|
|
);
|
2017-08-03 01:37:44 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if new_ncols.value() > ncols {
|
2021-07-17 12:17:56 +08:00
|
|
|
|
res.columns_range_mut(ncols..).fill(val.clone());
|
2017-08-03 01:37:44 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if new_nrows.value() > nrows {
|
2018-02-02 19:26:35 +08:00
|
|
|
|
res.slice_range_mut(nrows.., ..cmp::min(ncols, new_ncols.value()))
|
|
|
|
|
.fill(val);
|
2017-08-03 01:37:44 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
res
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-25 23:03:18 +08:00
|
|
|
|
/// Reshapes `self` such that it has dimensions `new_nrows × new_ncols`.
|
2020-08-19 13:52:26 +08:00
|
|
|
|
///
|
2020-10-25 23:03:18 +08:00
|
|
|
|
/// This will reinterpret `self` as if it is a matrix with `new_nrows` rows and `new_ncols`
|
|
|
|
|
/// columns. The arrangements of the component in the output matrix are the same as what
|
|
|
|
|
/// would be obtained by `Matrix::from_slice_generic(self.as_slice(), new_nrows, new_ncols)`.
|
|
|
|
|
///
|
|
|
|
|
/// If `self` is a dynamically-sized matrix, then its components are neither copied nor moved.
|
|
|
|
|
/// If `self` is staticyll-sized, then a copy may happen in some situations.
|
|
|
|
|
/// This function will panic if the given dimensions are such that the number of elements of
|
|
|
|
|
/// the input matrix are not equal to the number of elements of the output matrix.
|
|
|
|
|
///
|
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
|
|
|
|
/// ```
|
2021-01-03 22:20:34 +08:00
|
|
|
|
/// # use nalgebra::{Matrix3x2, Matrix2x3, DMatrix, Const, Dynamic};
|
2020-10-25 23:03:18 +08:00
|
|
|
|
///
|
|
|
|
|
/// let m1 = Matrix2x3::new(
|
|
|
|
|
/// 1.1, 1.2, 1.3,
|
|
|
|
|
/// 2.1, 2.2, 2.3
|
|
|
|
|
/// );
|
|
|
|
|
/// let m2 = Matrix3x2::new(
|
|
|
|
|
/// 1.1, 2.2,
|
|
|
|
|
/// 2.1, 1.3,
|
|
|
|
|
/// 1.2, 2.3
|
|
|
|
|
/// );
|
2021-01-03 22:20:34 +08:00
|
|
|
|
/// let reshaped = m1.reshape_generic(Const::<3>, Const::<2>);
|
2020-10-25 23:03:18 +08:00
|
|
|
|
/// assert_eq!(reshaped, m2);
|
|
|
|
|
///
|
|
|
|
|
/// let dm1 = DMatrix::from_row_slice(
|
|
|
|
|
/// 4,
|
|
|
|
|
/// 3,
|
|
|
|
|
/// &[
|
|
|
|
|
/// 1.0, 0.0, 0.0,
|
|
|
|
|
/// 0.0, 0.0, 1.0,
|
|
|
|
|
/// 0.0, 0.0, 0.0,
|
|
|
|
|
/// 0.0, 1.0, 0.0
|
|
|
|
|
/// ],
|
|
|
|
|
/// );
|
|
|
|
|
/// let dm2 = DMatrix::from_row_slice(
|
|
|
|
|
/// 6,
|
|
|
|
|
/// 2,
|
|
|
|
|
/// &[
|
2020-10-25 23:20:27 +08:00
|
|
|
|
/// 1.0, 0.0,
|
|
|
|
|
/// 0.0, 1.0,
|
|
|
|
|
/// 0.0, 0.0,
|
|
|
|
|
/// 0.0, 1.0,
|
|
|
|
|
/// 0.0, 0.0,
|
|
|
|
|
/// 0.0, 0.0,
|
2020-10-25 23:03:18 +08:00
|
|
|
|
/// ],
|
|
|
|
|
/// );
|
|
|
|
|
/// let reshaped = dm1.reshape_generic(Dynamic::new(6), Dynamic::new(2));
|
|
|
|
|
/// assert_eq!(reshaped, dm2);
|
|
|
|
|
/// ```
|
2020-08-19 13:52:26 +08:00
|
|
|
|
pub fn reshape_generic<R2, C2>(
|
|
|
|
|
self,
|
|
|
|
|
new_nrows: R2,
|
|
|
|
|
new_ncols: C2,
|
2021-04-11 17:00:38 +08:00
|
|
|
|
) -> Matrix<T, R2, C2, S::Output>
|
2020-08-19 13:52:26 +08:00
|
|
|
|
where
|
|
|
|
|
R2: Dim,
|
|
|
|
|
C2: Dim,
|
2021-04-11 17:00:38 +08:00
|
|
|
|
S: ReshapableStorage<T, R, C, R2, C2>,
|
2020-08-19 13:52:26 +08:00
|
|
|
|
{
|
|
|
|
|
let data = self.data.reshape_generic(new_nrows, new_ncols);
|
|
|
|
|
Matrix::from_data(data)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-15 23:57:49 +08:00
|
|
|
|
/// # In-place resizing
|
2019-02-03 22:16:50 +08:00
|
|
|
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
2021-07-17 12:17:56 +08:00
|
|
|
|
impl<T: Clone> OMatrix<T, Dynamic, Dynamic> {
|
2019-01-29 19:03:48 +08:00
|
|
|
|
/// Resizes this matrix in-place.
|
|
|
|
|
///
|
|
|
|
|
/// The values are copied such that `self[(i, j)] == result[(i, j)]`. If the result has more
|
|
|
|
|
/// rows and/or columns than `self`, then the extra rows or columns are filled with `val`.
|
|
|
|
|
///
|
|
|
|
|
/// Defined only for owned fully-dynamic matrices, i.e., `DMatrix`.
|
2021-04-11 17:00:38 +08:00
|
|
|
|
pub fn resize_mut(&mut self, new_nrows: usize, new_ncols: usize, val: T)
|
2020-04-06 00:49:48 +08:00
|
|
|
|
where
|
2021-04-11 17:00:38 +08:00
|
|
|
|
DefaultAllocator: Reallocator<T, Dynamic, Dynamic, Dynamic, Dynamic>,
|
2020-04-06 00:49:48 +08:00
|
|
|
|
{
|
2021-07-16 12:56:58 +08:00
|
|
|
|
let placeholder =
|
|
|
|
|
Matrix::new_uninitialized_generic(Dynamic::new(0), Dynamic::new(0)).assume_init();
|
2019-01-29 19:03:48 +08:00
|
|
|
|
let old = mem::replace(self, placeholder);
|
|
|
|
|
let new = old.resize(new_nrows, new_ncols, val);
|
|
|
|
|
let _ = mem::replace(self, new);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-02-03 22:16:50 +08:00
|
|
|
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
2021-07-17 12:17:56 +08:00
|
|
|
|
impl<T: Clone, C: Dim> OMatrix<T, Dynamic, C>
|
2020-04-06 00:49:48 +08:00
|
|
|
|
where
|
2021-04-11 17:00:38 +08:00
|
|
|
|
DefaultAllocator: Allocator<T, Dynamic, C>,
|
2019-04-08 23:29:32 +08:00
|
|
|
|
{
|
2019-01-29 19:03:48 +08:00
|
|
|
|
/// Changes the number of rows of this matrix in-place.
|
|
|
|
|
///
|
|
|
|
|
/// The values are copied such that `self[(i, j)] == result[(i, j)]`. If the result has more
|
|
|
|
|
/// rows than `self`, then the extra rows are filled with `val`.
|
|
|
|
|
///
|
|
|
|
|
/// Defined only for owned matrices with a dynamic number of rows (for example, `DVector`).
|
|
|
|
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
2021-04-11 17:00:38 +08:00
|
|
|
|
pub fn resize_vertically_mut(&mut self, new_nrows: usize, val: T)
|
2020-04-06 00:49:48 +08:00
|
|
|
|
where
|
2021-04-11 17:00:38 +08:00
|
|
|
|
DefaultAllocator: Reallocator<T, Dynamic, C, Dynamic, C>,
|
2020-04-06 00:49:48 +08:00
|
|
|
|
{
|
2021-07-16 12:56:58 +08:00
|
|
|
|
let placeholder = Matrix::from_fn_generic(Dynamic::new(0), self.data.shape().1, |_, _| val);
|
2019-01-29 19:03:48 +08:00
|
|
|
|
let old = mem::replace(self, placeholder);
|
|
|
|
|
let new = old.resize_vertically(new_nrows, val);
|
|
|
|
|
let _ = mem::replace(self, new);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-02-03 22:16:50 +08:00
|
|
|
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
2021-07-17 12:17:56 +08:00
|
|
|
|
impl<T: Clone, R: Dim> OMatrix<T, R, Dynamic>
|
2020-04-06 00:49:48 +08:00
|
|
|
|
where
|
2021-04-11 17:00:38 +08:00
|
|
|
|
DefaultAllocator: Allocator<T, R, Dynamic>,
|
2019-04-08 23:29:32 +08:00
|
|
|
|
{
|
2019-01-29 19:03:48 +08:00
|
|
|
|
/// Changes the number of column of this matrix in-place.
|
|
|
|
|
///
|
|
|
|
|
/// The values are copied such that `self[(i, j)] == result[(i, j)]`. If the result has more
|
|
|
|
|
/// columns than `self`, then the extra columns are filled with `val`.
|
|
|
|
|
///
|
|
|
|
|
/// Defined only for owned matrices with a dynamic number of columns (for example, `DVector`).
|
|
|
|
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
2021-04-11 17:00:38 +08:00
|
|
|
|
pub fn resize_horizontally_mut(&mut self, new_ncols: usize, val: T)
|
2020-04-06 00:49:48 +08:00
|
|
|
|
where
|
2021-04-11 17:00:38 +08:00
|
|
|
|
DefaultAllocator: Reallocator<T, R, Dynamic, R, Dynamic>,
|
2020-04-06 00:49:48 +08:00
|
|
|
|
{
|
2021-07-16 12:56:58 +08:00
|
|
|
|
let placeholder = Matrix::from_fn_generic(self.data.shape().0, Dynamic::new(0), |_, _| val);
|
2019-01-29 19:03:48 +08:00
|
|
|
|
let old = mem::replace(self, placeholder);
|
|
|
|
|
let new = old.resize_horizontally(new_ncols, val);
|
|
|
|
|
let _ = mem::replace(self, new);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-07-17 12:17:56 +08:00
|
|
|
|
unsafe fn compress_rows<T>(data: &mut [T], nrows: usize, ncols: usize, i: usize, nremove: usize) {
|
2017-08-03 01:37:44 +08:00
|
|
|
|
let new_nrows = nrows - nremove;
|
2018-02-03 17:46:04 +08:00
|
|
|
|
|
|
|
|
|
if new_nrows == 0 || ncols == 0 {
|
|
|
|
|
return; // Nothing to do as the output matrix is empty.
|
|
|
|
|
}
|
|
|
|
|
|
2018-02-02 19:26:35 +08:00
|
|
|
|
let ptr_in = data.as_ptr();
|
|
|
|
|
let ptr_out = data.as_mut_ptr();
|
2017-08-03 01:37:44 +08:00
|
|
|
|
|
|
|
|
|
let mut curr_i = i;
|
|
|
|
|
|
2018-02-02 19:26:35 +08:00
|
|
|
|
for k in 0..ncols - 1 {
|
|
|
|
|
ptr::copy(
|
2020-11-16 21:59:53 +08:00
|
|
|
|
ptr_in.add(curr_i + (k + 1) * nremove),
|
|
|
|
|
ptr_out.add(curr_i),
|
2018-02-02 19:26:35 +08:00
|
|
|
|
new_nrows,
|
|
|
|
|
);
|
2017-08-03 01:37:44 +08:00
|
|
|
|
|
|
|
|
|
curr_i += new_nrows;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Deal with the last column from which less values have to be copied.
|
|
|
|
|
let remaining_len = nrows - i - nremove;
|
2018-02-02 19:26:35 +08:00
|
|
|
|
ptr::copy(
|
2020-11-16 21:59:53 +08:00
|
|
|
|
ptr_in.add(nrows * ncols - remaining_len),
|
|
|
|
|
ptr_out.add(curr_i),
|
2018-02-02 19:26:35 +08:00
|
|
|
|
remaining_len,
|
|
|
|
|
);
|
2017-08-03 01:37:44 +08:00
|
|
|
|
}
|
|
|
|
|
|
2018-02-03 17:54:51 +08:00
|
|
|
|
// Moves entries of a matrix buffer to make place for `ninsert` emty rows starting at the `i-th` row index.
|
|
|
|
|
// The `data` buffer is assumed to contained at least `(nrows + ninsert) * ncols` elements.
|
2021-07-17 12:17:56 +08:00
|
|
|
|
unsafe fn extend_rows<T>(data: &mut [T], nrows: usize, ncols: usize, i: usize, ninsert: usize) {
|
2017-08-03 01:37:44 +08:00
|
|
|
|
let new_nrows = nrows + ninsert;
|
2018-02-03 17:46:04 +08:00
|
|
|
|
|
|
|
|
|
if new_nrows == 0 || ncols == 0 {
|
|
|
|
|
return; // Nothing to do as the output matrix is empty.
|
|
|
|
|
}
|
|
|
|
|
|
2018-02-02 19:26:35 +08:00
|
|
|
|
let ptr_in = data.as_ptr();
|
|
|
|
|
let ptr_out = data.as_mut_ptr();
|
2017-08-03 01:37:44 +08:00
|
|
|
|
|
|
|
|
|
let remaining_len = nrows - i;
|
|
|
|
|
let mut curr_i = new_nrows * ncols - remaining_len;
|
|
|
|
|
|
|
|
|
|
// Deal with the last column from which less values have to be copied.
|
2018-02-02 19:26:35 +08:00
|
|
|
|
ptr::copy(
|
2020-11-16 21:59:53 +08:00
|
|
|
|
ptr_in.add(nrows * ncols - remaining_len),
|
|
|
|
|
ptr_out.add(curr_i),
|
2018-02-02 19:26:35 +08:00
|
|
|
|
remaining_len,
|
|
|
|
|
);
|
2017-08-03 01:37:44 +08:00
|
|
|
|
|
2018-02-02 19:26:35 +08:00
|
|
|
|
for k in (0..ncols - 1).rev() {
|
2017-08-03 01:37:44 +08:00
|
|
|
|
curr_i -= new_nrows;
|
|
|
|
|
|
2020-11-16 21:59:53 +08:00
|
|
|
|
ptr::copy(ptr_in.add(k * nrows + i), ptr_out.add(curr_i), nrows);
|
2017-08-03 01:37:44 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
2018-11-11 07:02:52 +08:00
|
|
|
|
|
|
|
|
|
/// Extend the number of columns of the `Matrix` with elements from
|
|
|
|
|
/// a given iterator.
|
2019-02-03 22:16:50 +08:00
|
|
|
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
2021-04-11 17:00:38 +08:00
|
|
|
|
impl<T, R, S> Extend<T> for Matrix<T, R, Dynamic, S>
|
2018-11-11 07:02:52 +08:00
|
|
|
|
where
|
|
|
|
|
R: Dim,
|
2021-04-11 17:00:38 +08:00
|
|
|
|
S: Extend<T>,
|
2018-11-11 07:02:52 +08:00
|
|
|
|
{
|
|
|
|
|
/// Extend the number of columns of the `Matrix` with elements
|
|
|
|
|
/// from the given iterator.
|
|
|
|
|
///
|
|
|
|
|
/// # Example
|
|
|
|
|
/// ```
|
2021-04-11 17:00:38 +08:00
|
|
|
|
/// # use nalgebra::{DMatrix, Dynamic, Matrix, OMatrix, Matrix3};
|
2018-11-11 07:02:52 +08:00
|
|
|
|
///
|
|
|
|
|
/// let data = vec![0, 1, 2, // column 1
|
|
|
|
|
/// 3, 4, 5]; // column 2
|
|
|
|
|
///
|
2018-11-14 04:01:33 +08:00
|
|
|
|
/// let mut matrix = DMatrix::from_vec(3, 2, data);
|
2018-11-11 07:02:52 +08:00
|
|
|
|
///
|
|
|
|
|
/// matrix.extend(vec![6, 7, 8]); // column 3
|
|
|
|
|
///
|
|
|
|
|
/// assert!(matrix.eq(&Matrix3::new(0, 3, 6,
|
|
|
|
|
/// 1, 4, 7,
|
|
|
|
|
/// 2, 5, 8)));
|
|
|
|
|
/// ```
|
|
|
|
|
///
|
|
|
|
|
/// # Panics
|
|
|
|
|
/// This function panics if the number of elements yielded by the
|
|
|
|
|
/// given iterator is not a multiple of the number of rows of the
|
|
|
|
|
/// `Matrix`.
|
|
|
|
|
///
|
|
|
|
|
/// ```should_panic
|
2021-04-11 17:00:38 +08:00
|
|
|
|
/// # use nalgebra::{DMatrix, Dynamic, OMatrix};
|
2018-11-11 07:02:52 +08:00
|
|
|
|
/// let data = vec![0, 1, 2, // column 1
|
|
|
|
|
/// 3, 4, 5]; // column 2
|
|
|
|
|
///
|
2018-11-14 04:01:33 +08:00
|
|
|
|
/// let mut matrix = DMatrix::from_vec(3, 2, data);
|
2018-11-11 07:02:52 +08:00
|
|
|
|
///
|
2018-11-14 04:01:33 +08:00
|
|
|
|
/// // The following panics because the vec length is not a multiple of 3.
|
|
|
|
|
/// matrix.extend(vec![6, 7, 8, 9]);
|
2018-11-11 07:02:52 +08:00
|
|
|
|
/// ```
|
2021-04-11 17:00:38 +08:00
|
|
|
|
fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
|
2018-11-11 07:02:52 +08:00
|
|
|
|
self.data.extend(iter);
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-11-13 02:53:30 +08:00
|
|
|
|
|
|
|
|
|
/// Extend the number of rows of the `Vector` with elements from
|
|
|
|
|
/// a given iterator.
|
2019-02-03 22:16:50 +08:00
|
|
|
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
2021-04-11 17:00:38 +08:00
|
|
|
|
impl<T, S> Extend<T> for Matrix<T, Dynamic, U1, S>
|
2018-11-13 02:53:30 +08:00
|
|
|
|
where
|
2021-04-11 17:00:38 +08:00
|
|
|
|
S: Extend<T>,
|
2018-11-13 02:53:30 +08:00
|
|
|
|
{
|
|
|
|
|
/// Extend the number of rows of a `Vector` with elements
|
|
|
|
|
/// from the given iterator.
|
|
|
|
|
///
|
|
|
|
|
/// # Example
|
|
|
|
|
/// ```
|
2018-11-14 04:01:33 +08:00
|
|
|
|
/// # use nalgebra::DVector;
|
2018-12-09 19:22:10 +08:00
|
|
|
|
/// let mut vector = DVector::from_vec(vec![0, 1, 2]);
|
2018-11-13 02:53:30 +08:00
|
|
|
|
/// vector.extend(vec![3, 4, 5]);
|
2018-12-09 19:22:10 +08:00
|
|
|
|
/// assert!(vector.eq(&DVector::from_vec(vec![0, 1, 2, 3, 4, 5])));
|
2018-11-13 02:53:30 +08:00
|
|
|
|
/// ```
|
2021-04-11 17:00:38 +08:00
|
|
|
|
fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
|
2018-11-13 02:53:30 +08:00
|
|
|
|
self.data.extend(iter);
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-11-14 05:17:00 +08:00
|
|
|
|
|
2019-02-03 22:16:50 +08:00
|
|
|
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
2021-07-17 12:17:56 +08:00
|
|
|
|
impl<T, R: Dim, S, RV: Dim, SV> Extend<Vector<T, RV, SV>> for Matrix<T, R, Dynamic, S>
|
2018-11-14 05:17:00 +08:00
|
|
|
|
where
|
2021-04-11 17:00:38 +08:00
|
|
|
|
S: Extend<Vector<T, RV, SV>>,
|
|
|
|
|
SV: Storage<T, RV>,
|
2018-11-18 01:13:03 +08:00
|
|
|
|
ShapeConstraint: SameNumberOfRows<R, RV>,
|
2018-11-14 05:17:00 +08:00
|
|
|
|
{
|
|
|
|
|
/// Extends the number of columns of a `Matrix` with `Vector`s
|
|
|
|
|
/// from a given iterator.
|
|
|
|
|
///
|
|
|
|
|
/// # Example
|
|
|
|
|
/// ```
|
|
|
|
|
/// # use nalgebra::{DMatrix, Vector3, Matrix3x4};
|
|
|
|
|
///
|
|
|
|
|
/// let data = vec![0, 1, 2, // column 1
|
|
|
|
|
/// 3, 4, 5]; // column 2
|
|
|
|
|
///
|
|
|
|
|
/// let mut matrix = DMatrix::from_vec(3, 2, data);
|
|
|
|
|
///
|
|
|
|
|
/// matrix.extend(
|
|
|
|
|
/// vec![Vector3::new(6, 7, 8), // column 3
|
|
|
|
|
/// Vector3::new(9, 10, 11)]); // column 4
|
|
|
|
|
///
|
|
|
|
|
/// assert!(matrix.eq(&Matrix3x4::new(0, 3, 6, 9,
|
|
|
|
|
/// 1, 4, 7, 10,
|
|
|
|
|
/// 2, 5, 8, 11)));
|
|
|
|
|
/// ```
|
|
|
|
|
///
|
|
|
|
|
/// # Panics
|
|
|
|
|
/// This function panics if the dimension of each `Vector` yielded
|
|
|
|
|
/// by the given iterator is not equal to the number of rows of
|
|
|
|
|
/// this `Matrix`.
|
|
|
|
|
///
|
|
|
|
|
/// ```should_panic
|
|
|
|
|
/// # use nalgebra::{DMatrix, Vector2, Matrix3x4};
|
|
|
|
|
/// let mut matrix =
|
|
|
|
|
/// DMatrix::from_vec(3, 2,
|
|
|
|
|
/// vec![0, 1, 2, // column 1
|
|
|
|
|
/// 3, 4, 5]); // column 2
|
|
|
|
|
///
|
|
|
|
|
/// // The following panics because this matrix can only be extended with 3-dimensional vectors.
|
|
|
|
|
/// matrix.extend(
|
|
|
|
|
/// vec![Vector2::new(6, 7)]); // too few dimensions!
|
|
|
|
|
/// ```
|
|
|
|
|
///
|
|
|
|
|
/// ```should_panic
|
|
|
|
|
/// # use nalgebra::{DMatrix, Vector4, Matrix3x4};
|
|
|
|
|
/// let mut matrix =
|
|
|
|
|
/// DMatrix::from_vec(3, 2,
|
|
|
|
|
/// vec![0, 1, 2, // column 1
|
|
|
|
|
/// 3, 4, 5]); // column 2
|
|
|
|
|
///
|
|
|
|
|
/// // The following panics because this matrix can only be extended with 3-dimensional vectors.
|
|
|
|
|
/// matrix.extend(
|
|
|
|
|
/// vec![Vector4::new(6, 7, 8, 9)]); // too few dimensions!
|
|
|
|
|
/// ```
|
2021-04-11 17:00:38 +08:00
|
|
|
|
fn extend<I: IntoIterator<Item = Vector<T, RV, SV>>>(&mut self, iter: I) {
|
2018-11-14 05:17:00 +08:00
|
|
|
|
self.data.extend(iter);
|
|
|
|
|
}
|
|
|
|
|
}
|