Finally figured out some trait nitty-gritty

This commit is contained in:
Violeta Hernández 2021-07-14 13:24:27 -05:00
parent 1a78b00476
commit 8d10e69e33
9 changed files with 105 additions and 95 deletions

View File

@ -153,15 +153,15 @@ where
where where
DefaultAllocator: Allocator<Complex<T>, D>, DefaultAllocator: Allocator<Complex<T>, D>,
{ {
let mut out = unsafe { let mut out =
OVector::new_uninitialized_generic(self.t.data.shape().0, Const::<1>).assume_init() unsafe { OVector::new_uninitialized_generic(self.t.data.shape().0, Const::<1>) };
};
for i in 0..out.len() { for i in 0..out.len() {
out[i] = Complex::new(self.re[i], self.im[i]) out[i] = MaybeUninit::new(Complex::new(self.re[i], self.im[i]));
} }
out // Safety: all entries have been initialized.
unsafe { out.assume_init() }
} }
} }

View File

@ -1,3 +1,4 @@
#[cfg(any(feature = "alloc", feature = "std"))] #[cfg(any(feature = "alloc", feature = "std"))]
use crate::base::dimension::Dynamic; use crate::base::dimension::Dynamic;
use crate::base::dimension::{U1, U2, U3, U4, U5, U6}; use crate::base::dimension::{U1, U2, U3, U4, U5, U6};

View File

@ -1,6 +1,5 @@
//! Abstract definition of a matrix data storage allocator. //! Abstract definition of a matrix data storage allocator.
use std::any::Any;
use std::mem::MaybeUninit; use std::mem::MaybeUninit;
use crate::base::constraint::{SameNumberOfColumns, SameNumberOfRows, ShapeConstraint}; use crate::base::constraint::{SameNumberOfColumns, SameNumberOfRows, ShapeConstraint};
@ -17,7 +16,7 @@ use crate::base::DefaultAllocator;
/// ///
/// Every allocator must be both static and dynamic. Though not all implementations may share the /// Every allocator must be both static and dynamic. Though not all implementations may share the
/// same `Buffer` type. /// same `Buffer` type.
pub trait Allocator<T, R: Dim, C: Dim = U1>: Any + Sized { pub trait Allocator<T, R: Dim, C: Dim = U1>: 'static + Sized {
/// The type of buffer this allocator can instanciate. /// The type of buffer this allocator can instanciate.
type Buffer: ContiguousStorageMut<T, R, C>; type Buffer: ContiguousStorageMut<T, R, C>;

View File

@ -30,16 +30,8 @@ use crate::base::{
#[macro_export] #[macro_export]
macro_rules! unimplemented_or_uninitialized_generic { macro_rules! unimplemented_or_uninitialized_generic {
($nrows:expr, $ncols:expr) => {{ ($nrows:expr, $ncols:expr) => {{
#[cfg(feature="no_unsound_assume_init")] { crate::base::Matrix::new_uninitialized_generic($nrows, $ncols)
// Some of the call sites need the number of rows and columns from this to infer a type, so }};
// uninitialized memory is used to infer the type, as `T: Zero` isn't available at all callsites.
// This may technically still be UB even though the assume_init is dead code, but all callsites should be fixed before #556 is closed.
let typeinference_helper = crate::base::Matrix::new_uninitialized_generic($nrows, $ncols);
unimplemented!();
typeinference_helper.assume_init()
}
#[cfg(not(feature="no_unsound_assume_init"))] { crate::base::Matrix::new_uninitialized_generic($nrows, $ncols).assume_init() }
}}
} }
/// # Generic constructors /// # Generic constructors
@ -78,7 +70,7 @@ where
#[inline] #[inline]
pub fn zeros_generic(nrows: R, ncols: C) -> Self pub fn zeros_generic(nrows: R, ncols: C) -> Self
where where
T: Zero, T: Zero + Clone,
{ {
Self::from_element_generic(nrows, ncols, T::zero()) Self::from_element_generic(nrows, ncols, T::zero())
} }
@ -98,22 +90,28 @@ where
/// The order of elements in the slice must follow the usual mathematic writing, i.e., /// The order of elements in the slice must follow the usual mathematic writing, i.e.,
/// row-by-row. /// row-by-row.
#[inline] #[inline]
pub fn from_row_slice_generic(nrows: R, ncols: C, slice: &[T]) -> Self { pub fn from_row_slice_generic(nrows: R, ncols: C, slice: &[T]) -> Self
where
T: Clone,
{
assert!( assert!(
slice.len() == nrows.value() * ncols.value(), slice.len() == nrows.value() * ncols.value(),
"Matrix init. error: the slice did not contain the right number of elements." "Matrix init. error: the slice did not contain the right number of elements."
); );
let mut res = unsafe { crate::unimplemented_or_uninitialized_generic!(nrows, ncols) }; let mut res = Matrix::new_uninitialized_generic(nrows, ncols);
let mut iter = slice.iter(); let mut iter = slice.iter();
for i in 0..nrows.value() { for i in 0..nrows.value() {
for j in 0..ncols.value() { for j in 0..ncols.value() {
unsafe { *res.get_unchecked_mut((i, j)) = iter.next().unwrap().inlined_clone() } unsafe {
*res.get_unchecked_mut((i, j)) = MaybeUninit::new(iter.next().unwrap().clone());
}
} }
} }
res // Safety: all entries have been initialized.
unsafe { res.assume_init() }
} }
/// Creates a matrix with its elements filled with the components provided by a slice. The /// Creates a matrix with its elements filled with the components provided by a slice. The
@ -130,15 +128,18 @@ where
where where
F: FnMut(usize, usize) -> T, F: FnMut(usize, usize) -> T,
{ {
let mut res: Self = unsafe { crate::unimplemented_or_uninitialized_generic!(nrows, ncols) }; let mut res = Matrix::new_uninitialized_generic(nrows, ncols);
for j in 0..ncols.value() { for j in 0..ncols.value() {
for i in 0..nrows.value() { for i in 0..nrows.value() {
unsafe { *res.get_unchecked_mut((i, j)) = f(i, j) } unsafe {
*res.get_unchecked_mut((i, j)) = MaybeUninit::new(f(i, j));
}
} }
} }
res // Safety: all entries have been initialized.
unsafe { Matrix::assume_init(res) }
} }
/// Creates a new identity matrix. /// Creates a new identity matrix.
@ -160,7 +161,7 @@ where
#[inline] #[inline]
pub fn from_diagonal_element_generic(nrows: R, ncols: C, elt: T) -> Self pub fn from_diagonal_element_generic(nrows: R, ncols: C, elt: T) -> Self
where where
T: Zero + One, T: Zero + One+Clone,
{ {
let mut res = Self::zeros_generic(nrows, ncols); let mut res = Self::zeros_generic(nrows, ncols);
@ -178,7 +179,7 @@ where
#[inline] #[inline]
pub fn from_partial_diagonal_generic(nrows: R, ncols: C, elts: &[T]) -> Self pub fn from_partial_diagonal_generic(nrows: R, ncols: C, elts: &[T]) -> Self
where where
T: Zero, T: Zero+Clone,
{ {
let mut res = Self::zeros_generic(nrows, ncols); let mut res = Self::zeros_generic(nrows, ncols);
assert!( assert!(
@ -187,7 +188,7 @@ where
); );
for (i, elt) in elts.iter().enumerate() { for (i, elt) in elts.iter().enumerate() {
unsafe { *res.get_unchecked_mut((i, i)) = elt.inlined_clone() } unsafe { *res.get_unchecked_mut((i, i)) = elt.clone() }
} }
res res
@ -211,7 +212,7 @@ where
/// ``` /// ```
#[inline] #[inline]
pub fn from_rows<SB>(rows: &[Matrix<T, Const<1>, C, SB>]) -> Self pub fn from_rows<SB>(rows: &[Matrix<T, Const<1>, C, SB>]) -> Self
where where T:Clone,
SB: Storage<T, Const<1>, C>, SB: Storage<T, Const<1>, C>,
{ {
assert!(!rows.is_empty(), "At least one row must be given."); assert!(!rows.is_empty(), "At least one row must be given.");
@ -231,7 +232,7 @@ where
// TODO: optimize that. // TODO: optimize that.
Self::from_fn_generic(R::from_usize(nrows), C::from_usize(ncols), |i, j| { Self::from_fn_generic(R::from_usize(nrows), C::from_usize(ncols), |i, j| {
rows[i][(0, j)].inlined_clone() rows[i][(0, j)].clone()
}) })
} }
@ -253,7 +254,7 @@ where
/// ``` /// ```
#[inline] #[inline]
pub fn from_columns<SB>(columns: &[Vector<T, R, SB>]) -> Self pub fn from_columns<SB>(columns: &[Vector<T, R, SB>]) -> Self
where where T:Clone,
SB: Storage<T, R>, SB: Storage<T, R>,
{ {
assert!(!columns.is_empty(), "At least one column must be given."); assert!(!columns.is_empty(), "At least one column must be given.");
@ -273,7 +274,7 @@ where
// TODO: optimize that. // TODO: optimize that.
Self::from_fn_generic(R::from_usize(nrows), C::from_usize(ncols), |i, j| { Self::from_fn_generic(R::from_usize(nrows), C::from_usize(ncols), |i, j| {
columns[j][i].inlined_clone() columns[j][i].clone()
}) })
} }
@ -458,7 +459,7 @@ macro_rules! impl_constructors(
#[inline] #[inline]
pub fn zeros($($args: usize),*) -> Self pub fn zeros($($args: usize),*) -> Self
where where
T: Zero T: Zero + Clone
{ {
Self::zeros_generic($($gargs),*) Self::zeros_generic($($gargs),*)
} }

View File

@ -3,6 +3,7 @@ use alloc::vec::Vec;
use simba::scalar::{SubsetOf, SupersetOf}; use simba::scalar::{SubsetOf, SupersetOf};
use std::borrow::{Borrow, BorrowMut}; use std::borrow::{Borrow, BorrowMut};
use std::convert::{AsMut, AsRef, From, Into}; use std::convert::{AsMut, AsRef, From, Into};
use std::mem::MaybeUninit;
use simba::simd::{PrimitiveSimdValue, SimdValue}; use simba::simd::{PrimitiveSimdValue, SimdValue};
@ -44,17 +45,19 @@ where
let nrows2 = R2::from_usize(nrows); let nrows2 = R2::from_usize(nrows);
let ncols2 = C2::from_usize(ncols); let ncols2 = C2::from_usize(ncols);
let mut res: OMatrix<T2, R2, C2> = let mut res = OMatrix::<T2, R2, C2>::new_uninitialized_generic(nrows2, ncols2);
unsafe { crate::unimplemented_or_uninitialized_generic!(nrows2, ncols2) };
for i in 0..nrows { for i in 0..nrows {
for j in 0..ncols { for j in 0..ncols {
unsafe { unsafe {
*res.get_unchecked_mut((i, j)) = T2::from_subset(self.get_unchecked((i, j))) *res.get_unchecked_mut((i, j)) =
MaybeUninit::new(T2::from_subset(self.get_unchecked((i, j))));
} }
} }
} }
res // Safety: all entries have been initialized.
unsafe { Matrix::assume_init(res) }
} }
#[inline] #[inline]
@ -68,16 +71,18 @@ where
let nrows = R1::from_usize(nrows2); let nrows = R1::from_usize(nrows2);
let ncols = C1::from_usize(ncols2); let ncols = C1::from_usize(ncols2);
let mut res: Self = unsafe { crate::unimplemented_or_uninitialized_generic!(nrows, ncols) }; let mut res = OMatrix::new_uninitialized_generic(nrows, ncols);
for i in 0..nrows2 { for i in 0..nrows2 {
for j in 0..ncols2 { for j in 0..ncols2 {
unsafe { unsafe {
*res.get_unchecked_mut((i, j)) = m.get_unchecked((i, j)).to_subset_unchecked() *res.get_unchecked_mut((i, j)) =
MaybeUninit::new(m.get_unchecked((i, j)).to_subset_unchecked());
} }
} }
} }
res // Safety: all entries have been initialized.
unsafe { res.assume_init() }
} }
} }

View File

@ -68,7 +68,7 @@ impl<T, const R: usize, const C: usize> Allocator<T, Const<R>, Const<C>> for Def
); );
// Safety: we have initialized all entries. // Safety: we have initialized all entries.
unsafe { Self::assume_init(res) } unsafe { <Self as Allocator<T, Const<R>, Const<C>>>::assume_init(res) }
} }
} }

View File

@ -34,6 +34,10 @@ use crate::{ArrayStorage, SMatrix, SimdComplexField};
#[cfg(any(feature = "std", feature = "alloc"))] #[cfg(any(feature = "std", feature = "alloc"))]
use crate::{DMatrix, DVector, Dynamic, VecStorage}; use crate::{DMatrix, DVector, Dynamic, VecStorage};
/// An uninitialized matrix.
pub type UninitMatrix<T, R, C> =
Matrix<MaybeUninit<T>, R, C, <DefaultAllocator as Allocator<T, R, C>>::UninitBuffer>;
/// A square matrix. /// A square matrix.
pub type SquareMatrix<T, D, S> = Matrix<T, D, D, S>; pub type SquareMatrix<T, D, S> = Matrix<T, D, D, S>;
@ -347,39 +351,34 @@ impl<T, R, C, S> Matrix<T, R, C, S> {
} }
} }
impl<T, R: Dim, C: Dim, S> Matrix<T, R, C, S> impl<T, R: Dim, C: Dim>
Matrix<MaybeUninit<T>, R, C, <DefaultAllocator as Allocator<T, R, C>>::UninitBuffer>
where where
S: Storage<T, R, C>, DefaultAllocator: Allocator<T, R, C>,
DefaultAllocator: Allocator<T, R, C, Buffer = S>,
{ {
/// Allocates a matrix with the given number of rows and columns without initializing its content. /// Allocates a matrix with the given number of rows and columns without initializing its content.
pub fn new_uninitialized_generic( ///
nrows: R, /// Note: calling `Self::new_uninitialized_generic` is often **not** what you want to do. Consider
ncols: C, /// calling `Matrix::new_uninitialized_generic` instead.
) -> Matrix<MaybeUninit<T>, R, C, <DefaultAllocator as Allocator<T, R, C>>::UninitBuffer> { pub fn new_uninitialized_generic(nrows: R, ncols: C) -> Self {
Matrix { Self {
data: <DefaultAllocator as Allocator<T, R, C>>::allocate_uninitialized(nrows, ncols), data: <DefaultAllocator as Allocator<T, R, C>>::allocate_uninitialized(nrows, ncols),
_phantoms: PhantomData, _phantoms: PhantomData,
} }
} }
} }
impl<T, R: Dim, C: Dim, S> Matrix<MaybeUninit<T>, R, C, S> impl<T, R: Dim, C: Dim>
Matrix<MaybeUninit<T>, R, C, <DefaultAllocator as Allocator<T, R, C>>::UninitBuffer>
where where
S: Storage<T, R, C>, DefaultAllocator: Allocator<T, R, C>,
DefaultAllocator: Allocator<T, R, C, Buffer = S>,
{ {
/// Assumes a matrix's entries to be initialized. This operation should be near zero-cost. /// Assumes a matrix's entries to be initialized. This operation should be near zero-cost.
pub unsafe fn assume_init( pub unsafe fn assume_init(
uninit: Matrix< self,
MaybeUninit<T>, ) -> Matrix<T, R, C, <DefaultAllocator as Allocator<T, R, C>>::Buffer> {
R,
C,
<DefaultAllocator as Allocator<T, R, C>>::UninitBuffer,
>,
) -> Matrix<T, R, C, S> {
Matrix { Matrix {
data: <DefaultAllocator as Allocator<T, R, C>>::assume_init(uninit.data), data: <DefaultAllocator as Allocator<T, R, C>>::assume_init(self.data),
_phantoms: PhantomData, _phantoms: PhantomData,
} }
} }
@ -654,24 +653,25 @@ impl<T, R: Dim, C: Dim, S: Storage<T, R, C>> Matrix<T, R, C, S> {
let nrows: SameShapeR<R, R2> = Dim::from_usize(nrows); let nrows: SameShapeR<R, R2> = Dim::from_usize(nrows);
let ncols: SameShapeC<C, C2> = Dim::from_usize(ncols); let ncols: SameShapeC<C, C2> = Dim::from_usize(ncols);
let mut res: MatrixSum<T, R, C, R2, C2> = let mut res = Matrix::new_uninitialized_generic(nrows, ncols);
unsafe { crate::unimplemented_or_uninitialized_generic!(nrows, ncols) };
// TODO: use copy_from // TODO: use copy_from
for j in 0..res.ncols() { for j in 0..res.ncols() {
for i in 0..res.nrows() { for i in 0..res.nrows() {
unsafe { unsafe {
*res.get_unchecked_mut((i, j)) = self.get_unchecked((i, j)).clone(); *res.get_unchecked_mut((i, j)) =
MaybeUninit::new(self.get_unchecked((i, j)).clone());
} }
} }
} }
res unsafe { Matrix::assume_init(res) }
} }
/// Transposes `self` and store the result into `out`. /// Transposes `self` and store the result into `out`, which will become
/// fully initialized.
#[inline] #[inline]
pub fn transpose_to<R2: Dim, C2: Dim, SB>(&self, out: &mut Matrix<T, R2, C2, SB>) pub fn transpose_to<R2: Dim, C2: Dim, SB>(&self, out: &mut Matrix<MaybeUninit<T>, R2, C2, SB>)
where where
T: Clone, T: Clone,
SB: StorageMut<T, R2, C2>, SB: StorageMut<T, R2, C2>,
@ -687,7 +687,8 @@ impl<T, R: Dim, C: Dim, S: Storage<T, R, C>> Matrix<T, R, C, S> {
for i in 0..nrows { for i in 0..nrows {
for j in 0..ncols { for j in 0..ncols {
unsafe { unsafe {
*out.get_unchecked_mut((j, i)) = self.get_unchecked((i, j)).clone(); *out.get_unchecked_mut((j, i)) =
MaybeUninit::new(self.get_unchecked((i, j)).clone());
} }
} }
} }
@ -702,17 +703,18 @@ impl<T, R: Dim, C: Dim, S: Storage<T, R, C>> Matrix<T, R, C, S> {
DefaultAllocator: Allocator<T, C, R>, DefaultAllocator: Allocator<T, C, R>,
{ {
let (nrows, ncols) = self.data.shape(); let (nrows, ncols) = self.data.shape();
let mut res = OMatrix::new_uninitialized_generic(ncols, nrows);
unsafe {
let mut res = crate::unimplemented_or_uninitialized_generic!(ncols, nrows);
self.transpose_to(&mut res); self.transpose_to(&mut res);
res unsafe {
// Safety: res is now fully initialized due to the guarantees of transpose_to.
res.assume_init()
} }
} }
} }
/// # Elementwise mapping and folding /// # Elementwise mapping and folding
// Todo: maybe make ref versions of these methods that can be used when T is expensive to clone?
impl<T, R: Dim, C: Dim, S: Storage<T, R, C>> Matrix<T, R, C, S> { impl<T, R: Dim, C: Dim, S: Storage<T, R, C>> Matrix<T, R, C, S> {
/// Returns a matrix containing the result of `f` applied to each of its entries. /// Returns a matrix containing the result of `f` applied to each of its entries.
#[inline] #[inline]
@ -724,19 +726,19 @@ impl<T, R: Dim, C: Dim, S: Storage<T, R, C>> Matrix<T, R, C, S> {
{ {
let (nrows, ncols) = self.data.shape(); let (nrows, ncols) = self.data.shape();
let mut res: OMatrix<T2, R, C> = let mut res = OMatrix::new_uninitialized_generic(nrows, ncols);
unsafe { crate::unimplemented_or_uninitialized_generic!(nrows, ncols) };
for j in 0..ncols.value() { for j in 0..ncols.value() {
for i in 0..nrows.value() { for i in 0..nrows.value() {
unsafe { unsafe {
let a = self.data.get_unchecked(i, j).clone(); let a = self.data.get_unchecked(i, j).clone();
*res.data.get_unchecked_mut(i, j) = f(a) *res.data.get_unchecked_mut(i, j) = MaybeUninit::new(f(a));
} }
} }
} }
res // Safety: all entries have been initialized.
unsafe { res.assume_init() }
} }
/// Cast the components of `self` to another type. /// Cast the components of `self` to another type.
@ -821,8 +823,7 @@ impl<T, R: Dim, C: Dim, S: Storage<T, R, C>> Matrix<T, R, C, S> {
{ {
let (nrows, ncols) = self.data.shape(); let (nrows, ncols) = self.data.shape();
let mut res: OMatrix<N3, R, C> = let mut res = OMatrix::<N3, R, C>::new_uninitialized_generic(nrows, ncols);
unsafe { crate::unimplemented_or_uninitialized_generic!(nrows, ncols) };
assert_eq!( assert_eq!(
(nrows.value(), ncols.value()), (nrows.value(), ncols.value()),
@ -835,12 +836,13 @@ impl<T, R: Dim, C: Dim, S: Storage<T, R, C>> Matrix<T, R, C, S> {
unsafe { unsafe {
let a = self.data.get_unchecked(i, j).clone(); let a = self.data.get_unchecked(i, j).clone();
let b = rhs.data.get_unchecked(i, j).clone(); let b = rhs.data.get_unchecked(i, j).clone();
*res.data.get_unchecked_mut(i, j) = f(a, b) *res.data.get_unchecked_mut(i, j) = MaybeUninit::new(f(a, b));
} }
} }
} }
res // Safety: all entries have been initialized.
unsafe { res.assume_init() }
} }
/// Returns a matrix containing the result of `f` applied to each entries of `self` and /// Returns a matrix containing the result of `f` applied to each entries of `self` and
@ -862,8 +864,7 @@ impl<T, R: Dim, C: Dim, S: Storage<T, R, C>> Matrix<T, R, C, S> {
{ {
let (nrows, ncols) = self.data.shape(); let (nrows, ncols) = self.data.shape();
let mut res: OMatrix<N4, R, C> = let mut res = OMatrix::new_uninitialized_generic(nrows, ncols);
unsafe { crate::unimplemented_or_uninitialized_generic!(nrows, ncols) };
assert_eq!( assert_eq!(
(nrows.value(), ncols.value()), (nrows.value(), ncols.value()),
@ -882,12 +883,13 @@ impl<T, R: Dim, C: Dim, S: Storage<T, R, C>> Matrix<T, R, C, S> {
let a = self.data.get_unchecked(i, j).clone(); let a = self.data.get_unchecked(i, j).clone();
let b = b.data.get_unchecked(i, j).clone(); let b = b.data.get_unchecked(i, j).clone();
let c = c.data.get_unchecked(i, j).clone(); let c = c.data.get_unchecked(i, j).clone();
*res.data.get_unchecked_mut(i, j) = f(a, b, c) *res.data.get_unchecked_mut(i, j) = MaybeUninit::new(f(a, b, c));
} }
} }
} }
res // Safety: all entries have been initialized.
unsafe { res.assume_init() }
} }
/// Folds a function `f` on each entry of `self`. /// Folds a function `f` on each entry of `self`.
@ -1322,7 +1324,7 @@ impl<T, D: Dim, S: StorageMut<T, D, D>> Matrix<T, D, D, S> {
impl<T: SimdComplexField, R: Dim, C: Dim, S: Storage<T, R, C>> Matrix<T, R, C, S> { impl<T: SimdComplexField, R: Dim, C: Dim, S: Storage<T, R, C>> Matrix<T, R, C, S> {
/// Takes the adjoint (aka. conjugate-transpose) of `self` and store the result into `out`. /// Takes the adjoint (aka. conjugate-transpose) of `self` and store the result into `out`.
#[inline] #[inline]
pub fn adjoint_to<R2, C2, SB>(&self, out: &mut Matrix<T, R2, C2, SB>) pub fn adjoint_to<R2, C2, SB>(&self, out: &mut Matrix<MaybeUninit<T>, R2, C2, SB>)
where where
R2: Dim, R2: Dim,
C2: Dim, C2: Dim,
@ -1339,7 +1341,8 @@ impl<T: SimdComplexField, R: Dim, C: Dim, S: Storage<T, R, C>> Matrix<T, R, C, S
for i in 0..nrows { for i in 0..nrows {
for j in 0..ncols { for j in 0..ncols {
unsafe { unsafe {
*out.get_unchecked_mut((j, i)) = self.get_unchecked((i, j)).simd_conjugate(); *out.get_unchecked_mut((j, i)) =
MaybeUninit::new(self.get_unchecked((i, j)).simd_conjugate());
} }
} }
} }
@ -1355,8 +1358,7 @@ impl<T: SimdComplexField, R: Dim, C: Dim, S: Storage<T, R, C>> Matrix<T, R, C, S
let (nrows, ncols) = self.data.shape(); let (nrows, ncols) = self.data.shape();
unsafe { unsafe {
let mut res: OMatrix<_, C, R> = let mut res = OMatrix::new_uninitialized_generic(ncols, nrows);
crate::unimplemented_or_uninitialized_generic!(ncols, nrows);
self.adjoint_to(&mut res); self.adjoint_to(&mut res);
res res
@ -1480,7 +1482,7 @@ impl<T, D: Dim, S: Storage<T, D, D>> SquareMatrix<T, D, S> {
pub fn diagonal(&self) -> OVector<T, D> pub fn diagonal(&self) -> OVector<T, D>
where where
T: Clone, T: Clone,
DefaultAllocator: Allocator<T, D> + Allocator<MaybeUninit<T>, D>, DefaultAllocator: Allocator<T, D>,
{ {
self.map_diagonal(|e| e) self.map_diagonal(|e| e)
} }
@ -1493,7 +1495,7 @@ impl<T, D: Dim, S: Storage<T, D, D>> SquareMatrix<T, D, S> {
pub fn map_diagonal<T2: Clone>(&self, mut f: impl FnMut(T) -> T2) -> OVector<T2, D> pub fn map_diagonal<T2: Clone>(&self, mut f: impl FnMut(T) -> T2) -> OVector<T2, D>
where where
T: Clone, T: Clone,
DefaultAllocator: Allocator<T2, D> + Allocator<MaybeUninit<T2>, D>, DefaultAllocator: Allocator<T2, D>,
{ {
assert!( assert!(
self.is_square(), self.is_square(),

View File

@ -297,10 +297,10 @@ where
/// Computes the complex eigenvalues of the decomposed matrix. /// Computes the complex eigenvalues of the decomposed matrix.
fn do_complex_eigenvalues( fn do_complex_eigenvalues(
t: &OMatrix<T, D, D>, t: &OMatrix<T, D, D>,
out: &mut OVector<MaybeUninit<NumComplex<T>>, D>, out: &mut OVector<NumComplex<T>, D>,
) where ) where
T: RealField, T: RealField,
DefaultAllocator: Allocator<MaybeUninit<NumComplex<T>>, D>, DefaultAllocator: Allocator<NumComplex<T>, D>,
{ {
let dim = t.nrows(); let dim = t.nrows();
let mut m = 0; let mut m = 0;

View File

@ -263,6 +263,8 @@ where
/// `nvals` possible non-zero values. /// `nvals` possible non-zero values.
pub fn new_uninitialized_generic(nrows: R, ncols: C, nvals: usize) -> Self { pub fn new_uninitialized_generic(nrows: R, ncols: C, nvals: usize) -> Self {
let mut i = Vec::with_capacity(nvals); let mut i = Vec::with_capacity(nvals);
//BEEP BEEP!!!! UNDEFINED BEHAVIOR ALERT!!! BEEP BEEEP!!!
unsafe { unsafe {
i.set_len(nvals); i.set_len(nvals);
} }