Propagate `mem::MaybeUninit` through the return types of `Allocator::allocate_uninitialized` and `Matrix::new_uninitialized_generic`.
Most call sites still invoke UB through `assume_init`. Said call sites instead invoke `unimplemented!()` if the `no_unsound_assume_init` feature is enabled, to make it easier to gradually fix them. Progress towards #556.
This commit is contained in:
parent
adc82845d1
commit
36a3ac814f
|
@ -36,6 +36,7 @@ compare = [ "matrixcompare-core" ]
|
||||||
libm = [ "simba/libm" ]
|
libm = [ "simba/libm" ]
|
||||||
libm-force = [ "simba/libm_force" ]
|
libm-force = [ "simba/libm_force" ]
|
||||||
proptest-support = [ "proptest" ]
|
proptest-support = [ "proptest" ]
|
||||||
|
no_unsound_assume_init = [ ]
|
||||||
|
|
||||||
# This feature is only used for tests, and enables tests that require more time to run
|
# This feature is only used for tests, and enables tests that require more time to run
|
||||||
slow-tests = []
|
slow-tests = []
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
//! Abstract definition of a matrix data storage allocator.
|
//! Abstract definition of a matrix data storage allocator.
|
||||||
|
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
|
use std::mem;
|
||||||
|
|
||||||
use crate::base::constraint::{SameNumberOfColumns, SameNumberOfRows, ShapeConstraint};
|
use crate::base::constraint::{SameNumberOfColumns, SameNumberOfRows, ShapeConstraint};
|
||||||
use crate::base::dimension::{Dim, U1};
|
use crate::base::dimension::{Dim, U1};
|
||||||
|
@ -21,7 +22,7 @@ pub trait Allocator<N: Scalar, R: Dim, C: Dim = U1>: Any + Sized {
|
||||||
type Buffer: ContiguousStorageMut<N, R, C> + Clone;
|
type Buffer: ContiguousStorageMut<N, R, C> + Clone;
|
||||||
|
|
||||||
/// Allocates a buffer with the given number of rows and columns without initializing its content.
|
/// Allocates a buffer with the given number of rows and columns without initializing its content.
|
||||||
unsafe fn allocate_uninitialized(nrows: R, ncols: C) -> Self::Buffer;
|
unsafe fn allocate_uninitialized(nrows: R, ncols: C) -> mem::MaybeUninit<Self::Buffer>;
|
||||||
|
|
||||||
/// Allocates a buffer initialized with the content of the given iterator.
|
/// Allocates a buffer initialized with the content of the given iterator.
|
||||||
fn allocate_from_iterator<I: IntoIterator<Item = N>>(
|
fn allocate_from_iterator<I: IntoIterator<Item = N>>(
|
||||||
|
|
|
@ -1328,7 +1328,10 @@ where
|
||||||
ShapeConstraint: DimEq<D1, D1> + DimEq<D1, R3> + DimEq<C3, D4>,
|
ShapeConstraint: DimEq<D1, D1> + DimEq<D1, R3> + DimEq<C3, D4>,
|
||||||
DefaultAllocator: Allocator<N, D1>,
|
DefaultAllocator: Allocator<N, D1>,
|
||||||
{
|
{
|
||||||
let mut work = unsafe { Vector::new_uninitialized_generic(self.data.shape().0, U1) };
|
#[cfg(feature="no_unsound_assume_init")]
|
||||||
|
let mut work = Vector::zeros_generic(self.data.shape().0, U1);
|
||||||
|
#[cfg(not(feature="no_unsound_assume_init"))]
|
||||||
|
let mut work = unsafe { Vector::new_uninitialized_generic(self.data.shape().0, U1).assume_init() };
|
||||||
self.quadform_tr_with_workspace(&mut work, alpha, lhs, mid, beta)
|
self.quadform_tr_with_workspace(&mut work, alpha, lhs, mid, beta)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1421,7 +1424,10 @@ where
|
||||||
ShapeConstraint: DimEq<D2, R3> + DimEq<D1, C3> + AreMultipliable<C3, R3, D2, U1>,
|
ShapeConstraint: DimEq<D2, R3> + DimEq<D1, C3> + AreMultipliable<C3, R3, D2, U1>,
|
||||||
DefaultAllocator: Allocator<N, D2>,
|
DefaultAllocator: Allocator<N, D2>,
|
||||||
{
|
{
|
||||||
let mut work = unsafe { Vector::new_uninitialized_generic(mid.data.shape().0, U1) };
|
#[cfg(feature="no_unsound_assume_init")]
|
||||||
|
let mut work = Vector::zeros_generic(mid.data.shape().0, U1);
|
||||||
|
#[cfg(not(feature="no_unsound_assume_init"))]
|
||||||
|
let mut work = unsafe { Vector::new_uninitialized_generic(mid.data.shape().0, U1).assume_init() };
|
||||||
self.quadform_with_workspace(&mut work, alpha, mid, rhs, beta)
|
self.quadform_with_workspace(&mut work, alpha, mid, rhs, beta)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@ use rand::Rng;
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
use rand_distr::StandardNormal;
|
use rand_distr::StandardNormal;
|
||||||
use std::iter;
|
use std::iter;
|
||||||
|
use std::mem;
|
||||||
use typenum::{self, Cmp, Greater};
|
use typenum::{self, Cmp, Greater};
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
|
@ -25,6 +26,16 @@ use crate::base::dimension::{Dim, DimName, Dynamic, U1, U2, U3, U4, U5, U6};
|
||||||
use crate::base::storage::Storage;
|
use crate::base::storage::Storage;
|
||||||
use crate::base::{DefaultAllocator, Matrix, MatrixMN, MatrixN, Scalar, Unit, Vector, VectorN};
|
use crate::base::{DefaultAllocator, Matrix, MatrixMN, MatrixN, Scalar, Unit, Vector, VectorN};
|
||||||
|
|
||||||
|
/// When "no_unsound_assume_init" is enabled, expands to `zeros_generic()` instead of `new_uninitialized_generic().assume_init()`.
|
||||||
|
/// Intended for use in contexts where the `Scalar` type implements `num_traits::Zero`, to check whether uninitialized memory is actually performance-critical.
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! zero_or_uninitialized_generic {
|
||||||
|
($nrows:expr, $ncols:expr) => {{
|
||||||
|
#[cfg(feature="no_unsound_assume_init")] { crate::base::Matrix::zeros_generic($nrows, $ncols) }
|
||||||
|
#[cfg(not(feature="no_unsound_assume_init"))] { crate::base::Matrix::new_uninitialized_generic($nrows, $ncols).assume_init() }
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
|
||||||
/// # Generic constructors
|
/// # Generic constructors
|
||||||
/// This set of matrix and vector construction functions are all generic
|
/// This set of matrix and vector construction functions are all generic
|
||||||
/// with-regard to the matrix dimensions. They all expect to be given
|
/// with-regard to the matrix dimensions. They all expect to be given
|
||||||
|
@ -38,8 +49,8 @@ where
|
||||||
/// Creates a new uninitialized matrix. If the matrix has a compile-time dimension, this panics
|
/// Creates a new uninitialized matrix. If the matrix has a compile-time dimension, this panics
|
||||||
/// if `nrows != R::to_usize()` or `ncols != C::to_usize()`.
|
/// if `nrows != R::to_usize()` or `ncols != C::to_usize()`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub unsafe fn new_uninitialized_generic(nrows: R, ncols: C) -> Self {
|
pub unsafe fn new_uninitialized_generic(nrows: R, ncols: C) -> mem::MaybeUninit<Self> {
|
||||||
Self::from_data(DefaultAllocator::allocate_uninitialized(nrows, ncols))
|
Self::from_uninitialized_data(DefaultAllocator::allocate_uninitialized(nrows, ncols))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a matrix with all its elements set to `elem`.
|
/// Creates a matrix with all its elements set to `elem`.
|
||||||
|
@ -88,7 +99,10 @@ where
|
||||||
"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 { Self::new_uninitialized_generic(nrows, ncols) };
|
#[cfg(feature="no_unsound_assume_init")]
|
||||||
|
let mut res: Self = unimplemented!();
|
||||||
|
#[cfg(not(feature="no_unsound_assume_init"))]
|
||||||
|
let mut res = unsafe { Self::new_uninitialized_generic(nrows, ncols).assume_init() };
|
||||||
let mut iter = slice.iter();
|
let mut iter = slice.iter();
|
||||||
|
|
||||||
for i in 0..nrows.value() {
|
for i in 0..nrows.value() {
|
||||||
|
@ -114,7 +128,10 @@ where
|
||||||
where
|
where
|
||||||
F: FnMut(usize, usize) -> N,
|
F: FnMut(usize, usize) -> N,
|
||||||
{
|
{
|
||||||
let mut res = unsafe { Self::new_uninitialized_generic(nrows, ncols) };
|
#[cfg(feature="no_unsound_assume_init")]
|
||||||
|
let mut res: Self = unimplemented!();
|
||||||
|
#[cfg(not(feature="no_unsound_assume_init"))]
|
||||||
|
let mut res = unsafe { Self::new_uninitialized_generic(nrows, ncols).assume_init() };
|
||||||
|
|
||||||
for j in 0..ncols.value() {
|
for j in 0..ncols.value() {
|
||||||
for i in 0..nrows.value() {
|
for i in 0..nrows.value() {
|
||||||
|
@ -356,7 +373,7 @@ macro_rules! impl_constructors(
|
||||||
($($Dims: ty),*; $(=> $DimIdent: ident: $DimBound: ident),*; $($gargs: expr),*; $($args: ident),*) => {
|
($($Dims: ty),*; $(=> $DimIdent: ident: $DimBound: ident),*; $($gargs: expr),*; $($args: ident),*) => {
|
||||||
/// Creates a new uninitialized matrix or vector.
|
/// Creates a new uninitialized matrix or vector.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub unsafe fn new_uninitialized($($args: usize),*) -> Self {
|
pub unsafe fn new_uninitialized($($args: usize),*) -> mem::MaybeUninit<Self> {
|
||||||
Self::new_uninitialized_generic($($gargs),*)
|
Self::new_uninitialized_generic($($gargs),*)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -865,7 +882,10 @@ macro_rules! componentwise_constructors_impl(
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new($($args: N),*) -> Self {
|
pub fn new($($args: N),*) -> Self {
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut res = Self::new_uninitialized();
|
#[cfg(feature="no_unsound_assume_init")]
|
||||||
|
let mut res: Self = unimplemented!();
|
||||||
|
#[cfg(not(feature="no_unsound_assume_init"))]
|
||||||
|
let mut res = Self::new_uninitialized().assume_init();
|
||||||
$( *res.get_unchecked_mut(($irow, $icol)) = $args; )*
|
$( *res.get_unchecked_mut(($irow, $icol)) = $args; )*
|
||||||
|
|
||||||
res
|
res
|
||||||
|
|
|
@ -50,7 +50,10 @@ 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 = unsafe { MatrixMN::<N2, R2, C2>::new_uninitialized_generic(nrows2, ncols2) };
|
#[cfg(feature="no_unsound_assume_init")]
|
||||||
|
let mut res: MatrixMN<N2, R2, C2> = unimplemented!();
|
||||||
|
#[cfg(not(feature="no_unsound_assume_init"))]
|
||||||
|
let mut res = unsafe { MatrixMN::<N2, R2, C2>::new_uninitialized_generic(nrows2, ncols2).assume_init() };
|
||||||
for i in 0..nrows {
|
for i in 0..nrows {
|
||||||
for j in 0..ncols {
|
for j in 0..ncols {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -73,7 +76,10 @@ 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 = unsafe { Self::new_uninitialized_generic(nrows, ncols) };
|
#[cfg(feature="no_unsound_assume_init")]
|
||||||
|
let mut res: Self = unimplemented!();
|
||||||
|
#[cfg(not(feature="no_unsound_assume_init"))]
|
||||||
|
let mut res = unsafe { Self::new_uninitialized_generic(nrows, ncols).assume_init() };
|
||||||
for i in 0..nrows2 {
|
for i in 0..nrows2 {
|
||||||
for j in 0..ncols2 {
|
for j in 0..ncols2 {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -117,9 +123,9 @@ macro_rules! impl_from_into_asref_1D(
|
||||||
fn from(arr: [N; $SZ]) -> Self {
|
fn from(arr: [N; $SZ]) -> Self {
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut res = Self::new_uninitialized();
|
let mut res = Self::new_uninitialized();
|
||||||
ptr::copy_nonoverlapping(&arr[0], res.data.ptr_mut(), $SZ);
|
ptr::copy_nonoverlapping(&arr[0], (*res.as_mut_ptr()).data.ptr_mut(), $SZ);
|
||||||
|
|
||||||
res
|
res.assume_init()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -184,9 +190,9 @@ macro_rules! impl_from_into_asref_2D(
|
||||||
fn from(arr: [[N; $SZRows]; $SZCols]) -> Self {
|
fn from(arr: [[N; $SZRows]; $SZCols]) -> Self {
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut res = Self::new_uninitialized();
|
let mut res = Self::new_uninitialized();
|
||||||
ptr::copy_nonoverlapping(&arr[0][0], res.data.ptr_mut(), $SZRows * $SZCols);
|
ptr::copy_nonoverlapping(&arr[0][0], (*res.as_mut_ptr()).data.ptr_mut(), $SZRows * $SZCols);
|
||||||
|
|
||||||
res
|
res.assume_init()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -306,13 +312,13 @@ macro_rules! impl_from_into_mint_2D(
|
||||||
fn from(m: mint::$MV<N>) -> Self {
|
fn from(m: mint::$MV<N>) -> Self {
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut res = Self::new_uninitialized();
|
let mut res = Self::new_uninitialized();
|
||||||
let mut ptr = res.data.ptr_mut();
|
let mut ptr = (*res).data.ptr_mut();
|
||||||
$(
|
$(
|
||||||
ptr::copy_nonoverlapping(&m.$component.x, ptr, $SZRows);
|
ptr::copy_nonoverlapping(&m.$component.x, ptr, $SZRows);
|
||||||
ptr = ptr.offset($SZRows);
|
ptr = ptr.offset($SZRows);
|
||||||
)*
|
)*
|
||||||
let _ = ptr;
|
let _ = ptr;
|
||||||
res
|
res.assume_init()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,9 +45,8 @@ where
|
||||||
type Buffer = ArrayStorage<N, R, C>;
|
type Buffer = ArrayStorage<N, R, C>;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn allocate_uninitialized(_: R, _: C) -> Self::Buffer {
|
unsafe fn allocate_uninitialized(_: R, _: C) -> mem::MaybeUninit<Self::Buffer> {
|
||||||
// TODO: Undefined behavior, see #556
|
mem::MaybeUninit::<Self::Buffer>::uninit()
|
||||||
mem::MaybeUninit::<Self::Buffer>::uninit().assume_init()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -56,7 +55,10 @@ where
|
||||||
ncols: C,
|
ncols: C,
|
||||||
iter: I,
|
iter: I,
|
||||||
) -> Self::Buffer {
|
) -> Self::Buffer {
|
||||||
let mut res = unsafe { Self::allocate_uninitialized(nrows, ncols) };
|
#[cfg(feature="no_unsound_assume_init")]
|
||||||
|
let mut res: Self::Buffer = unimplemented!();
|
||||||
|
#[cfg(not(feature="no_unsound_assume_init"))]
|
||||||
|
let mut res = unsafe { Self::allocate_uninitialized(nrows, ncols).assume_init() };
|
||||||
let mut count = 0;
|
let mut count = 0;
|
||||||
|
|
||||||
for (res, e) in res.iter_mut().zip(iter.into_iter()) {
|
for (res, e) in res.iter_mut().zip(iter.into_iter()) {
|
||||||
|
@ -80,13 +82,13 @@ impl<N: Scalar, C: Dim> Allocator<N, Dynamic, C> for DefaultAllocator {
|
||||||
type Buffer = VecStorage<N, Dynamic, C>;
|
type Buffer = VecStorage<N, Dynamic, C>;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn allocate_uninitialized(nrows: Dynamic, ncols: C) -> Self::Buffer {
|
unsafe fn allocate_uninitialized(nrows: Dynamic, ncols: C) -> mem::MaybeUninit<Self::Buffer> {
|
||||||
let mut res = Vec::new();
|
let mut res = Vec::new();
|
||||||
let length = nrows.value() * ncols.value();
|
let length = nrows.value() * ncols.value();
|
||||||
res.reserve_exact(length);
|
res.reserve_exact(length);
|
||||||
res.set_len(length);
|
res.set_len(length);
|
||||||
|
|
||||||
VecStorage::new(nrows, ncols, res)
|
mem::MaybeUninit::new(VecStorage::new(nrows, ncols, res))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -110,13 +112,13 @@ impl<N: Scalar, R: DimName> Allocator<N, R, Dynamic> for DefaultAllocator {
|
||||||
type Buffer = VecStorage<N, R, Dynamic>;
|
type Buffer = VecStorage<N, R, Dynamic>;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn allocate_uninitialized(nrows: R, ncols: Dynamic) -> Self::Buffer {
|
unsafe fn allocate_uninitialized(nrows: R, ncols: Dynamic) -> mem::MaybeUninit<Self::Buffer> {
|
||||||
let mut res = Vec::new();
|
let mut res = Vec::new();
|
||||||
let length = nrows.value() * ncols.value();
|
let length = nrows.value() * ncols.value();
|
||||||
res.reserve_exact(length);
|
res.reserve_exact(length);
|
||||||
res.set_len(length);
|
res.set_len(length);
|
||||||
|
|
||||||
VecStorage::new(nrows, ncols, res)
|
mem::MaybeUninit::new(VecStorage::new(nrows, ncols, res))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -156,7 +158,10 @@ where
|
||||||
cto: CTo,
|
cto: CTo,
|
||||||
buf: <Self as Allocator<N, RFrom, CFrom>>::Buffer,
|
buf: <Self as Allocator<N, RFrom, CFrom>>::Buffer,
|
||||||
) -> ArrayStorage<N, RTo, CTo> {
|
) -> ArrayStorage<N, RTo, CTo> {
|
||||||
let mut res = <Self as Allocator<N, RTo, CTo>>::allocate_uninitialized(rto, cto);
|
#[cfg(feature="no_unsound_assume_init")]
|
||||||
|
let mut res: ArrayStorage<N, RTo, CTo> = unimplemented!();
|
||||||
|
#[cfg(not(feature="no_unsound_assume_init"))]
|
||||||
|
let mut res = <Self as Allocator<N, RTo, CTo>>::allocate_uninitialized(rto, cto).assume_init();
|
||||||
|
|
||||||
let (rfrom, cfrom) = buf.shape();
|
let (rfrom, cfrom) = buf.shape();
|
||||||
|
|
||||||
|
@ -184,7 +189,10 @@ where
|
||||||
cto: CTo,
|
cto: CTo,
|
||||||
buf: ArrayStorage<N, RFrom, CFrom>,
|
buf: ArrayStorage<N, RFrom, CFrom>,
|
||||||
) -> VecStorage<N, Dynamic, CTo> {
|
) -> VecStorage<N, Dynamic, CTo> {
|
||||||
let mut res = <Self as Allocator<N, Dynamic, CTo>>::allocate_uninitialized(rto, cto);
|
#[cfg(feature="no_unsound_assume_init")]
|
||||||
|
let mut res: VecStorage<N, Dynamic, CTo> = unimplemented!();
|
||||||
|
#[cfg(not(feature="no_unsound_assume_init"))]
|
||||||
|
let mut res = <Self as Allocator<N, Dynamic, CTo>>::allocate_uninitialized(rto, cto).assume_init();
|
||||||
|
|
||||||
let (rfrom, cfrom) = buf.shape();
|
let (rfrom, cfrom) = buf.shape();
|
||||||
|
|
||||||
|
@ -212,7 +220,10 @@ where
|
||||||
cto: Dynamic,
|
cto: Dynamic,
|
||||||
buf: ArrayStorage<N, RFrom, CFrom>,
|
buf: ArrayStorage<N, RFrom, CFrom>,
|
||||||
) -> VecStorage<N, RTo, Dynamic> {
|
) -> VecStorage<N, RTo, Dynamic> {
|
||||||
let mut res = <Self as Allocator<N, RTo, Dynamic>>::allocate_uninitialized(rto, cto);
|
#[cfg(feature="no_unsound_assume_init")]
|
||||||
|
let mut res: VecStorage<N, RTo, Dynamic> = unimplemented!();
|
||||||
|
#[cfg(not(feature="no_unsound_assume_init"))]
|
||||||
|
let mut res = <Self as Allocator<N, RTo, Dynamic>>::allocate_uninitialized(rto, cto).assume_init();
|
||||||
|
|
||||||
let (rfrom, cfrom) = buf.shape();
|
let (rfrom, cfrom) = buf.shape();
|
||||||
|
|
||||||
|
|
|
@ -54,8 +54,7 @@ impl<N: Scalar + Zero, R: Dim, C: Dim, S: Storage<N, R, C>> Matrix<N, R, C, S> {
|
||||||
{
|
{
|
||||||
let irows = irows.into_iter();
|
let irows = irows.into_iter();
|
||||||
let ncols = self.data.shape().1;
|
let ncols = self.data.shape().1;
|
||||||
let mut res =
|
let mut res = unsafe { crate::zero_or_uninitialized_generic!(Dynamic::new(irows.len()), ncols) };
|
||||||
unsafe { MatrixMN::new_uninitialized_generic(Dynamic::new(irows.len()), ncols) };
|
|
||||||
|
|
||||||
// First, check that all the indices from irows are valid.
|
// First, check that all the indices from irows are valid.
|
||||||
// This will allow us to use unchecked access in the inner loop.
|
// This will allow us to use unchecked access in the inner loop.
|
||||||
|
@ -90,7 +89,7 @@ impl<N: Scalar + Zero, R: Dim, C: Dim, S: Storage<N, R, C>> Matrix<N, R, C, S> {
|
||||||
let icols = icols.into_iter();
|
let icols = icols.into_iter();
|
||||||
let nrows = self.data.shape().0;
|
let nrows = self.data.shape().0;
|
||||||
let mut res =
|
let mut res =
|
||||||
unsafe { MatrixMN::new_uninitialized_generic(nrows, Dynamic::new(icols.len())) };
|
unsafe { crate::zero_or_uninitialized_generic!(nrows, Dynamic::new(icols.len())) };
|
||||||
|
|
||||||
for (destination, source) in icols.enumerate() {
|
for (destination, source) in icols.enumerate() {
|
||||||
res.column_mut(destination).copy_from(&self.column(*source))
|
res.column_mut(destination).copy_from(&self.column(*source))
|
||||||
|
@ -896,7 +895,10 @@ impl<N: Scalar> DMatrix<N> {
|
||||||
where
|
where
|
||||||
DefaultAllocator: Reallocator<N, Dynamic, Dynamic, Dynamic, Dynamic>,
|
DefaultAllocator: Reallocator<N, Dynamic, Dynamic, Dynamic, Dynamic>,
|
||||||
{
|
{
|
||||||
let placeholder = unsafe { Self::new_uninitialized(0, 0) };
|
#[cfg(feature="no_unsound_assume_init")]
|
||||||
|
let placeholder = unimplemented!();
|
||||||
|
#[cfg(not(feature="no_unsound_assume_init"))]
|
||||||
|
let placeholder = unsafe { Self::new_uninitialized(0, 0).assume_init() };
|
||||||
let old = mem::replace(self, placeholder);
|
let old = mem::replace(self, placeholder);
|
||||||
let new = old.resize(new_nrows, new_ncols, val);
|
let new = old.resize(new_nrows, new_ncols, val);
|
||||||
let _ = mem::replace(self, new);
|
let _ = mem::replace(self, new);
|
||||||
|
@ -919,8 +921,10 @@ where
|
||||||
where
|
where
|
||||||
DefaultAllocator: Reallocator<N, Dynamic, C, Dynamic, C>,
|
DefaultAllocator: Reallocator<N, Dynamic, C, Dynamic, C>,
|
||||||
{
|
{
|
||||||
let placeholder =
|
#[cfg(feature="no_unsound_assume_init")]
|
||||||
unsafe { Self::new_uninitialized_generic(Dynamic::new(0), self.data.shape().1) };
|
let placeholder = unimplemented!();
|
||||||
|
#[cfg(not(feature="no_unsound_assume_init"))]
|
||||||
|
let placeholder = unsafe { Self::new_uninitialized_generic(Dynamic::new(0), self.data.shape().1).assume_init() };
|
||||||
let old = mem::replace(self, placeholder);
|
let old = mem::replace(self, placeholder);
|
||||||
let new = old.resize_vertically(new_nrows, val);
|
let new = old.resize_vertically(new_nrows, val);
|
||||||
let _ = mem::replace(self, new);
|
let _ = mem::replace(self, new);
|
||||||
|
@ -943,8 +947,10 @@ where
|
||||||
where
|
where
|
||||||
DefaultAllocator: Reallocator<N, R, Dynamic, R, Dynamic>,
|
DefaultAllocator: Reallocator<N, R, Dynamic, R, Dynamic>,
|
||||||
{
|
{
|
||||||
let placeholder =
|
#[cfg(feature="no_unsound_assume_init")]
|
||||||
unsafe { Self::new_uninitialized_generic(self.data.shape().0, Dynamic::new(0)) };
|
let placeholder = unimplemented!();
|
||||||
|
#[cfg(not(feature="no_unsound_assume_init"))]
|
||||||
|
let placeholder = unsafe { Self::new_uninitialized_generic(self.data.shape().0, Dynamic::new(0)).assume_init() };
|
||||||
let old = mem::replace(self, placeholder);
|
let old = mem::replace(self, placeholder);
|
||||||
let new = old.resize_horizontally(new_ncols, val);
|
let new = old.resize_horizontally(new_ncols, val);
|
||||||
let _ = mem::replace(self, new);
|
let _ = mem::replace(self, new);
|
||||||
|
|
|
@ -298,6 +298,17 @@ impl<N: Scalar, R: Dim, C: Dim, S: Storage<N, R, C>> Matrix<N, R, C, S> {
|
||||||
unsafe { Self::from_data_statically_unchecked(data) }
|
unsafe { Self::from_data_statically_unchecked(data) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Creates a new uninitialized matrix with the given uninitialized data
|
||||||
|
pub unsafe fn from_uninitialized_data(data: mem::MaybeUninit<S>) -> mem::MaybeUninit<Self> {
|
||||||
|
let res: Matrix<N, R, C, mem::MaybeUninit<S>> = Matrix { data, _phantoms: PhantomData };
|
||||||
|
let res: mem::MaybeUninit<Matrix<N, R, C, mem::MaybeUninit<S>>> = mem::MaybeUninit::new(res);
|
||||||
|
// safety: since we wrap the inner MaybeUninit in an outer MaybeUninit above, the fact that the `data` field is partially-uninitialized is still opaque.
|
||||||
|
// with s/transmute_copy/transmute/, rustc claims that `MaybeUninit<Matrix<N, R, C, MaybeUninit<S>>>` may be of a different size from `MaybeUninit<Matrix<N, R, C, S>>`
|
||||||
|
// but MaybeUninit's documentation says "MaybeUninit<T> is guaranteed to have the same size, alignment, and ABI as T", which implies those types should be the same size
|
||||||
|
let res: mem::MaybeUninit<Matrix<N, R, C, S>> = mem::transmute_copy(&res);
|
||||||
|
res
|
||||||
|
}
|
||||||
|
|
||||||
/// The shape of this matrix returned as the tuple (number of rows, number of columns).
|
/// The shape of this matrix returned as the tuple (number of rows, number of columns).
|
||||||
///
|
///
|
||||||
/// # Examples:
|
/// # Examples:
|
||||||
|
@ -496,8 +507,10 @@ impl<N: Scalar, R: Dim, C: Dim, S: Storage<N, R, C>> Matrix<N, 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<N, R, C, R2, C2> =
|
#[cfg(feature="no_unsound_assume_init")]
|
||||||
unsafe { Matrix::new_uninitialized_generic(nrows, ncols) };
|
let mut res: MatrixSum<N, R, C, R2, C2> = unimplemented!();
|
||||||
|
#[cfg(not(feature="no_unsound_assume_init"))]
|
||||||
|
let mut res: MatrixSum<N, R, C, R2, C2> = unsafe { Matrix::new_uninitialized_generic(nrows, ncols).assume_init() };
|
||||||
|
|
||||||
// TODO: use copy_from
|
// TODO: use copy_from
|
||||||
for j in 0..res.ncols() {
|
for j in 0..res.ncols() {
|
||||||
|
@ -546,7 +559,10 @@ impl<N: Scalar, R: Dim, C: Dim, S: Storage<N, R, C>> Matrix<N, R, C, S> {
|
||||||
let (nrows, ncols) = self.data.shape();
|
let (nrows, ncols) = self.data.shape();
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut res = Matrix::new_uninitialized_generic(ncols, nrows);
|
#[cfg(feature="no_unsound_assume_init")]
|
||||||
|
let mut res = unimplemented!();
|
||||||
|
#[cfg(not(feature="no_unsound_assume_init"))]
|
||||||
|
let mut res = Matrix::new_uninitialized_generic(ncols, nrows).assume_init();
|
||||||
self.transpose_to(&mut res);
|
self.transpose_to(&mut res);
|
||||||
|
|
||||||
res
|
res
|
||||||
|
@ -564,7 +580,10 @@ impl<N: Scalar, R: Dim, C: Dim, S: Storage<N, R, C>> Matrix<N, R, C, S> {
|
||||||
{
|
{
|
||||||
let (nrows, ncols) = self.data.shape();
|
let (nrows, ncols) = self.data.shape();
|
||||||
|
|
||||||
let mut res = unsafe { MatrixMN::new_uninitialized_generic(nrows, ncols) };
|
#[cfg(feature="no_unsound_assume_init")]
|
||||||
|
let mut res: MatrixMN<N2, R, C> = unimplemented!();
|
||||||
|
#[cfg(not(feature="no_unsound_assume_init"))]
|
||||||
|
let mut res = unsafe { MatrixMN::new_uninitialized_generic(nrows, ncols).assume_init() };
|
||||||
|
|
||||||
for j in 0..ncols.value() {
|
for j in 0..ncols.value() {
|
||||||
for i in 0..nrows.value() {
|
for i in 0..nrows.value() {
|
||||||
|
@ -608,7 +627,10 @@ impl<N: Scalar, R: Dim, C: Dim, S: Storage<N, R, C>> Matrix<N, R, C, S> {
|
||||||
{
|
{
|
||||||
let (nrows, ncols) = self.data.shape();
|
let (nrows, ncols) = self.data.shape();
|
||||||
|
|
||||||
let mut res = unsafe { MatrixMN::new_uninitialized_generic(nrows, ncols) };
|
#[cfg(feature="no_unsound_assume_init")]
|
||||||
|
let mut res: MatrixMN<N2, R, C> = unimplemented!();
|
||||||
|
#[cfg(not(feature="no_unsound_assume_init"))]
|
||||||
|
let mut res = unsafe { MatrixMN::new_uninitialized_generic(nrows, ncols).assume_init() };
|
||||||
|
|
||||||
for j in 0..ncols.value() {
|
for j in 0..ncols.value() {
|
||||||
for i in 0..nrows.value() {
|
for i in 0..nrows.value() {
|
||||||
|
@ -635,7 +657,10 @@ impl<N: Scalar, R: Dim, C: Dim, S: Storage<N, R, C>> Matrix<N, R, C, S> {
|
||||||
{
|
{
|
||||||
let (nrows, ncols) = self.data.shape();
|
let (nrows, ncols) = self.data.shape();
|
||||||
|
|
||||||
let mut res = unsafe { MatrixMN::new_uninitialized_generic(nrows, ncols) };
|
#[cfg(feature="no_unsound_assume_init")]
|
||||||
|
let mut res: MatrixMN<N3, R, C> = unimplemented!();
|
||||||
|
#[cfg(not(feature="no_unsound_assume_init"))]
|
||||||
|
let mut res = unsafe { MatrixMN::new_uninitialized_generic(nrows, ncols).assume_init() };
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
(nrows.value(), ncols.value()),
|
(nrows.value(), ncols.value()),
|
||||||
|
@ -676,7 +701,10 @@ impl<N: Scalar, R: Dim, C: Dim, S: Storage<N, R, C>> Matrix<N, R, C, S> {
|
||||||
{
|
{
|
||||||
let (nrows, ncols) = self.data.shape();
|
let (nrows, ncols) = self.data.shape();
|
||||||
|
|
||||||
let mut res = unsafe { MatrixMN::new_uninitialized_generic(nrows, ncols) };
|
#[cfg(feature="no_unsound_assume_init")]
|
||||||
|
let mut res: MatrixMN<N4, R, C> = unimplemented!();
|
||||||
|
#[cfg(not(feature="no_unsound_assume_init"))]
|
||||||
|
let mut res = unsafe { MatrixMN::new_uninitialized_generic(nrows, ncols).assume_init() };
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
(nrows.value(), ncols.value()),
|
(nrows.value(), ncols.value()),
|
||||||
|
@ -1170,7 +1198,10 @@ impl<N: SimdComplexField, R: Dim, C: Dim, S: Storage<N, R, C>> Matrix<N, R, C, S
|
||||||
let (nrows, ncols) = self.data.shape();
|
let (nrows, ncols) = self.data.shape();
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut res: MatrixMN<_, C, R> = Matrix::new_uninitialized_generic(ncols, nrows);
|
#[cfg(feature="no_unsound_assume_init")]
|
||||||
|
let mut res = unimplemented!();
|
||||||
|
#[cfg(not(feature="no_unsound_assume_init"))]
|
||||||
|
let mut res: MatrixMN<_, C, R> = Matrix::new_uninitialized_generic(ncols, nrows).assume_init();
|
||||||
self.adjoint_to(&mut res);
|
self.adjoint_to(&mut res);
|
||||||
|
|
||||||
res
|
res
|
||||||
|
@ -1311,7 +1342,10 @@ impl<N: Scalar, D: Dim, S: Storage<N, D, D>> SquareMatrix<N, D, S> {
|
||||||
);
|
);
|
||||||
|
|
||||||
let dim = self.data.shape().0;
|
let dim = self.data.shape().0;
|
||||||
let mut res = unsafe { VectorN::new_uninitialized_generic(dim, U1) };
|
#[cfg(feature="no_unsound_assume_init")]
|
||||||
|
let mut res: VectorN<N2, D> = unimplemented!();
|
||||||
|
#[cfg(not(feature="no_unsound_assume_init"))]
|
||||||
|
let mut res = unsafe { VectorN::new_uninitialized_generic(dim, U1).assume_init() };
|
||||||
|
|
||||||
for i in 0..dim.value() {
|
for i in 0..dim.value() {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -1438,7 +1472,7 @@ impl<N: Scalar + Zero, D: DimAdd<U1>, S: Storage<N, D>> Vector<N, D, S> {
|
||||||
{
|
{
|
||||||
let len = self.len();
|
let len = self.len();
|
||||||
let hnrows = DimSum::<D, U1>::from_usize(len + 1);
|
let hnrows = DimSum::<D, U1>::from_usize(len + 1);
|
||||||
let mut res = unsafe { VectorN::<N, _>::new_uninitialized_generic(hnrows, U1) };
|
let mut res: VectorN::<N, _> = unsafe { crate::zero_or_uninitialized_generic!(hnrows, U1) };
|
||||||
res.generic_slice_mut((0, 0), self.data.shape())
|
res.generic_slice_mut((0, 0), self.data.shape())
|
||||||
.copy_from(self);
|
.copy_from(self);
|
||||||
res[(len, 0)] = element;
|
res[(len, 0)] = element;
|
||||||
|
@ -1783,7 +1817,10 @@ impl<N: Scalar + ClosedAdd + ClosedSub + ClosedMul, R: Dim, C: Dim, S: Storage<N
|
||||||
// TODO: soooo ugly!
|
// TODO: soooo ugly!
|
||||||
let nrows = SameShapeR::<R, R2>::from_usize(3);
|
let nrows = SameShapeR::<R, R2>::from_usize(3);
|
||||||
let ncols = SameShapeC::<C, C2>::from_usize(1);
|
let ncols = SameShapeC::<C, C2>::from_usize(1);
|
||||||
let mut res = Matrix::new_uninitialized_generic(nrows, ncols);
|
#[cfg(feature="no_unsound_assume_init")]
|
||||||
|
let mut res: MatrixCross<N, R, C, R2, C2> = unimplemented!();
|
||||||
|
#[cfg(not(feature="no_unsound_assume_init"))]
|
||||||
|
let mut res = Matrix::new_uninitialized_generic(nrows, ncols).assume_init();
|
||||||
|
|
||||||
let ax = self.get_unchecked((0, 0));
|
let ax = self.get_unchecked((0, 0));
|
||||||
let ay = self.get_unchecked((1, 0));
|
let ay = self.get_unchecked((1, 0));
|
||||||
|
@ -1807,7 +1844,10 @@ impl<N: Scalar + ClosedAdd + ClosedSub + ClosedMul, R: Dim, C: Dim, S: Storage<N
|
||||||
// TODO: ugly!
|
// TODO: ugly!
|
||||||
let nrows = SameShapeR::<R, R2>::from_usize(1);
|
let nrows = SameShapeR::<R, R2>::from_usize(1);
|
||||||
let ncols = SameShapeC::<C, C2>::from_usize(3);
|
let ncols = SameShapeC::<C, C2>::from_usize(3);
|
||||||
let mut res = Matrix::new_uninitialized_generic(nrows, ncols);
|
#[cfg(feature="no_unsound_assume_init")]
|
||||||
|
let mut res: MatrixCross<N, R, C, R2, C2> = unimplemented!();
|
||||||
|
#[cfg(not(feature="no_unsound_assume_init"))]
|
||||||
|
let mut res = Matrix::new_uninitialized_generic(nrows, ncols).assume_init();
|
||||||
|
|
||||||
let ax = self.get_unchecked((0, 0));
|
let ax = self.get_unchecked((0, 0));
|
||||||
let ay = self.get_unchecked((0, 1));
|
let ay = self.get_unchecked((0, 1));
|
||||||
|
|
|
@ -15,7 +15,7 @@ mod alias_slice;
|
||||||
mod array_storage;
|
mod array_storage;
|
||||||
mod cg;
|
mod cg;
|
||||||
mod componentwise;
|
mod componentwise;
|
||||||
mod construction;
|
#[macro_use] mod construction;
|
||||||
mod construction_slice;
|
mod construction_slice;
|
||||||
mod conversion;
|
mod conversion;
|
||||||
mod edition;
|
mod edition;
|
||||||
|
|
|
@ -331,7 +331,10 @@ macro_rules! componentwise_binop_impl(
|
||||||
let (nrows, ncols) = self.shape();
|
let (nrows, ncols) = self.shape();
|
||||||
let nrows: SameShapeR<R1, R2> = Dim::from_usize(nrows);
|
let nrows: SameShapeR<R1, R2> = Dim::from_usize(nrows);
|
||||||
let ncols: SameShapeC<C1, C2> = Dim::from_usize(ncols);
|
let ncols: SameShapeC<C1, C2> = Dim::from_usize(ncols);
|
||||||
Matrix::new_uninitialized_generic(nrows, ncols)
|
#[cfg(feature="no_unsound_assume_init")]
|
||||||
|
{ unimplemented!() }
|
||||||
|
#[cfg(not(feature="no_unsound_assume_init"))]
|
||||||
|
{ Matrix::new_uninitialized_generic(nrows, ncols).assume_init() }
|
||||||
};
|
};
|
||||||
|
|
||||||
self.$method_to_statically_unchecked(rhs, &mut res);
|
self.$method_to_statically_unchecked(rhs, &mut res);
|
||||||
|
@ -573,9 +576,7 @@ where
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn mul(self, rhs: &'b Matrix<N, R2, C2, SB>) -> Self::Output {
|
fn mul(self, rhs: &'b Matrix<N, R2, C2, SB>) -> Self::Output {
|
||||||
let mut res =
|
let mut res = unsafe { crate::zero_or_uninitialized_generic!(self.data.shape().0, rhs.data.shape().1) };
|
||||||
unsafe { Matrix::new_uninitialized_generic(self.data.shape().0, rhs.data.shape().1) };
|
|
||||||
|
|
||||||
self.mul_to(rhs, &mut res);
|
self.mul_to(rhs, &mut res);
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
@ -684,8 +685,7 @@ where
|
||||||
DefaultAllocator: Allocator<N, C1, C2>,
|
DefaultAllocator: Allocator<N, C1, C2>,
|
||||||
ShapeConstraint: SameNumberOfRows<R1, R2>,
|
ShapeConstraint: SameNumberOfRows<R1, R2>,
|
||||||
{
|
{
|
||||||
let mut res =
|
let mut res = unsafe { crate::zero_or_uninitialized_generic!(self.data.shape().1, rhs.data.shape().1) };
|
||||||
unsafe { Matrix::new_uninitialized_generic(self.data.shape().1, rhs.data.shape().1) };
|
|
||||||
|
|
||||||
self.tr_mul_to(rhs, &mut res);
|
self.tr_mul_to(rhs, &mut res);
|
||||||
res
|
res
|
||||||
|
@ -700,8 +700,7 @@ where
|
||||||
DefaultAllocator: Allocator<N, C1, C2>,
|
DefaultAllocator: Allocator<N, C1, C2>,
|
||||||
ShapeConstraint: SameNumberOfRows<R1, R2>,
|
ShapeConstraint: SameNumberOfRows<R1, R2>,
|
||||||
{
|
{
|
||||||
let mut res =
|
let mut res = unsafe { crate::zero_or_uninitialized_generic!(self.data.shape().1, rhs.data.shape().1) };
|
||||||
unsafe { Matrix::new_uninitialized_generic(self.data.shape().1, rhs.data.shape().1) };
|
|
||||||
|
|
||||||
self.ad_mul_to(rhs, &mut res);
|
self.ad_mul_to(rhs, &mut res);
|
||||||
res
|
res
|
||||||
|
@ -815,8 +814,7 @@ where
|
||||||
let (nrows1, ncols1) = self.data.shape();
|
let (nrows1, ncols1) = self.data.shape();
|
||||||
let (nrows2, ncols2) = rhs.data.shape();
|
let (nrows2, ncols2) = rhs.data.shape();
|
||||||
|
|
||||||
let mut res =
|
let mut res = unsafe { crate::zero_or_uninitialized_generic!(nrows1.mul(nrows2), ncols1.mul(ncols2)) };
|
||||||
unsafe { Matrix::new_uninitialized_generic(nrows1.mul(nrows2), ncols1.mul(ncols2)) };
|
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut data_res = res.data.ptr_mut();
|
let mut data_res = res.data.ptr_mut();
|
||||||
|
|
|
@ -17,7 +17,10 @@ impl<N: Scalar, R: Dim, C: Dim, S: Storage<N, R, C>> Matrix<N, R, C, S> {
|
||||||
DefaultAllocator: Allocator<N, U1, C>,
|
DefaultAllocator: Allocator<N, U1, C>,
|
||||||
{
|
{
|
||||||
let ncols = self.data.shape().1;
|
let ncols = self.data.shape().1;
|
||||||
let mut res = unsafe { RowVectorN::new_uninitialized_generic(U1, ncols) };
|
#[cfg(feature="no_unsound_assume_init")]
|
||||||
|
let mut res: RowVectorN<N, C> = unimplemented!();
|
||||||
|
#[cfg(not(feature="no_unsound_assume_init"))]
|
||||||
|
let mut res = unsafe { RowVectorN::new_uninitialized_generic(U1, ncols).assume_init() };
|
||||||
|
|
||||||
for i in 0..ncols.value() {
|
for i in 0..ncols.value() {
|
||||||
// TODO: avoid bound checking of column.
|
// TODO: avoid bound checking of column.
|
||||||
|
@ -42,7 +45,10 @@ impl<N: Scalar, R: Dim, C: Dim, S: Storage<N, R, C>> Matrix<N, R, C, S> {
|
||||||
DefaultAllocator: Allocator<N, C>,
|
DefaultAllocator: Allocator<N, C>,
|
||||||
{
|
{
|
||||||
let ncols = self.data.shape().1;
|
let ncols = self.data.shape().1;
|
||||||
let mut res = unsafe { VectorN::new_uninitialized_generic(ncols, U1) };
|
#[cfg(feature="no_unsound_assume_init")]
|
||||||
|
let mut res: VectorN<N, C> = unimplemented!();
|
||||||
|
#[cfg(not(feature="no_unsound_assume_init"))]
|
||||||
|
let mut res = unsafe { VectorN::new_uninitialized_generic(ncols, U1).assume_init() };
|
||||||
|
|
||||||
for i in 0..ncols.value() {
|
for i in 0..ncols.value() {
|
||||||
// TODO: avoid bound checking of column.
|
// TODO: avoid bound checking of column.
|
||||||
|
|
|
@ -181,7 +181,10 @@ where
|
||||||
D: DimNameAdd<U1>,
|
D: DimNameAdd<U1>,
|
||||||
DefaultAllocator: Allocator<N, DimNameSum<D, U1>>,
|
DefaultAllocator: Allocator<N, DimNameSum<D, U1>>,
|
||||||
{
|
{
|
||||||
let mut res = unsafe { VectorN::<_, DimNameSum<D, U1>>::new_uninitialized() };
|
#[cfg(feature="no_unsound_assume_init")]
|
||||||
|
let mut res: VectorN<N, DimNameSum<D, U1>> = unimplemented!();
|
||||||
|
#[cfg(not(feature="no_unsound_assume_init"))]
|
||||||
|
let mut res = unsafe { VectorN::<_, DimNameSum<D, U1>>::new_uninitialized().assume_init() };
|
||||||
res.fixed_slice_mut::<D, U1>(0, 0).copy_from(&self.coords);
|
res.fixed_slice_mut::<D, U1>(0, 0).copy_from(&self.coords);
|
||||||
res[(D::dim(), 0)] = N::one();
|
res[(D::dim(), 0)] = N::one();
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,10 @@ where
|
||||||
/// Creates a new point with uninitialized coordinates.
|
/// Creates a new point with uninitialized coordinates.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub unsafe fn new_uninitialized() -> Self {
|
pub unsafe fn new_uninitialized() -> Self {
|
||||||
Self::from(VectorN::new_uninitialized())
|
#[cfg(feature="no_unsound_assume_init")]
|
||||||
|
{ unimplemented!() }
|
||||||
|
#[cfg(not(feature="no_unsound_assume_init"))]
|
||||||
|
{ Self::from(VectorN::new_uninitialized().assume_init()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a new point with all coordinates equal to zero.
|
/// Creates a new point with all coordinates equal to zero.
|
||||||
|
|
|
@ -87,6 +87,7 @@ an optimized set of tools for computer graphics and physics. Those features incl
|
||||||
)]
|
)]
|
||||||
#![cfg_attr(not(feature = "std"), no_std)]
|
#![cfg_attr(not(feature = "std"), no_std)]
|
||||||
#![cfg_attr(all(feature = "alloc", not(feature = "std")), feature(alloc))]
|
#![cfg_attr(all(feature = "alloc", not(feature = "std")), feature(alloc))]
|
||||||
|
#![cfg_attr(feature = "no_unsound_assume_init", allow(unreachable_code))]
|
||||||
|
|
||||||
#[cfg(feature = "arbitrary")]
|
#[cfg(feature = "arbitrary")]
|
||||||
extern crate quickcheck;
|
extern crate quickcheck;
|
||||||
|
|
|
@ -81,11 +81,11 @@ where
|
||||||
"Cannot compute the bidiagonalization of an empty matrix."
|
"Cannot compute the bidiagonalization of an empty matrix."
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut diagonal = unsafe { MatrixMN::new_uninitialized_generic(min_nrows_ncols, U1) };
|
let mut diagonal = unsafe { crate::zero_or_uninitialized_generic!(min_nrows_ncols, U1) };
|
||||||
let mut off_diagonal =
|
let mut off_diagonal =
|
||||||
unsafe { MatrixMN::new_uninitialized_generic(min_nrows_ncols.sub(U1), U1) };
|
unsafe { crate::zero_or_uninitialized_generic!(min_nrows_ncols.sub(U1), U1) };
|
||||||
let mut axis_packed = unsafe { MatrixMN::new_uninitialized_generic(ncols, U1) };
|
let mut axis_packed = unsafe { crate::zero_or_uninitialized_generic!(ncols, U1) };
|
||||||
let mut work = unsafe { MatrixMN::new_uninitialized_generic(nrows, U1) };
|
let mut work = unsafe { crate::zero_or_uninitialized_generic!(nrows, U1) };
|
||||||
|
|
||||||
let upper_diagonal = nrows.value() >= ncols.value();
|
let upper_diagonal = nrows.value() >= ncols.value();
|
||||||
if upper_diagonal {
|
if upper_diagonal {
|
||||||
|
@ -239,8 +239,8 @@ where
|
||||||
let min_nrows_ncols = nrows.min(ncols);
|
let min_nrows_ncols = nrows.min(ncols);
|
||||||
|
|
||||||
let mut res = Matrix::identity_generic(min_nrows_ncols, ncols);
|
let mut res = Matrix::identity_generic(min_nrows_ncols, ncols);
|
||||||
let mut work = unsafe { MatrixMN::new_uninitialized_generic(min_nrows_ncols, U1) };
|
let mut work = unsafe { crate::zero_or_uninitialized_generic!(min_nrows_ncols, U1) };
|
||||||
let mut axis_packed = unsafe { MatrixMN::new_uninitialized_generic(ncols, U1) };
|
let mut axis_packed = unsafe { crate::zero_or_uninitialized_generic!(ncols, U1) };
|
||||||
|
|
||||||
let shift = self.axis_shift().1;
|
let shift = self.axis_shift().1;
|
||||||
|
|
||||||
|
|
|
@ -223,9 +223,9 @@ where
|
||||||
|
|
||||||
// loads the data into a new matrix with an additional jth row/column
|
// loads the data into a new matrix with an additional jth row/column
|
||||||
let mut chol = unsafe {
|
let mut chol = unsafe {
|
||||||
Matrix::new_uninitialized_generic(
|
crate::zero_or_uninitialized_generic!(
|
||||||
self.chol.data.shape().0.add(U1),
|
self.chol.data.shape().0.add(U1),
|
||||||
self.chol.data.shape().1.add(U1),
|
self.chol.data.shape().1.add(U1)
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
chol.slice_range_mut(..j, ..j)
|
chol.slice_range_mut(..j, ..j)
|
||||||
|
@ -288,9 +288,9 @@ where
|
||||||
|
|
||||||
// loads the data into a new matrix except for the jth row/column
|
// loads the data into a new matrix except for the jth row/column
|
||||||
let mut chol = unsafe {
|
let mut chol = unsafe {
|
||||||
Matrix::new_uninitialized_generic(
|
crate::zero_or_uninitialized_generic!(
|
||||||
self.chol.data.shape().0.sub(U1),
|
self.chol.data.shape().0.sub(U1),
|
||||||
self.chol.data.shape().1.sub(U1),
|
self.chol.data.shape().1.sub(U1)
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
chol.slice_range_mut(..j, ..j)
|
chol.slice_range_mut(..j, ..j)
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::allocator::Allocator;
|
use crate::allocator::Allocator;
|
||||||
use crate::base::{DefaultAllocator, MatrixMN, MatrixN, VectorN};
|
use crate::base::{DefaultAllocator, MatrixN, VectorN};
|
||||||
use crate::dimension::{DimDiff, DimSub, U1};
|
use crate::dimension::{DimDiff, DimSub, U1};
|
||||||
use crate::storage::Storage;
|
use crate::storage::Storage;
|
||||||
use simba::scalar::ComplexField;
|
use simba::scalar::ComplexField;
|
||||||
|
@ -48,7 +48,7 @@ where
|
||||||
{
|
{
|
||||||
/// Computes the Hessenberg decomposition using householder reflections.
|
/// Computes the Hessenberg decomposition using householder reflections.
|
||||||
pub fn new(hess: MatrixN<N, D>) -> Self {
|
pub fn new(hess: MatrixN<N, D>) -> Self {
|
||||||
let mut work = unsafe { MatrixMN::new_uninitialized_generic(hess.data.shape().0, U1) };
|
let mut work = unsafe { crate::zero_or_uninitialized_generic!(hess.data.shape().0, U1) };
|
||||||
Self::new_with_workspace(hess, &mut work)
|
Self::new_with_workspace(hess, &mut work)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,7 +74,7 @@ where
|
||||||
"Hessenberg: invalid workspace size."
|
"Hessenberg: invalid workspace size."
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut subdiag = unsafe { MatrixMN::new_uninitialized_generic(dim.sub(U1), U1) };
|
let mut subdiag = unsafe { crate::zero_or_uninitialized_generic!(dim.sub(U1), U1) };
|
||||||
|
|
||||||
if dim.value() == 0 {
|
if dim.value() == 0 {
|
||||||
return Hessenberg { hess, subdiag };
|
return Hessenberg { hess, subdiag };
|
||||||
|
|
|
@ -70,9 +70,12 @@ where
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn identity_generic(dim: D) -> Self {
|
pub fn identity_generic(dim: D) -> Self {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
#[cfg(feature="no_unsound_assume_init")]
|
||||||
|
unimplemented!();
|
||||||
|
#[cfg(not(feature="no_unsound_assume_init"))]
|
||||||
Self {
|
Self {
|
||||||
len: 0,
|
len: 0,
|
||||||
ipiv: VectorN::new_uninitialized_generic(dim, U1),
|
ipiv: VectorN::new_uninitialized_generic(dim, U1).assume_init(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,7 +54,7 @@ where
|
||||||
let (nrows, ncols) = matrix.data.shape();
|
let (nrows, ncols) = matrix.data.shape();
|
||||||
let min_nrows_ncols = nrows.min(ncols);
|
let min_nrows_ncols = nrows.min(ncols);
|
||||||
|
|
||||||
let mut diag = unsafe { MatrixMN::new_uninitialized_generic(min_nrows_ncols, U1) };
|
let mut diag = unsafe { crate::zero_or_uninitialized_generic!(min_nrows_ncols, U1) };
|
||||||
|
|
||||||
if min_nrows_ncols.value() == 0 {
|
if min_nrows_ncols.value() == 0 {
|
||||||
return QR { qr: matrix, diag };
|
return QR { qr: matrix, diag };
|
||||||
|
|
|
@ -71,7 +71,7 @@ where
|
||||||
/// number of iteration is exceeded, `None` is returned. If `niter == 0`, then the algorithm
|
/// number of iteration is exceeded, `None` is returned. If `niter == 0`, then the algorithm
|
||||||
/// continues indefinitely until convergence.
|
/// continues indefinitely until convergence.
|
||||||
pub fn try_new(m: MatrixN<N, D>, eps: N::RealField, max_niter: usize) -> Option<Self> {
|
pub fn try_new(m: MatrixN<N, D>, eps: N::RealField, max_niter: usize) -> Option<Self> {
|
||||||
let mut work = unsafe { VectorN::new_uninitialized_generic(m.data.shape().0, U1) };
|
let mut work = unsafe { crate::zero_or_uninitialized_generic!(m.data.shape().0, U1) };
|
||||||
|
|
||||||
Self::do_decompose(m, &mut work, eps, max_niter, true)
|
Self::do_decompose(m, &mut work, eps, max_niter, true)
|
||||||
.map(|(q, t)| Schur { q: q.unwrap(), t })
|
.map(|(q, t)| Schur { q: q.unwrap(), t })
|
||||||
|
@ -378,7 +378,7 @@ where
|
||||||
///
|
///
|
||||||
/// Return `None` if some eigenvalues are complex.
|
/// Return `None` if some eigenvalues are complex.
|
||||||
pub fn eigenvalues(&self) -> Option<VectorN<N, D>> {
|
pub fn eigenvalues(&self) -> Option<VectorN<N, D>> {
|
||||||
let mut out = unsafe { VectorN::new_uninitialized_generic(self.t.data.shape().0, U1) };
|
let mut out = unsafe { crate::zero_or_uninitialized_generic!(self.t.data.shape().0, U1) };
|
||||||
if Self::do_eigenvalues(&self.t, &mut out) {
|
if Self::do_eigenvalues(&self.t, &mut out) {
|
||||||
Some(out)
|
Some(out)
|
||||||
} else {
|
} else {
|
||||||
|
@ -392,7 +392,7 @@ where
|
||||||
N: RealField,
|
N: RealField,
|
||||||
DefaultAllocator: Allocator<NumComplex<N>, D>,
|
DefaultAllocator: Allocator<NumComplex<N>, D>,
|
||||||
{
|
{
|
||||||
let mut out = unsafe { VectorN::new_uninitialized_generic(self.t.data.shape().0, U1) };
|
let mut out = unsafe { crate::zero_or_uninitialized_generic!(self.t.data.shape().0, U1) };
|
||||||
Self::do_complex_eigenvalues(&self.t, &mut out);
|
Self::do_complex_eigenvalues(&self.t, &mut out);
|
||||||
out
|
out
|
||||||
}
|
}
|
||||||
|
@ -503,7 +503,7 @@ where
|
||||||
"Unable to compute eigenvalues of a non-square matrix."
|
"Unable to compute eigenvalues of a non-square matrix."
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut work = unsafe { VectorN::new_uninitialized_generic(self.data.shape().0, U1) };
|
let mut work = unsafe { crate::zero_or_uninitialized_generic!(self.data.shape().0, U1) };
|
||||||
|
|
||||||
// Special case for 2x2 matrices.
|
// Special case for 2x2 matrices.
|
||||||
if self.nrows() == 2 {
|
if self.nrows() == 2 {
|
||||||
|
@ -544,7 +544,7 @@ where
|
||||||
DefaultAllocator: Allocator<NumComplex<N>, D>,
|
DefaultAllocator: Allocator<NumComplex<N>, D>,
|
||||||
{
|
{
|
||||||
let dim = self.data.shape().0;
|
let dim = self.data.shape().0;
|
||||||
let mut work = unsafe { VectorN::new_uninitialized_generic(dim, U1) };
|
let mut work = unsafe { crate::zero_or_uninitialized_generic!(dim, U1) };
|
||||||
|
|
||||||
let schur = Schur::do_decompose(
|
let schur = Schur::do_decompose(
|
||||||
self.clone_owned(),
|
self.clone_owned(),
|
||||||
|
@ -554,7 +554,7 @@ where
|
||||||
false,
|
false,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let mut eig = unsafe { VectorN::new_uninitialized_generic(dim, U1) };
|
let mut eig = unsafe { crate::zero_or_uninitialized_generic!(dim, U1) };
|
||||||
Schur::do_complex_eigenvalues(&schur.1, &mut eig);
|
Schur::do_complex_eigenvalues(&schur.1, &mut eig);
|
||||||
eig
|
eig
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::allocator::Allocator;
|
use crate::allocator::Allocator;
|
||||||
use crate::base::{DefaultAllocator, MatrixMN, MatrixN, VectorN};
|
use crate::base::{DefaultAllocator, MatrixN, VectorN};
|
||||||
use crate::dimension::{DimDiff, DimSub, U1};
|
use crate::dimension::{DimDiff, DimSub, U1};
|
||||||
use crate::storage::Storage;
|
use crate::storage::Storage;
|
||||||
use simba::scalar::ComplexField;
|
use simba::scalar::ComplexField;
|
||||||
|
@ -61,8 +61,8 @@ where
|
||||||
"Unable to compute the symmetric tridiagonal decomposition of an empty matrix."
|
"Unable to compute the symmetric tridiagonal decomposition of an empty matrix."
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut off_diagonal = unsafe { MatrixMN::new_uninitialized_generic(dim.sub(U1), U1) };
|
let mut off_diagonal = unsafe { crate::zero_or_uninitialized_generic!(dim.sub(U1), U1) };
|
||||||
let mut p = unsafe { MatrixMN::new_uninitialized_generic(dim.sub(U1), U1) };
|
let mut p = unsafe { crate::zero_or_uninitialized_generic!(dim.sub(U1), U1) };
|
||||||
|
|
||||||
for i in 0..dim.value() - 1 {
|
for i in 0..dim.value() - 1 {
|
||||||
let mut m = m.rows_range_mut(i + 1..);
|
let mut m = m.rows_range_mut(i + 1..);
|
||||||
|
|
Loading…
Reference in New Issue