Finally figured out some trait nitty-gritty
This commit is contained in:
parent
1a78b00476
commit
8d10e69e33
|
@ -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() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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};
|
||||||
|
|
|
@ -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>;
|
||||||
|
|
||||||
|
|
|
@ -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()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -457,8 +458,8 @@ 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),*)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
self.transpose_to(&mut res);
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut res = crate::unimplemented_or_uninitialized_generic!(ncols, nrows);
|
// Safety: res is now fully initialized due to the guarantees of transpose_to.
|
||||||
self.transpose_to(&mut res);
|
res.assume_init()
|
||||||
|
|
||||||
res
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # 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(),
|
||||||
|
@ -1648,7 +1650,7 @@ impl<T: Clone + Zero, D: DimAdd<U1>, S: Storage<T, D>> Vector<T, D, S> {
|
||||||
|
|
||||||
impl<T, R: Dim, C: Dim, S> AbsDiffEq for Matrix<T, R, C, S>
|
impl<T, R: Dim, C: Dim, S> AbsDiffEq for Matrix<T, R, C, S>
|
||||||
where
|
where
|
||||||
T: AbsDiffEq,
|
T: AbsDiffEq,
|
||||||
S: Storage<T, R, C>,
|
S: Storage<T, R, C>,
|
||||||
T::Epsilon: Copy,
|
T::Epsilon: Copy,
|
||||||
{
|
{
|
||||||
|
@ -1669,7 +1671,7 @@ where
|
||||||
|
|
||||||
impl<T, R: Dim, C: Dim, S> RelativeEq for Matrix<T, R, C, S>
|
impl<T, R: Dim, C: Dim, S> RelativeEq for Matrix<T, R, C, S>
|
||||||
where
|
where
|
||||||
T: RelativeEq,
|
T: RelativeEq,
|
||||||
S: Storage<T, R, C>,
|
S: Storage<T, R, C>,
|
||||||
T::Epsilon: Copy,
|
T::Epsilon: Copy,
|
||||||
{
|
{
|
||||||
|
@ -1691,7 +1693,7 @@ where
|
||||||
|
|
||||||
impl<T, R: Dim, C: Dim, S> UlpsEq for Matrix<T, R, C, S>
|
impl<T, R: Dim, C: Dim, S> UlpsEq for Matrix<T, R, C, S>
|
||||||
where
|
where
|
||||||
T: UlpsEq,
|
T: UlpsEq,
|
||||||
S: Storage<T, R, C>,
|
S: Storage<T, R, C>,
|
||||||
T::Epsilon: Copy,
|
T::Epsilon: Copy,
|
||||||
{
|
{
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue