diff --git a/benches/core/matrix.rs b/benches/core/matrix.rs index 3c483c35..d13d54e9 100644 --- a/benches/core/matrix.rs +++ b/benches/core/matrix.rs @@ -1,4 +1,7 @@ -use na::{DMatrix, DVector, Matrix2, Matrix3, Matrix4, OMatrix, Vector2, Vector3, Vector4, U10}; +use na::{ + Const, DMatrix, DVector, Dynamic, Matrix2, Matrix3, Matrix4, OMatrix, Vector2, Vector3, + Vector4, U10, +}; use rand::Rng; use rand_isaac::IsaacRng; use std::ops::{Add, Div, Mul, Sub}; @@ -186,7 +189,7 @@ fn axpy(bench: &mut criterion::Criterion) { fn tr_mul_to(bench: &mut criterion::Criterion) { let a = DMatrix::::new_random(1000, 1000); let b = DVector::::new_random(1000); - let mut c = DVector::from_element(1000, 0.0); + let mut c = DVector::new_uninitialized_generic(Dynamic::new(1000), Const::<1>); bench.bench_function("tr_mul_to", move |bh| bh.iter(|| a.tr_mul_to(&b, &mut c))); } @@ -194,7 +197,7 @@ fn tr_mul_to(bench: &mut criterion::Criterion) { fn mat_mul_mat(bench: &mut criterion::Criterion) { let a = DMatrix::::new_random(100, 100); let b = DMatrix::::new_random(100, 100); - let mut ab = DMatrix::::from_element(100, 100, 0.0); + let mut ab = DMatrix::new_uninitialized_generic(Dynamic::new(100), Dynamic::new(100)); bench.bench_function("mat_mul_mat", move |bh| { bh.iter(|| { diff --git a/nalgebra-lapack/src/eigen.rs b/nalgebra-lapack/src/eigen.rs index 1bca79a5..9adbb26b 100644 --- a/nalgebra-lapack/src/eigen.rs +++ b/nalgebra-lapack/src/eigen.rs @@ -78,9 +78,9 @@ where let lda = n as i32; - let mut wr = unsafe { Matrix::new_uninitialized_generic(nrows, Const::<1>).assume_init() }; + let mut wr = unsafe { Matrix::new_uninitialized_generic(nrows, U1).assume_init() }; // TODO: Tap into the workspace. - let mut wi = unsafe { Matrix::new_uninitialized_generic(nrows, Const::<1>).assume_init() }; + let mut wi = unsafe { Matrix::new_uninitialized_generic(nrows, U1).assume_init() }; let mut info = 0; let mut placeholder1 = [T::zero()]; @@ -247,8 +247,8 @@ where let lda = n as i32; - let mut wr = unsafe { Matrix::new_uninitialized_generic(nrows, Const::<1>).assume_init() }; - let mut wi = unsafe { Matrix::new_uninitialized_generic(nrows, Const::<1>).assume_init() }; + let mut wr = unsafe { Matrix::new_uninitialized_generic(nrows, U1).assume_init() }; + let mut wi = unsafe { Matrix::new_uninitialized_generic(nrows, U1).assume_init() }; let mut info = 0; let mut placeholder1 = [T::zero()]; @@ -291,7 +291,7 @@ where ); lapack_panic!(info); - let mut res = unsafe { Matrix::new_uninitialized_generic(nrows, Const::<1>).assume_init() }; + let mut res = unsafe { Matrix::new_uninitialized_generic(nrows, U1).assume_init() }; for i in 0..res.len() { res[i] = Complex::new(wr[i], wi[i]); diff --git a/nalgebra-lapack/src/hessenberg.rs b/nalgebra-lapack/src/hessenberg.rs index c5765022..bddd133f 100644 --- a/nalgebra-lapack/src/hessenberg.rs +++ b/nalgebra-lapack/src/hessenberg.rs @@ -61,7 +61,7 @@ where ); let mut tau = unsafe { - Matrix::new_uninitialized_generic(nrows.sub(Const::<1>), Const::<1>).assume_init() + Matrix::new_uninitialized_generic(nrows.sub(U1), U1).assume_init() }; let mut info = 0; diff --git a/nalgebra-lapack/src/lu.rs b/nalgebra-lapack/src/lu.rs index 2130fc7e..162b9ae7 100644 --- a/nalgebra-lapack/src/lu.rs +++ b/nalgebra-lapack/src/lu.rs @@ -66,7 +66,7 @@ where let nrows = nrows.value() as i32; let ncols = ncols.value() as i32; - let mut ipiv: OVector = Matrix::zeros_generic(min_nrows_ncols, Const::<1>); + let mut ipiv: OVector = Matrix::zeros_generic(min_nrows_ncols, U1); let mut info = 0; diff --git a/nalgebra-lapack/src/qr.rs b/nalgebra-lapack/src/qr.rs index 7b2d5df6..4f290201 100644 --- a/nalgebra-lapack/src/qr.rs +++ b/nalgebra-lapack/src/qr.rs @@ -58,7 +58,7 @@ where let mut info = 0; let mut tau = unsafe { - Matrix::new_uninitialized_generic(nrows.min(ncols), Const::<1>).assume_init() + Matrix::new_uninitialized_generic(nrows.min(ncols), U1).assume_init() }; if nrows.value() == 0 || ncols.value() == 0 { diff --git a/nalgebra-lapack/src/schur.rs b/nalgebra-lapack/src/schur.rs index 35da8bec..e5435dbf 100644 --- a/nalgebra-lapack/src/schur.rs +++ b/nalgebra-lapack/src/schur.rs @@ -78,8 +78,8 @@ where let mut info = 0; - let mut wr = unsafe { Matrix::new_uninitialized_generic(nrows, Const::<1>).assume_init() }; - let mut wi = unsafe { Matrix::new_uninitialized_generic(nrows, Const::<1>).assume_init() }; + let mut wr = unsafe { Matrix::new_uninitialized_generic(nrows, U1).assume_init() }; + let mut wi = unsafe { Matrix::new_uninitialized_generic(nrows, U1).assume_init() }; let mut q = unsafe { Matrix::new_uninitialized_generic(nrows, ncols).assume_init() }; // Placeholders: let mut bwork = [0i32]; @@ -154,7 +154,7 @@ where DefaultAllocator: Allocator, D>, { let mut out = - unsafe { OVector::new_uninitialized_generic(self.t.data.shape().0, Const::<1>) }; + unsafe { OVector::new_uninitialized_generic(self.t.data.shape().0, U1) }; for i in 0..out.len() { out[i] = MaybeUninit::new(Complex::new(self.re[i], self.im[i])); diff --git a/nalgebra-lapack/src/svd.rs b/nalgebra-lapack/src/svd.rs index 3357e621..2321668d 100644 --- a/nalgebra-lapack/src/svd.rs +++ b/nalgebra-lapack/src/svd.rs @@ -100,7 +100,7 @@ macro_rules! svd_impl( let lda = nrows.value() as i32; let mut u = unsafe { Matrix::new_uninitialized_generic(nrows, nrows).assume_init() }; - let mut s = unsafe { Matrix::new_uninitialized_generic(nrows.min(ncols), Const::<1>).assume_init() }; + let mut s = unsafe { Matrix::new_uninitialized_generic(nrows.min(ncols), U1).assume_init() }; let mut vt = unsafe { Matrix::new_uninitialized_generic(ncols, ncols).assume_init() }; let ldu = nrows.value(); diff --git a/nalgebra-lapack/src/symmetric_eigen.rs b/nalgebra-lapack/src/symmetric_eigen.rs index d276437e..cceca046 100644 --- a/nalgebra-lapack/src/symmetric_eigen.rs +++ b/nalgebra-lapack/src/symmetric_eigen.rs @@ -95,7 +95,7 @@ where let lda = n as i32; let mut values = - unsafe { Matrix::new_uninitialized_generic(nrows, Const::<1>).assume_init() }; + unsafe { Matrix::new_uninitialized_generic(nrows, U1).assume_init() }; let mut info = 0; let lwork = T::xsyev_work_size(jobz, b'L', n as i32, m.as_mut_slice(), lda, &mut info); diff --git a/nalgebra-sparse/src/convert/impl_std_ops.rs b/nalgebra-sparse/src/convert/impl_std_ops.rs index 4e2a039f..d775fa13 100644 --- a/nalgebra-sparse/src/convert/impl_std_ops.rs +++ b/nalgebra-sparse/src/convert/impl_std_ops.rs @@ -8,7 +8,7 @@ use num_traits::Zero; impl<'a, T, R: Dim, C: Dim, S> From<&'a Matrix> for CooMatrix where - T: Scalar + Zero, + T: Scalar + Zero + PartialEq, S: Storage, { fn from(matrix: &'a Matrix) -> Self { @@ -45,7 +45,7 @@ where impl<'a, T, R: Dim, C: Dim, S> From<&'a Matrix> for CsrMatrix where - T: Scalar + Zero, + T: Scalar + Zero + PartialEq, S: Storage, { fn from(matrix: &'a Matrix) -> Self { @@ -82,7 +82,7 @@ where impl<'a, T, R: Dim, C: Dim, S> From<&'a Matrix> for CscMatrix where - T: Scalar + Zero, + T: Scalar + Zero + PartialEq, S: Storage, { fn from(matrix: &'a Matrix) -> Self { diff --git a/nalgebra-sparse/src/convert/serial.rs b/nalgebra-sparse/src/convert/serial.rs index 7e0da7bc..ebdf4e65 100644 --- a/nalgebra-sparse/src/convert/serial.rs +++ b/nalgebra-sparse/src/convert/serial.rs @@ -16,11 +16,9 @@ use crate::csc::CscMatrix; use crate::csr::CsrMatrix; /// Converts a dense matrix to [`CooMatrix`]. -pub fn convert_dense_coo(dense: &Matrix) -> CooMatrix +pub fn convert_dense_coo(dense: &Matrix) -> CooMatrix where - T: Scalar + Zero, - R: Dim, - C: Dim, + T: Scalar + Zero + PartialEq, S: Storage, { let mut coo = CooMatrix::new(dense.nrows(), dense.ncols()); @@ -93,7 +91,7 @@ where /// Converts a dense matrix to a [`CsrMatrix`]. pub fn convert_dense_csr(dense: &Matrix) -> CsrMatrix where - T: Scalar + Zero, + T: Scalar + Zero + PartialEq, R: Dim, C: Dim, S: Storage, @@ -170,7 +168,7 @@ where /// Converts a dense matrix to a [`CscMatrix`]. pub fn convert_dense_csc(dense: &Matrix) -> CscMatrix where - T: Scalar + Zero, + T: Scalar + Zero + PartialEq, R: Dim, C: Dim, S: Storage, diff --git a/nalgebra-sparse/src/ops/impl_std_ops.rs b/nalgebra-sparse/src/ops/impl_std_ops.rs index 590bd934..11d59ded 100644 --- a/nalgebra-sparse/src/ops/impl_std_ops.rs +++ b/nalgebra-sparse/src/ops/impl_std_ops.rs @@ -6,7 +6,7 @@ use crate::ops::serial::{ spmm_csc_prealloc, spmm_csr_dense, spmm_csr_pattern, spmm_csr_prealloc, }; use crate::ops::Op; -use nalgebra::allocator::Allocator; +use nalgebra::allocator::{Allocator, InnerAllocator}; use nalgebra::base::storage::Storage; use nalgebra::constraint::{DimEq, ShapeConstraint}; use nalgebra::{ @@ -28,7 +28,7 @@ macro_rules! impl_bin_op { // Note: The Neg bound is currently required because we delegate e.g. // Sub to SpAdd with negative coefficients. This is not well-defined for // unsigned data types. - $($scalar_type: $($bounds + )? Scalar + ClosedAdd + ClosedSub + ClosedMul + Zero + One + Neg)? + $($scalar_type: $($bounds + )? Scalar + ClosedAdd + ClosedSub + ClosedMul + Zero + One + Neg + PartialEq)? { type Output = $ret; fn $method(self, $b: $b_type) -> Self::Output { @@ -306,9 +306,9 @@ macro_rules! impl_spmm_cs_dense { // TODO: Is it possible to simplify these bounds? ShapeConstraint: // Bounds so that we can turn OMatrix into a DMatrixSliceMut - DimEq>::Buffer as Storage>::RStride> + DimEq>::Buffer as Storage>::RStride> + DimEq - + DimEq>::Buffer as Storage>::CStride> + + DimEq>::Buffer as Storage>::CStride> // Bounds so that we can turn &Matrix into a DMatrixSlice + DimEq + DimEq diff --git a/nalgebra-sparse/src/ops/serial/cs.rs b/nalgebra-sparse/src/ops/serial/cs.rs index 66b0ad76..69b2fd7f 100644 --- a/nalgebra-sparse/src/ops/serial/cs.rs +++ b/nalgebra-sparse/src/ops/serial/cs.rs @@ -74,7 +74,7 @@ pub fn spadd_cs_prealloc( a: Op<&CsMatrix>, ) -> Result<(), OperationError> where - T: Scalar + ClosedAdd + ClosedMul + Zero + One, + T: Scalar + ClosedAdd + ClosedMul + Zero + One+PartialEq, { match a { Op::NoOp(a) => { diff --git a/nalgebra-sparse/src/ops/serial/csc.rs b/nalgebra-sparse/src/ops/serial/csc.rs index 95350d91..03acf810 100644 --- a/nalgebra-sparse/src/ops/serial/csc.rs +++ b/nalgebra-sparse/src/ops/serial/csc.rs @@ -55,7 +55,7 @@ pub fn spadd_csc_prealloc( a: Op<&CscMatrix>, ) -> Result<(), OperationError> where - T: Scalar + ClosedAdd + ClosedMul + Zero + One, + T: Scalar + ClosedAdd + ClosedMul + Zero + One+PartialEq, { assert_compatible_spadd_dims!(c, a); spadd_cs_prealloc(beta, &mut c.cs, alpha, a.map_same_op(|a| &a.cs)) diff --git a/nalgebra-sparse/src/ops/serial/csr.rs b/nalgebra-sparse/src/ops/serial/csr.rs index f6fcc62a..ecbcc1a4 100644 --- a/nalgebra-sparse/src/ops/serial/csr.rs +++ b/nalgebra-sparse/src/ops/serial/csr.rs @@ -50,7 +50,7 @@ pub fn spadd_csr_prealloc( a: Op<&CsrMatrix>, ) -> Result<(), OperationError> where - T: Scalar + ClosedAdd + ClosedMul + Zero + One, + T: Scalar + ClosedAdd + ClosedMul + Zero + One + PartialEq, { assert_compatible_spadd_dims!(c, a); spadd_cs_prealloc(beta, &mut c.cs, alpha, a.map_same_op(|a| &a.cs)) diff --git a/src/base/allocator.rs b/src/base/allocator.rs index 92a38300..95a65c6f 100644 --- a/src/base/allocator.rs +++ b/src/base/allocator.rs @@ -1,6 +1,6 @@ //! Abstract definition of a matrix data storage allocator. -use std::mem::MaybeUninit; +use std::mem::{ManuallyDrop, MaybeUninit}; use crate::base::constraint::{SameNumberOfColumns, SameNumberOfRows, ShapeConstraint}; use crate::base::dimension::{Dim, U1}; @@ -30,9 +30,12 @@ pub trait InnerAllocator: 'static + Sized { ) -> Self::Buffer; } -/// Same as the [`InnerAllocator`] trait, but also provides methods to build uninitialized buffers. +/// Same as the [`InnerAllocator`] trait, but also provides methods to build uninitialized buffers, +/// or buffers whose entries must be manually dropped. pub trait Allocator: - InnerAllocator + InnerAllocator, R, C> + InnerAllocator + + InnerAllocator, R, C> + + InnerAllocator, R, C> { /// Allocates a buffer with the given number of rows and columns without initializing its content. fn allocate_uninitialized( @@ -44,6 +47,11 @@ pub trait Allocator: unsafe fn assume_init( uninit: , R, C>>::Buffer, ) -> >::Buffer; + + /// Specifies that a given buffer's entries should be manually dropped. + fn manually_drop( + buf: >::Buffer, + ) -> , R, C>>::Buffer; } /// A matrix reallocator. Changes the size of the memory buffer that initially contains (RFrom × @@ -84,8 +92,7 @@ where impl SameShapeAllocator for DefaultAllocator where - DefaultAllocator: - Allocator + Allocator, SameShapeC>, + DefaultAllocator: Allocator + Allocator, SameShapeC>, ShapeConstraint: SameNumberOfRows + SameNumberOfColumns, { } @@ -93,9 +100,7 @@ where // XXX: Bad name. /// Restricts the given number of rows to be equal. pub trait SameShapeVectorAllocator: - Allocator - + Allocator> - + SameShapeAllocator + Allocator + Allocator> + SameShapeAllocator where ShapeConstraint: SameNumberOfRows, { diff --git a/src/base/blas.rs b/src/base/blas.rs index dd36ab37..4c72b74d 100644 --- a/src/base/blas.rs +++ b/src/base/blas.rs @@ -329,22 +329,18 @@ where if !b.is_zero() { for i in 0..x.len() { - - let y = y.get_unchecked_mut(i * rstride1); - *y = a.inlined_clone() - * x.get_unchecked(i * rstride2).inlined_clone() - * c.inlined_clone() - + b.inlined_clone() * y.inlined_clone(); - + let y = y.get_unchecked_mut(i * rstride1); + *y = a.inlined_clone() + * x.get_unchecked(i * rstride2).inlined_clone() + * c.inlined_clone() + + b.inlined_clone() * y.inlined_clone(); } } else { for i in 0..x.len() { - - let y = y.get_unchecked_mut(i * rstride1); - *y = a.inlined_clone() - * x.get_unchecked(i * rstride2).inlined_clone() - * c.inlined_clone(); - + let y = y.get_unchecked_mut(i * rstride1); + *y = a.inlined_clone() + * x.get_unchecked(i * rstride2).inlined_clone() + * c.inlined_clone(); } } } @@ -788,7 +784,7 @@ where for j in 1..ncols2 { let col2 = a.column(j); - let val = x.vget_unchecked(j).inlined_clone() ; + let val = x.vget_unchecked(j).inlined_clone(); init.axcpy(alpha.inlined_clone(), &col2, val, T::one()); } } @@ -852,6 +848,8 @@ where } } + /// Computes `self = alpha * a * x`, where `a` is an **hermitian** matrix, `x` a + /// vector, and `alpha, beta` two scalars. pub fn hegemv_z( &mut self, alpha: T, @@ -1574,7 +1572,8 @@ where ShapeConstraint: DimEq + DimEq, DefaultAllocator: Allocator, { - let mut work = Matrix::new_uninitialized_generic(R3::from_usize(self.shape().0), Const::<1>); + let mut work = + Matrix::new_uninitialized_generic(R3::from_usize(self.shape().0), Const::<1>); work.gemv_z(T::one(), lhs, &mid.column(0)); let mut work = unsafe { work.assume_init() }; @@ -1624,7 +1623,8 @@ where DefaultAllocator: Allocator, { // TODO: figure out why type inference wasn't doing its job. - let mut work = Matrix::new_uninitialized_generic(D3::from_usize(self.shape().0), Const::<1>); + let mut work = + Matrix::new_uninitialized_generic(D3::from_usize(self.shape().0), Const::<1>); work.gemv_z::(T::one(), mid, &rhs.column(0)); let mut work = unsafe { work.assume_init() }; diff --git a/src/base/construction.rs b/src/base/construction.rs index 3daf918b..e99b9e02 100644 --- a/src/base/construction.rs +++ b/src/base/construction.rs @@ -906,7 +906,7 @@ impl Arbitrary for OMatrix where T: Arbitrary + Send, DefaultAllocator: Allocator, - Owned: Clone+Send, + Owned: Clone + Send, { #[inline] fn arbitrary(g: &mut Gen) -> Self { diff --git a/src/base/conversion.rs b/src/base/conversion.rs index 66ebe3bd..b768ed73 100644 --- a/src/base/conversion.rs +++ b/src/base/conversion.rs @@ -361,7 +361,7 @@ where } } -impl<'a, T: Dim, R: Dim, C: Dim, RSlice: Dim, CSlice: Dim, RStride: Dim, CStride: Dim, S> +impl<'a, T, R: Dim, C: Dim, RSlice: Dim, CSlice: Dim, RStride: Dim, CStride: Dim, S> From<&'a mut Matrix> for MatrixSliceMut<'a, T, RSlice, CSlice, RStride, CStride> where S: StorageMut, diff --git a/src/base/default_allocator.rs b/src/base/default_allocator.rs index 4551bcff..4d8d0010 100644 --- a/src/base/default_allocator.rs +++ b/src/base/default_allocator.rs @@ -4,8 +4,7 @@ //! heap-allocated buffers for matrices with at least one dimension unknown at compile-time. use std::cmp; -use std::mem::ManuallyDrop; -use std::mem::MaybeUninit; +use std::mem::{self, ManuallyDrop, MaybeUninit}; use std::ptr; #[cfg(all(feature = "alloc", not(feature = "std")))] @@ -22,10 +21,6 @@ use crate::base::storage::{ContiguousStorageMut, Storage, StorageMut}; use crate::base::vec_storage::VecStorage; use crate::storage::Owned; -type DefaultBuffer = >::Buffer; -type DefaultUninitBuffer = - , R, C>>::Buffer; - /* * * Allocator. @@ -72,7 +67,7 @@ impl Allocator, Const> for Def _: Const, _: Const, ) -> Owned, Const, Const> { - // SAFETY: An uninitialized `[MaybeUninit<_>; LEN]` is valid. + // SAFETY: An uninitialized `[MaybeUninit<_>; _]` is valid. let array = unsafe { MaybeUninit::uninit().assume_init() }; ArrayStorage(array) } @@ -84,11 +79,24 @@ impl Allocator, Const> for Def // SAFETY: // * The caller guarantees that all elements of the array are initialized // * `MaybeUninit` and T are guaranteed to have the same layout - // * MaybeUnint does not drop, so there are no double-frees + // * `MaybeUnint` does not drop, so there are no double-frees // * `ArrayStorage` is transparent. // And thus the conversion is safe ArrayStorage((&uninit as *const _ as *const [_; C]).read()) } + + /// Specifies that a given buffer's entries should be manually dropped. + #[inline] + fn manually_drop( + buf: , Const>>::Buffer, + ) -> , Const, Const>>::Buffer { + // SAFETY: + // * `ManuallyDrop` and T are guaranteed to have the same layout + // * `ManuallyDrop` does not drop, so there are no double-frees + // * `ArrayStorage` is transparent. + // And thus the conversion is safe + ArrayStorage(unsafe { mem::transmute_copy(&ManuallyDrop::new(buf.0)) }) + } } // Dynamic - Static @@ -133,6 +141,25 @@ impl Allocator for DefaultAllocator { VecStorage::new(uninit.nrows, uninit.ncols, new_data) } + + #[inline] + fn manually_drop( + buf: >::Buffer, + ) -> , Dynamic, C>>::Buffer { + // Avoids dropping the buffer that will be used for the result. + let mut data = ManuallyDrop::new(buf.data); + + // Safety: ManuallyDrop has the same alignment and layout as T. + let new_data = unsafe { + Vec::from_raw_parts( + data.as_mut_ptr() as *mut ManuallyDrop, + data.len(), + data.capacity(), + ) + }; + + VecStorage::new(buf.nrows, buf.ncols, new_data) + } } // Static - Dynamic @@ -176,6 +203,25 @@ impl Allocator for DefaultAllocator { VecStorage::new(uninit.nrows, uninit.ncols, new_data) } + + #[inline] + fn manually_drop( + buf: >::Buffer, + ) -> , R, Dynamic>>::Buffer { + // Avoids dropping the buffer that will be used for the result. + let mut data = ManuallyDrop::new(buf.data); + + // Safety: ManuallyDrop has the same alignment and layout as T. + let new_data = unsafe { + Vec::from_raw_parts( + data.as_mut_ptr() as *mut ManuallyDrop, + data.len(), + data.capacity(), + ) + }; + + VecStorage::new(buf.nrows, buf.ncols, new_data) + } } /* diff --git a/src/base/matrix.rs b/src/base/matrix.rs index f973504b..38e9e7c3 100644 --- a/src/base/matrix.rs +++ b/src/base/matrix.rs @@ -8,7 +8,7 @@ use std::cmp::Ordering; use std::fmt; use std::hash::{Hash, Hasher}; use std::marker::PhantomData; -use std::mem::{self, MaybeUninit}; +use std::mem::{self, ManuallyDrop, MaybeUninit}; #[cfg(feature = "serde-serialize-no-std")] use serde::{Deserialize, Deserializer, Serialize, Serializer}; @@ -194,10 +194,7 @@ pub struct Matrix { impl Default for Matrix { fn default() -> Self { - Matrix { - data: Default::default(), - _phantoms: PhantomData, - } + unsafe { Matrix::from_data_statically_unchecked(Default::default()) } } } @@ -212,7 +209,7 @@ impl Serialize for Matrix { } #[cfg(feature = "serde-serialize-no-std")] -impl<'de, T: Dim, R: Dim, C, S: Serialize<'de>> Deserialize<'de> for Matrix { +impl<'de, T, R: Dim, C, S: Serialize<'de>> Deserialize<'de> for Matrix { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, @@ -344,9 +341,20 @@ where { /// Allocates a matrix with the given number of rows and columns without initializing its content. pub fn new_uninitialized_generic(nrows: R, ncols: C) -> OMatrix, R, C> { - OMatrix { - data: >::allocate_uninitialized(nrows, ncols), - _phantoms: PhantomData, + unsafe { + OMatrix::from_data_statically_unchecked( + >::allocate_uninitialized(nrows, ncols), + ) + } + } + + /// Converts this matrix into one whose entries need to be manually dropped. This should be + /// near zero-cost. + pub fn manually_drop(self) -> OMatrix, R, C> { + unsafe { + OMatrix::from_data_statically_unchecked( + >::manually_drop(self.data), + ) } } } @@ -356,11 +364,12 @@ where DefaultAllocator: Allocator, { /// Assumes a matrix's entries to be initialized. This operation should be near zero-cost. + /// + /// For the similar method that operates on matrix slices, see [`slice_assume_init`]. pub unsafe fn assume_init(self) -> OMatrix { - OMatrix { - data: >::assume_init(self.data), - _phantoms: PhantomData, - } + OMatrix::from_data_statically_unchecked( + >::assume_init(self.data), + ) } } @@ -711,30 +720,35 @@ impl> Matrix { res.assume_init() } } +} - /// Transposes `self`. Does not require `T: Clone` like its other counteparts. - pub fn transpose_into(self) -> OMatrix - where - DefaultAllocator: Allocator, - { +impl OMatrix +where + DefaultAllocator: Allocator + Allocator, +{ + /// Transposes `self`. Does not require `T: Clone` like its other counterparts. + pub fn transpose_into(self) -> OMatrix { let (nrows, ncols) = self.data.shape(); let mut res = OMatrix::new_uninitialized_generic(ncols, nrows); + let mut md = self.manually_drop(); let (nrows, ncols) = res.shape(); // TODO: optimize that. for i in 0..nrows { for j in 0..ncols { + // Safety: the indices are within range, and since the indices + // don't repeat, we don't do any double-drops. unsafe { - *res.get_unchecked_mut((j, i)) = MaybeUninit::new(*self.get_unchecked((i, j))); + *res.get_unchecked_mut((j, i)) = + MaybeUninit::new(ManuallyDrop::take(md.get_unchecked_mut((i, j)))); } } } - // BEEP! BEEP! There's a double drop here that needs to be fixed. - unsafe { - // Safety: res is now fully initialized due to the guarantees of transpose_to. + // Safety: res is now fully initialized, since we've initialized + // every single entry. res.assume_init() } } @@ -956,7 +970,6 @@ impl> Matrix { ShapeConstraint: SameNumberOfRows + SameNumberOfColumns, { let (nrows, ncols) = self.data.shape(); - let mut res = init; assert_eq!( @@ -982,6 +995,7 @@ impl> Matrix { #[inline] pub fn apply T>(&mut self, mut f: F) where + T: Clone, // This could be removed by changing the function signature. S: StorageMut, { let (nrows, ncols) = self.shape(); @@ -990,7 +1004,7 @@ impl> Matrix { for i in 0..nrows { unsafe { let e = self.data.get_unchecked_mut(i, j); - *e = f(*e) + *e = f(e.clone()) } } } @@ -1004,6 +1018,7 @@ impl> Matrix { rhs: &Matrix, mut f: impl FnMut(T, T2) -> T, ) where + T: Clone, // This could be removed by changing the function signature. S: StorageMut, S2: Storage, ShapeConstraint: SameNumberOfRows + SameNumberOfColumns, @@ -1021,7 +1036,7 @@ impl> Matrix { unsafe { let e = self.data.get_unchecked_mut(i, j); let rhs = rhs.get_unchecked((i, j)).clone(); - *e = f(*e, rhs) + *e = f(e.clone(), rhs) } } } @@ -1036,6 +1051,7 @@ impl> Matrix { c: &Matrix, mut f: impl FnMut(T, T2, N3) -> T, ) where + T: Clone, // This could be removed by changing the function signature. S: StorageMut, S2: Storage, S3: Storage, @@ -1061,7 +1077,7 @@ impl> Matrix { let e = self.data.get_unchecked_mut(i, j); let b = b.get_unchecked((i, j)).clone(); let c = c.get_unchecked((i, j)).clone(); - *e = f(*e, b, c) + *e = f(e.clone(), b, c) } } } @@ -1249,8 +1265,11 @@ impl> Matrix { /// Fills this matrix with the content of another one, after applying a function to /// the references of the entries of the other matrix. Both must have the same shape. #[inline] - pub fn copy_from_fn(&mut self, other: &Matrix,mut f: F) - where + pub fn copy_from_fn( + &mut self, + other: &Matrix, + mut f: F, + ) where SB: Storage, ShapeConstraint: SameNumberOfRows + SameNumberOfColumns, F: FnMut(&U) -> T, @@ -1272,20 +1291,20 @@ impl> Matrix { /// Fills this matrix with the content of another one, after applying a function to /// the entries of the other matrix. Both must have the same shape. #[inline] - pub fn move_from(&mut self, other: Matrix) + pub fn move_from(&mut self, other: OMatrix) where - SB: Storage, ShapeConstraint: SameNumberOfRows + SameNumberOfColumns, + DefaultAllocator: Allocator, { self.move_from_fn(other, |e| e) } /// Fills this matrix with the content of another one via moves. Both must have the same shape. #[inline] - pub fn move_from_fn(&mut self, other: Matrix, mut f: F) + pub fn move_from_fn(&mut self, other: OMatrix, mut f: F) where - SB: Storage, ShapeConstraint: SameNumberOfRows + SameNumberOfColumns, + DefaultAllocator: Allocator, F: FnMut(U) -> T, { assert!( @@ -1293,15 +1312,16 @@ impl> Matrix { "Unable to move from a matrix with a different shape." ); + let mut md = other.manually_drop(); + for j in 0..self.ncols() { for i in 0..self.nrows() { unsafe { - *self.get_unchecked_mut((i, j)) = f(*other.get_unchecked((i, j))); + *self.get_unchecked_mut((i, j)) = + f(ManuallyDrop::take(md.get_unchecked_mut((i, j)))); } } } - - // BEEP BEEEP!!!!! I'm double-freeing! OH NO!!!! (todo) } /// Fills this matrix with the content of the transpose another one via clones. @@ -1322,7 +1342,7 @@ impl> Matrix { pub fn tr_copy_from_fn( &mut self, other: &Matrix, - mut f: F, + mut f: F, ) where SB: Storage, ShapeConstraint: DimEq + SameNumberOfColumns, @@ -1345,9 +1365,9 @@ impl> Matrix { /// Fills this matrix with the content of the transpose another one via moves. #[inline] - pub fn tr_move_from(&mut self, other: Matrix) + pub fn tr_move_from(&mut self, other: OMatrix) where - SB: Storage, + DefaultAllocator: Allocator, ShapeConstraint: DimEq + SameNumberOfColumns, { self.tr_move_from_fn(other, |e| e) @@ -1356,13 +1376,10 @@ impl> Matrix { /// Fills this matrix with the content of the transpose of another one, after applying /// a function to the entries of the other matrix. Both must have the same shape. #[inline] - pub fn tr_move_from_fn( - &mut self, - other: Matrix, - mut f: F, - ) where - SB: Storage, + pub fn tr_move_from_fn(&mut self, other: OMatrix, mut f: F) + where ShapeConstraint: DimEq + SameNumberOfColumns, + DefaultAllocator: Allocator, F: FnMut(U) -> T, { let (nrows, ncols) = self.shape(); @@ -1371,21 +1388,25 @@ impl> Matrix { "Unable to move from a matrix with incompatible shape." ); + let mut md = other.manually_drop(); + for j in 0..ncols { for i in 0..nrows { unsafe { - *self.get_unchecked_mut((i, j)) = f(*other.get_unchecked((j, i))); + *self.get_unchecked_mut((i, j)) = + f(ManuallyDrop::take(md.get_unchecked_mut((j, i)))); } } } - - // BEEP BEEPP! Same thing as the non-transpose method, this is UB. } // TODO: rename `apply` to `apply_mut` and `apply_into` to `apply`? /// Returns `self` with each of its components replaced by the result of a closure `f` applied on it. #[inline] - pub fn apply_into T>(mut self, f: F) -> Self { + pub fn apply_into T>(mut self, f: F) -> Self + where + T: Clone, + { self.apply(f); self } @@ -1406,9 +1427,10 @@ impl, R, C>> Matrix(&mut self, other: Matrix) + pub fn move_init_from(&mut self, other: OMatrix) where SB: Storage, + DefaultAllocator: Allocator, ShapeConstraint: SameNumberOfRows + SameNumberOfColumns, { self.move_from_fn(other, MaybeUninit::new) @@ -1427,9 +1449,9 @@ impl, R, C>> Matrix(&mut self, other: Matrix) + pub fn tr_move_init_from(&mut self, other: OMatrix) where - SB: Storage, + DefaultAllocator: Allocator, ShapeConstraint: DimEq + SameNumberOfColumns, { self.tr_move_from_fn(other, MaybeUninit::new) diff --git a/src/base/matrix_slice.rs b/src/base/matrix_slice.rs index 30f30c41..7ba2eb8d 100644 --- a/src/base/matrix_slice.rs +++ b/src/base/matrix_slice.rs @@ -222,6 +222,7 @@ storage_impl!(SliceStorage, SliceStorageMut); impl<'a, T, R: Dim, C: Dim, RStride: Dim, CStride: Dim> SliceStorage<'a, MaybeUninit, R, C, RStride, CStride> { + /// Assumes a slice storage's entries to be initialized. This operation should be near zero-cost. pub unsafe fn assume_init(self) -> SliceStorage<'a, T, R, C, RStride, CStride> { SliceStorage::from_raw_parts(self.ptr as *const T, self.shape, self.strides) } @@ -230,6 +231,7 @@ impl<'a, T, R: Dim, C: Dim, RStride: Dim, CStride: Dim> impl<'a, T, R: Dim, C: Dim, RStride: Dim, CStride: Dim> SliceStorageMut<'a, MaybeUninit, R, C, RStride, CStride> { + /// Assumes a slice storage's entries to be initialized. This operation should be near zero-cost. pub unsafe fn assume_init(self) -> SliceStorageMut<'a, T, R, C, RStride, CStride> { SliceStorageMut::from_raw_parts(self.ptr as *mut T, self.shape, self.strides) } @@ -760,6 +762,7 @@ impl> Matrix { impl<'a, T, R: Dim, C: Dim, RStride: Dim, CStride: Dim> MatrixSlice<'a, MaybeUninit, R, C, RStride, CStride> { + /// Assumes a matrix slices's entries to be initialized. This operation should be near zero-cost. pub unsafe fn slice_assume_init(self) -> MatrixSlice<'a, T, R, C, RStride, CStride> { Matrix::from_data(self.data.assume_init()) } @@ -768,6 +771,7 @@ impl<'a, T, R: Dim, C: Dim, RStride: Dim, CStride: Dim> impl<'a, T, R: Dim, C: Dim, RStride: Dim, CStride: Dim> MatrixSliceMut<'a, MaybeUninit, R, C, RStride, CStride> { + /// Assumes a matrix slices's entries to be initialized. This operation should be near zero-cost. pub unsafe fn slice_assume_init(self) -> MatrixSliceMut<'a, T, R, C, RStride, CStride> { Matrix::from_data(self.data.assume_init()) } diff --git a/src/debug/random_orthogonal.rs b/src/debug/random_orthogonal.rs index c9684238..11ea832a 100644 --- a/src/debug/random_orthogonal.rs +++ b/src/debug/random_orthogonal.rs @@ -1,3 +1,5 @@ +use std::fmt; + #[cfg(feature = "arbitrary")] use crate::base::storage::Owned; #[cfg(feature = "arbitrary")] @@ -5,20 +7,48 @@ use quickcheck::{Arbitrary, Gen}; use crate::base::allocator::Allocator; use crate::base::dimension::{Dim, Dynamic}; -use crate::base::Scalar; use crate::base::{DefaultAllocator, OMatrix}; use crate::linalg::givens::GivensRotation; +use crate::storage::Owned; use simba::scalar::ComplexField; /// A random orthogonal matrix. -#[derive(Clone, Debug)] -pub struct RandomOrthogonal +pub struct RandomOrthogonal where DefaultAllocator: Allocator, { m: OMatrix, } +impl Copy for RandomOrthogonal +where + DefaultAllocator: Allocator, + Owned: Copy, +{ +} + +impl Clone for RandomOrthogonal +where + DefaultAllocator: Allocator, + Owned: Clone, +{ + fn clone(&self) -> Self { + Self { m: self.m.clone() } + } +} + +impl fmt::Debug for RandomOrthogonal +where + DefaultAllocator: Allocator, + Owned: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("RandomOrthogonal") + .field("m", &self.m) + .finish() + } +} + impl RandomOrthogonal where DefaultAllocator: Allocator, diff --git a/src/debug/random_sdp.rs b/src/debug/random_sdp.rs index a915f2fc..bec8ea93 100644 --- a/src/debug/random_sdp.rs +++ b/src/debug/random_sdp.rs @@ -1,3 +1,5 @@ +use std::fmt; + #[cfg(feature = "arbitrary")] use crate::base::storage::Owned; #[cfg(feature = "arbitrary")] @@ -5,21 +7,47 @@ use quickcheck::{Arbitrary, Gen}; use crate::base::allocator::Allocator; use crate::base::dimension::{Dim, Dynamic}; -use crate::base::Scalar; use crate::base::{DefaultAllocator, OMatrix}; +use crate::storage::Owned; use simba::scalar::ComplexField; use crate::debug::RandomOrthogonal; /// A random, well-conditioned, symmetric definite-positive matrix. -#[derive(Clone, Debug)] -pub struct RandomSDP +pub struct RandomSDP where DefaultAllocator: Allocator, { m: OMatrix, } +impl Copy for RandomSDP +where + DefaultAllocator: Allocator, + Owned: Copy, +{ +} + +impl Clone for RandomSDP +where + DefaultAllocator: Allocator, + Owned: Clone, +{ + fn clone(&self) -> Self { + Self { m: self.m.clone() } + } +} + +impl fmt::Debug for RandomSDP +where + DefaultAllocator: Allocator, + Owned: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("RandomSDP").field("m", &self.m).finish() + } +} + impl RandomSDP where DefaultAllocator: Allocator, diff --git a/src/geometry/dual_quaternion.rs b/src/geometry/dual_quaternion.rs index 2c5968ef..17af51fe 100644 --- a/src/geometry/dual_quaternion.rs +++ b/src/geometry/dual_quaternion.rs @@ -279,8 +279,11 @@ impl<'a, T: Deserialize<'a>> Deserialize<'a> for DualQuaternion { impl DualQuaternion { // TODO: Cloning shouldn't be necessary. - fn to_vector(self) -> OVectorwhere T:Clone { - (*self.as_ref()).into() + fn to_vector(self) -> OVector + where + T: Clone, + { + (self.as_ref().clone()).into() } } @@ -892,7 +895,7 @@ impl Default for UnitDualQuaternion { } } -impl fmt::Display for UnitDualQuaternion { +impl fmt::Display for UnitDualQuaternion { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { if let Some(axis) = self.rotation().axis() { let axis = axis.into_inner(); diff --git a/src/geometry/point.rs b/src/geometry/point.rs index f65813e9..f3c01a94 100644 --- a/src/geometry/point.rs +++ b/src/geometry/point.rs @@ -5,7 +5,7 @@ use std::fmt; use std::hash; #[cfg(feature = "abomonation-serialize")] use std::io::{Result as IOResult, Write}; -use std::mem::MaybeUninit; +use std::mem::{ManuallyDrop, MaybeUninit}; #[cfg(feature = "serde-serialize-no-std")] use serde::{Deserialize, Deserializer, Serialize, Serializer}; @@ -43,7 +43,6 @@ use crate::Scalar; /// may have some other methods, e.g., `isometry.inverse_transform_point(&point)`. See the documentation /// of said transformations for details. #[repr(C)] -// TODO: figure out why #[derive(Clone, Debug)] doesn't work! pub struct OPoint where DefaultAllocator: InnerAllocator, @@ -78,6 +77,16 @@ where } } +impl fmt::Debug for OPoint +where + DefaultAllocator: Allocator, + OVector: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("OPoint").field("coords",&self.coords).finish() + } +} + #[cfg(feature = "bytemuck")] unsafe impl bytemuck::Zeroable for OPoint where @@ -185,7 +194,10 @@ where /// assert_eq!(p, Point3::new(10.0, 20.0, 30.0)); /// ``` #[inline] - pub fn apply T>(&mut self, f: F) { + pub fn apply T>(&mut self, f: F) + where + T: Clone, + { self.coords.apply(f) } @@ -224,6 +236,8 @@ where unsafe { res.assume_init() } } + /// Converts this point into a vector in homogeneous coordinates, i.e., appends a `1` at the + /// end of it. Unlike [`to_homogeneous`], this method does not require `T: Clone`. pub fn into_homogeneous(self) -> OVector> where T: One, @@ -231,17 +245,15 @@ where DefaultAllocator: Allocator>, { let mut res = OVector::<_, DimNameSum>::new_uninitialized(); + let mut md = self.manually_drop(); - // TODO: maybe we can move the whole array at once? Or use `into_iter` - // to avoid double-dropping. for i in 0..D::dim() { unsafe { - *res.get_unchecked_mut(i) = MaybeUninit::new(*self.coords.get_unchecked(i)); + *res.get_unchecked_mut(i) = + MaybeUninit::new(ManuallyDrop::take(md.coords.get_unchecked_mut(i))); } } - // Fix double drop - unsafe { *res.get_unchecked_mut(D::dim()) = MaybeUninit::new(T::one()); res.assume_init() diff --git a/src/geometry/point_construction.rs b/src/geometry/point_construction.rs index 34048a35..581dca8d 100644 --- a/src/geometry/point_construction.rs +++ b/src/geometry/point_construction.rs @@ -1,4 +1,4 @@ -use std::mem::MaybeUninit; +use std::mem::{ManuallyDrop, MaybeUninit}; #[cfg(feature = "arbitrary")] use quickcheck::{Arbitrary, Gen}; @@ -32,6 +32,13 @@ where OPoint::from(OVector::new_uninitialized_generic(D::name(), Const::<1>)) } + /// Converts `self` into a point whose coordinates must be manually dropped. + /// This should be zero-cost. + #[inline] + pub fn manually_drop(self) -> OPoint, D> { + OPoint::from(self.coords.manually_drop()) + } + /// Creates a new point with all coordinates equal to zero. /// /// # Example diff --git a/src/geometry/point_conversion.rs b/src/geometry/point_conversion.rs index 02ca1895..b564f0ad 100644 --- a/src/geometry/point_conversion.rs +++ b/src/geometry/point_conversion.rs @@ -91,8 +91,10 @@ impl From<[T; D]> for Point { } } -impl From> for [T; D] where -T: Clone,{ +impl From> for [T; D] +where + T: Clone, +{ #[inline] fn from(p: Point) -> Self { p.coords.into() diff --git a/src/geometry/transform_ops.rs b/src/geometry/transform_ops.rs index 8a21afd0..2fa098fe 100644 --- a/src/geometry/transform_ops.rs +++ b/src/geometry/transform_ops.rs @@ -8,7 +8,8 @@ use simba::scalar::{ClosedAdd, ClosedMul, RealField, SubsetOf}; use crate::base::allocator::Allocator; use crate::base::dimension::{DimNameAdd, DimNameSum, U1}; -use crate::base::{Const, DefaultAllocator, OMatrix, SVector, Scalar};use crate::storage::Owned; +use crate::base::{Const, DefaultAllocator, OMatrix, SVector, Scalar}; +use crate::storage::Owned; use crate::geometry::{ Isometry, Point, Rotation, Similarity, SubTCategoryOf, SuperTCategoryOf, TAffine, TCategory, @@ -344,7 +345,8 @@ md_impl_all!( const D; for CA, CB; where Const: DimNameAdd, CA: TCategoryMul, CB: SubTCategoryOf, - DefaultAllocator: Allocator, U1>, DimNameSum, U1>>; + DefaultAllocator: Allocator, U1>, DimNameSum, U1>>, + Transform: Clone; // There's probably a better bound here. self: Transform, rhs: Transform, Output = Transform; [val val] => #[allow(clippy::suspicious_arithmetic_impl)] { self * rhs.inverse() }; [ref val] => #[allow(clippy::suspicious_arithmetic_impl)] { self * rhs.inverse() }; diff --git a/src/linalg/bidiagonal.rs b/src/linalg/bidiagonal.rs index f25981a2..b7cb5cd6 100644 --- a/src/linalg/bidiagonal.rs +++ b/src/linalg/bidiagonal.rs @@ -302,7 +302,7 @@ where let axis = self.uv.slice_range(i, i + shift..); let mut axis_packed = axis_packed.rows_range_mut(i + shift..); axis_packed.tr_copy_init_from(&axis); - let axis_packed = unsafe { axis_packed.slice_assume_init() }; + let axis_packed = unsafe { axis_packed.slice_assume_init() }; // TODO: sometimes, the axis might have a zero magnitude. let refl = Reflection::new(Unit::new_unchecked(axis_packed), T::zero()); diff --git a/src/linalg/col_piv_qr.rs b/src/linalg/col_piv_qr.rs index 1d01f294..4c896587 100644 --- a/src/linalg/col_piv_qr.rs +++ b/src/linalg/col_piv_qr.rs @@ -105,7 +105,7 @@ where ColPivQR { col_piv_qr: matrix, p, - diag:unsafe{diag.assume_init()}, + diag: unsafe { diag.assume_init() }, } } diff --git a/src/linalg/permutation_sequence.rs b/src/linalg/permutation_sequence.rs index 2cdfdd41..9f4bbdc3 100644 --- a/src/linalg/permutation_sequence.rs +++ b/src/linalg/permutation_sequence.rs @@ -99,11 +99,9 @@ where /// Creates a new sequence of D identity permutations. #[inline] pub fn identity_generic(dim: D) -> Self { - - Self { - len: 0, - ipiv: OVector::new_uninitialized_generic(dim, Const::<1>), - + Self { + len: 0, + ipiv: OVector::new_uninitialized_generic(dim, Const::<1>), } } diff --git a/src/linalg/symmetric_tridiagonal.rs b/src/linalg/symmetric_tridiagonal.rs index cff9dc11..de45717f 100644 --- a/src/linalg/symmetric_tridiagonal.rs +++ b/src/linalg/symmetric_tridiagonal.rs @@ -105,7 +105,7 @@ where let mut p = p.rows_range_mut(i..); p.hegemv_z(crate::convert(2.0), &m, &axis); - let p = unsafe { p.slice_assume_init() }; + let p = unsafe { p.slice_assume_init() }; let dot = axis.dotc(&p); m.hegerc(-T::one(), &p, &axis, T::one()); diff --git a/src/proptest/mod.rs b/src/proptest/mod.rs index 794080fe..a6bde56c 100644 --- a/src/proptest/mod.rs +++ b/src/proptest/mod.rs @@ -329,7 +329,7 @@ where D: Dim, DefaultAllocator: Allocator, { - matrix_(value_strategy, length.into(), Const::<1>.into()) + matrix_(value_strategy, length.into(), U1.into()) } impl Default for MatrixParameters diff --git a/src/sparse/cs_matrix.rs b/src/sparse/cs_matrix.rs index bf2edf4e..4bb15759 100644 --- a/src/sparse/cs_matrix.rs +++ b/src/sparse/cs_matrix.rs @@ -279,7 +279,7 @@ where CsMatrix { data: CsVecStorage { shape: (nrows, ncols), - p: OVector::zeros_generic(ncols, Const::<1>), + p: OVector::zeros_generic(ncols, U1), i, vals, }, @@ -429,7 +429,7 @@ impl> CsMatrix { let nvals = self.len(); let mut res = CsMatrix::new_uninitialized_generic(ncols, nrows, nvals); - let mut workspace = Vector::zeros_generic(nrows, Const::<1>); + let mut workspace = Vector::zeros_generic(nrows, U1); // Compute p. for i in 0..nvals { @@ -473,7 +473,7 @@ where // Size = R let nrows = self.data.shape().0; let mut workspace = - unsafe { crate::unimplemented_or_uninitialized_generic!(nrows, Const::<1>) }; + unsafe { crate::unimplemented_or_uninitialized_generic!(nrows, U1) }; self.sort_with_workspace(workspace.as_mut_slice()); } diff --git a/src/sparse/cs_matrix_cholesky.rs b/src/sparse/cs_matrix_cholesky.rs index 6d52d0a6..3ce66c92 100644 --- a/src/sparse/cs_matrix_cholesky.rs +++ b/src/sparse/cs_matrix_cholesky.rs @@ -49,9 +49,9 @@ where // Workspaces. let work_x = - unsafe { crate::unimplemented_or_uninitialized_generic!(m.data.shape().0, Const::<1>) }; + unsafe { crate::unimplemented_or_uninitialized_generic!(m.data.shape().0, U1) }; let work_c = - unsafe { crate::unimplemented_or_uninitialized_generic!(m.data.shape().1, Const::<1>) }; + unsafe { crate::unimplemented_or_uninitialized_generic!(m.data.shape().1, U1) }; let mut original_p = m.data.p.as_slice().to_vec(); original_p.push(m.data.i.len()); @@ -295,7 +295,7 @@ where let (nrows, ncols) = m.data.shape(); let mut rows = Vec::with_capacity(m.len()); let mut cols = - unsafe { crate::unimplemented_or_uninitialized_generic!(m.data.shape().0, Const::<1>) }; + unsafe { crate::unimplemented_or_uninitialized_generic!(m.data.shape().0, U1) }; let mut marks = Vec::new(); // NOTE: the following will actually compute the non-zero pattern of diff --git a/src/sparse/cs_matrix_ops.rs b/src/sparse/cs_matrix_ops.rs index e03b12a5..a9f22fcd 100644 --- a/src/sparse/cs_matrix_ops.rs +++ b/src/sparse/cs_matrix_ops.rs @@ -148,7 +148,7 @@ where ); let mut res = CsMatrix::new_uninitialized_generic(nrows1, ncols2, self.len() + rhs.len()); - let mut workspace = OVector::::zeros_generic(nrows1, Const::<1>); + let mut workspace = OVector::::zeros_generic(nrows1, U1); let mut nz = 0; for j in 0..ncols2.value() { @@ -241,9 +241,9 @@ where ); let mut res = CsMatrix::new_uninitialized_generic(nrows1, ncols2, self.len() + rhs.len()); - let mut timestamps = OVector::zeros_generic(nrows1, Const::<1>); + let mut timestamps = OVector::zeros_generic(nrows1, U1); let mut workspace = - unsafe { crate::unimplemented_or_uninitialized_generic!(nrows1, Const::<1>) }; + unsafe { crate::unimplemented_or_uninitialized_generic!(nrows1, U1) }; let mut nz = 0; for j in 0..ncols2.value() { diff --git a/src/sparse/cs_matrix_solve.rs b/src/sparse/cs_matrix_solve.rs index 235fcef3..ad38fe56 100644 --- a/src/sparse/cs_matrix_solve.rs +++ b/src/sparse/cs_matrix_solve.rs @@ -153,7 +153,7 @@ impl> CsMatrix { // We sort the reach so the result matrix has sorted indices. reach.sort_unstable(); let mut workspace = - unsafe { crate::unimplemented_or_uninitialized_generic!(b.data.shape().0, Const::<1>) }; + unsafe { crate::unimplemented_or_uninitialized_generic!(b.data.shape().0, U1) }; for i in reach.iter().cloned() { workspace[i] = T::zero(); @@ -191,7 +191,7 @@ impl> CsMatrix { // Copy the result into a sparse vector. let mut result = - CsVector::new_uninitialized_generic(b.data.shape().0, Const::<1>, reach.len()); + CsVector::new_uninitialized_generic(b.data.shape().0, U1, reach.len()); for (i, val) in reach.iter().zip(result.data.vals.iter_mut()) { *val = workspace[*i]; @@ -255,7 +255,7 @@ impl> CsMatrix { S2: CsStorage, DefaultAllocator: Allocator, { - let mut visited = OVector::repeat_generic(self.data.shape().1, Const::<1>, false); + let mut visited = OVector::repeat_generic(self.data.shape().1, U1, false); let mut stack = Vec::new(); for irow in b.data.column_row_indices(0) { diff --git a/tests/proptest/mod.rs b/tests/proptest/mod.rs index ec2e2c7b..60d32248 100644 --- a/tests/proptest/mod.rs +++ b/tests/proptest/mod.rs @@ -180,11 +180,11 @@ macro_rules! generate_matrix_sanity_test { // Test all fixed-size matrices with row/col dimensions up to 3 generate_matrix_sanity_test!(test_matrix_u0_u0, Const::<0>, Const::<0>); -generate_matrix_sanity_test!(test_matrix_u1_u0, Const::<1>, Const::<0>); -generate_matrix_sanity_test!(test_matrix_u0_u1, Const::<0>, Const::<1>); -generate_matrix_sanity_test!(test_matrix_u1_u1, Const::<1>, Const::<1>); -generate_matrix_sanity_test!(test_matrix_u2_u1, Const::<2>, Const::<1>); -generate_matrix_sanity_test!(test_matrix_u1_u2, Const::<1>, Const::<2>); +generate_matrix_sanity_test!(test_matrix_u1_u0, U1, Const::<0>); +generate_matrix_sanity_test!(test_matrix_u0_u1, Const::<0>, U1); +generate_matrix_sanity_test!(test_matrix_u1_u1, U1, U1); +generate_matrix_sanity_test!(test_matrix_u2_u1, Const::<2>, U1); +generate_matrix_sanity_test!(test_matrix_u1_u2, U1, Const::<2>); generate_matrix_sanity_test!(test_matrix_u2_u2, Const::<2>, Const::<2>); generate_matrix_sanity_test!(test_matrix_u3_u2, Const::<3>, Const::<2>); generate_matrix_sanity_test!(test_matrix_u2_u3, Const::<2>, Const::<3>);