We have reached compilation!
This commit is contained in:
parent
9a528e23b9
commit
c01d591478
|
@ -1,4 +1,7 @@
|
||||||
use na::{DMatrix, DVector, Matrix2, Matrix3, Matrix4, OMatrix, Vector2, Vector3, Vector4, U10};
|
use na::{
|
||||||
|
Const, DMatrix, DVector, Dynamic, Matrix2, Matrix3, Matrix4, OMatrix, Vector2, Vector3,
|
||||||
|
Vector4, U10,
|
||||||
|
};
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
use rand_isaac::IsaacRng;
|
use rand_isaac::IsaacRng;
|
||||||
use std::ops::{Add, Div, Mul, Sub};
|
use std::ops::{Add, Div, Mul, Sub};
|
||||||
|
@ -186,7 +189,7 @@ fn axpy(bench: &mut criterion::Criterion) {
|
||||||
fn tr_mul_to(bench: &mut criterion::Criterion) {
|
fn tr_mul_to(bench: &mut criterion::Criterion) {
|
||||||
let a = DMatrix::<f64>::new_random(1000, 1000);
|
let a = DMatrix::<f64>::new_random(1000, 1000);
|
||||||
let b = DVector::<f64>::new_random(1000);
|
let b = DVector::<f64>::new_random(1000);
|
||||||
let mut c = DVector::from_element(1000, 0.0);
|
let mut c = DVector::new_uninitialized_generic(Dynamic::new(1000), Const::<1>);
|
||||||
|
|
||||||
bench.bench_function("tr_mul_to", move |bh| bh.iter(|| a.tr_mul_to(&b, &mut c)));
|
bench.bench_function("tr_mul_to", move |bh| bh.iter(|| a.tr_mul_to(&b, &mut c)));
|
||||||
}
|
}
|
||||||
|
@ -194,7 +197,7 @@ fn tr_mul_to(bench: &mut criterion::Criterion) {
|
||||||
fn mat_mul_mat(bench: &mut criterion::Criterion) {
|
fn mat_mul_mat(bench: &mut criterion::Criterion) {
|
||||||
let a = DMatrix::<f64>::new_random(100, 100);
|
let a = DMatrix::<f64>::new_random(100, 100);
|
||||||
let b = DMatrix::<f64>::new_random(100, 100);
|
let b = DMatrix::<f64>::new_random(100, 100);
|
||||||
let mut ab = DMatrix::<f64>::from_element(100, 100, 0.0);
|
let mut ab = DMatrix::new_uninitialized_generic(Dynamic::new(100), Dynamic::new(100));
|
||||||
|
|
||||||
bench.bench_function("mat_mul_mat", move |bh| {
|
bench.bench_function("mat_mul_mat", move |bh| {
|
||||||
bh.iter(|| {
|
bh.iter(|| {
|
||||||
|
|
|
@ -78,9 +78,9 @@ where
|
||||||
|
|
||||||
let lda = n as i32;
|
let lda = n as i32;
|
||||||
|
|
||||||
let mut wr = unsafe { Matrix::new_uninitialized_generic(nrows, Const::<1>).assume_init() };
|
let mut wr = unsafe { Matrix::new_uninitialized_generic(nrows, U1).assume_init() };
|
||||||
// TODO: Tap into the workspace.
|
// TODO: Tap into the workspace.
|
||||||
let mut wi = unsafe { Matrix::new_uninitialized_generic(nrows, Const::<1>).assume_init() };
|
let mut wi = unsafe { Matrix::new_uninitialized_generic(nrows, U1).assume_init() };
|
||||||
|
|
||||||
let mut info = 0;
|
let mut info = 0;
|
||||||
let mut placeholder1 = [T::zero()];
|
let mut placeholder1 = [T::zero()];
|
||||||
|
@ -247,8 +247,8 @@ where
|
||||||
|
|
||||||
let lda = n as i32;
|
let lda = n as i32;
|
||||||
|
|
||||||
let mut wr = unsafe { Matrix::new_uninitialized_generic(nrows, Const::<1>).assume_init() };
|
let mut wr = unsafe { Matrix::new_uninitialized_generic(nrows, U1).assume_init() };
|
||||||
let mut wi = unsafe { Matrix::new_uninitialized_generic(nrows, Const::<1>).assume_init() };
|
let mut wi = unsafe { Matrix::new_uninitialized_generic(nrows, U1).assume_init() };
|
||||||
|
|
||||||
let mut info = 0;
|
let mut info = 0;
|
||||||
let mut placeholder1 = [T::zero()];
|
let mut placeholder1 = [T::zero()];
|
||||||
|
@ -291,7 +291,7 @@ where
|
||||||
);
|
);
|
||||||
lapack_panic!(info);
|
lapack_panic!(info);
|
||||||
|
|
||||||
let mut res = unsafe { Matrix::new_uninitialized_generic(nrows, Const::<1>).assume_init() };
|
let mut res = unsafe { Matrix::new_uninitialized_generic(nrows, U1).assume_init() };
|
||||||
|
|
||||||
for i in 0..res.len() {
|
for i in 0..res.len() {
|
||||||
res[i] = Complex::new(wr[i], wi[i]);
|
res[i] = Complex::new(wr[i], wi[i]);
|
||||||
|
|
|
@ -61,7 +61,7 @@ where
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut tau = unsafe {
|
let mut tau = unsafe {
|
||||||
Matrix::new_uninitialized_generic(nrows.sub(Const::<1>), Const::<1>).assume_init()
|
Matrix::new_uninitialized_generic(nrows.sub(U1), U1).assume_init()
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut info = 0;
|
let mut info = 0;
|
||||||
|
|
|
@ -66,7 +66,7 @@ where
|
||||||
let nrows = nrows.value() as i32;
|
let nrows = nrows.value() as i32;
|
||||||
let ncols = ncols.value() as i32;
|
let ncols = ncols.value() as i32;
|
||||||
|
|
||||||
let mut ipiv: OVector<i32, _> = Matrix::zeros_generic(min_nrows_ncols, Const::<1>);
|
let mut ipiv: OVector<i32, _> = Matrix::zeros_generic(min_nrows_ncols, U1);
|
||||||
|
|
||||||
let mut info = 0;
|
let mut info = 0;
|
||||||
|
|
||||||
|
|
|
@ -58,7 +58,7 @@ where
|
||||||
|
|
||||||
let mut info = 0;
|
let mut info = 0;
|
||||||
let mut tau = unsafe {
|
let mut tau = unsafe {
|
||||||
Matrix::new_uninitialized_generic(nrows.min(ncols), Const::<1>).assume_init()
|
Matrix::new_uninitialized_generic(nrows.min(ncols), U1).assume_init()
|
||||||
};
|
};
|
||||||
|
|
||||||
if nrows.value() == 0 || ncols.value() == 0 {
|
if nrows.value() == 0 || ncols.value() == 0 {
|
||||||
|
|
|
@ -78,8 +78,8 @@ where
|
||||||
|
|
||||||
let mut info = 0;
|
let mut info = 0;
|
||||||
|
|
||||||
let mut wr = unsafe { Matrix::new_uninitialized_generic(nrows, Const::<1>).assume_init() };
|
let mut wr = unsafe { Matrix::new_uninitialized_generic(nrows, U1).assume_init() };
|
||||||
let mut wi = unsafe { Matrix::new_uninitialized_generic(nrows, Const::<1>).assume_init() };
|
let mut wi = unsafe { Matrix::new_uninitialized_generic(nrows, U1).assume_init() };
|
||||||
let mut q = unsafe { Matrix::new_uninitialized_generic(nrows, ncols).assume_init() };
|
let mut q = unsafe { Matrix::new_uninitialized_generic(nrows, ncols).assume_init() };
|
||||||
// Placeholders:
|
// Placeholders:
|
||||||
let mut bwork = [0i32];
|
let mut bwork = [0i32];
|
||||||
|
@ -154,7 +154,7 @@ where
|
||||||
DefaultAllocator: Allocator<Complex<T>, D>,
|
DefaultAllocator: Allocator<Complex<T>, D>,
|
||||||
{
|
{
|
||||||
let mut out =
|
let mut out =
|
||||||
unsafe { OVector::new_uninitialized_generic(self.t.data.shape().0, Const::<1>) };
|
unsafe { OVector::new_uninitialized_generic(self.t.data.shape().0, U1) };
|
||||||
|
|
||||||
for i in 0..out.len() {
|
for i in 0..out.len() {
|
||||||
out[i] = MaybeUninit::new(Complex::new(self.re[i], self.im[i]));
|
out[i] = MaybeUninit::new(Complex::new(self.re[i], self.im[i]));
|
||||||
|
|
|
@ -100,7 +100,7 @@ macro_rules! svd_impl(
|
||||||
let lda = nrows.value() as i32;
|
let lda = nrows.value() as i32;
|
||||||
|
|
||||||
let mut u = unsafe { Matrix::new_uninitialized_generic(nrows, nrows).assume_init() };
|
let mut u = unsafe { Matrix::new_uninitialized_generic(nrows, nrows).assume_init() };
|
||||||
let mut s = unsafe { Matrix::new_uninitialized_generic(nrows.min(ncols), Const::<1>).assume_init() };
|
let mut s = unsafe { Matrix::new_uninitialized_generic(nrows.min(ncols), U1).assume_init() };
|
||||||
let mut vt = unsafe { Matrix::new_uninitialized_generic(ncols, ncols).assume_init() };
|
let mut vt = unsafe { Matrix::new_uninitialized_generic(ncols, ncols).assume_init() };
|
||||||
|
|
||||||
let ldu = nrows.value();
|
let ldu = nrows.value();
|
||||||
|
|
|
@ -95,7 +95,7 @@ where
|
||||||
let lda = n as i32;
|
let lda = n as i32;
|
||||||
|
|
||||||
let mut values =
|
let mut values =
|
||||||
unsafe { Matrix::new_uninitialized_generic(nrows, Const::<1>).assume_init() };
|
unsafe { Matrix::new_uninitialized_generic(nrows, U1).assume_init() };
|
||||||
let mut info = 0;
|
let mut info = 0;
|
||||||
|
|
||||||
let lwork = T::xsyev_work_size(jobz, b'L', n as i32, m.as_mut_slice(), lda, &mut info);
|
let lwork = T::xsyev_work_size(jobz, b'L', n as i32, m.as_mut_slice(), lda, &mut info);
|
||||||
|
|
|
@ -8,7 +8,7 @@ use num_traits::Zero;
|
||||||
|
|
||||||
impl<'a, T, R: Dim, C: Dim, S> From<&'a Matrix<T, R, C, S>> for CooMatrix<T>
|
impl<'a, T, R: Dim, C: Dim, S> From<&'a Matrix<T, R, C, S>> for CooMatrix<T>
|
||||||
where
|
where
|
||||||
T: Scalar + Zero,
|
T: Scalar + Zero + PartialEq,
|
||||||
S: Storage<T, R, C>,
|
S: Storage<T, R, C>,
|
||||||
{
|
{
|
||||||
fn from(matrix: &'a Matrix<T, R, C, S>) -> Self {
|
fn from(matrix: &'a Matrix<T, R, C, S>) -> Self {
|
||||||
|
@ -45,7 +45,7 @@ where
|
||||||
|
|
||||||
impl<'a, T, R: Dim, C: Dim, S> From<&'a Matrix<T, R, C, S>> for CsrMatrix<T>
|
impl<'a, T, R: Dim, C: Dim, S> From<&'a Matrix<T, R, C, S>> for CsrMatrix<T>
|
||||||
where
|
where
|
||||||
T: Scalar + Zero,
|
T: Scalar + Zero + PartialEq,
|
||||||
S: Storage<T, R, C>,
|
S: Storage<T, R, C>,
|
||||||
{
|
{
|
||||||
fn from(matrix: &'a Matrix<T, R, C, S>) -> Self {
|
fn from(matrix: &'a Matrix<T, R, C, S>) -> Self {
|
||||||
|
@ -82,7 +82,7 @@ where
|
||||||
|
|
||||||
impl<'a, T, R: Dim, C: Dim, S> From<&'a Matrix<T, R, C, S>> for CscMatrix<T>
|
impl<'a, T, R: Dim, C: Dim, S> From<&'a Matrix<T, R, C, S>> for CscMatrix<T>
|
||||||
where
|
where
|
||||||
T: Scalar + Zero,
|
T: Scalar + Zero + PartialEq,
|
||||||
S: Storage<T, R, C>,
|
S: Storage<T, R, C>,
|
||||||
{
|
{
|
||||||
fn from(matrix: &'a Matrix<T, R, C, S>) -> Self {
|
fn from(matrix: &'a Matrix<T, R, C, S>) -> Self {
|
||||||
|
|
|
@ -16,11 +16,9 @@ use crate::csc::CscMatrix;
|
||||||
use crate::csr::CsrMatrix;
|
use crate::csr::CsrMatrix;
|
||||||
|
|
||||||
/// Converts a dense matrix to [`CooMatrix`].
|
/// Converts a dense matrix to [`CooMatrix`].
|
||||||
pub fn convert_dense_coo<T, R, C, S>(dense: &Matrix<T, R, C, S>) -> CooMatrix<T>
|
pub fn convert_dense_coo<T, R: Dim, C: Dim, S>(dense: &Matrix<T, R, C, S>) -> CooMatrix<T>
|
||||||
where
|
where
|
||||||
T: Scalar + Zero,
|
T: Scalar + Zero + PartialEq,
|
||||||
R: Dim,
|
|
||||||
C: Dim,
|
|
||||||
S: Storage<T, R, C>,
|
S: Storage<T, R, C>,
|
||||||
{
|
{
|
||||||
let mut coo = CooMatrix::new(dense.nrows(), dense.ncols());
|
let mut coo = CooMatrix::new(dense.nrows(), dense.ncols());
|
||||||
|
@ -93,7 +91,7 @@ where
|
||||||
/// Converts a dense matrix to a [`CsrMatrix`].
|
/// Converts a dense matrix to a [`CsrMatrix`].
|
||||||
pub fn convert_dense_csr<T, R, C, S>(dense: &Matrix<T, R, C, S>) -> CsrMatrix<T>
|
pub fn convert_dense_csr<T, R, C, S>(dense: &Matrix<T, R, C, S>) -> CsrMatrix<T>
|
||||||
where
|
where
|
||||||
T: Scalar + Zero,
|
T: Scalar + Zero + PartialEq,
|
||||||
R: Dim,
|
R: Dim,
|
||||||
C: Dim,
|
C: Dim,
|
||||||
S: Storage<T, R, C>,
|
S: Storage<T, R, C>,
|
||||||
|
@ -170,7 +168,7 @@ where
|
||||||
/// Converts a dense matrix to a [`CscMatrix`].
|
/// Converts a dense matrix to a [`CscMatrix`].
|
||||||
pub fn convert_dense_csc<T, R, C, S>(dense: &Matrix<T, R, C, S>) -> CscMatrix<T>
|
pub fn convert_dense_csc<T, R, C, S>(dense: &Matrix<T, R, C, S>) -> CscMatrix<T>
|
||||||
where
|
where
|
||||||
T: Scalar + Zero,
|
T: Scalar + Zero + PartialEq,
|
||||||
R: Dim,
|
R: Dim,
|
||||||
C: Dim,
|
C: Dim,
|
||||||
S: Storage<T, R, C>,
|
S: Storage<T, R, C>,
|
||||||
|
|
|
@ -6,7 +6,7 @@ use crate::ops::serial::{
|
||||||
spmm_csc_prealloc, spmm_csr_dense, spmm_csr_pattern, spmm_csr_prealloc,
|
spmm_csc_prealloc, spmm_csr_dense, spmm_csr_pattern, spmm_csr_prealloc,
|
||||||
};
|
};
|
||||||
use crate::ops::Op;
|
use crate::ops::Op;
|
||||||
use nalgebra::allocator::Allocator;
|
use nalgebra::allocator::{Allocator, InnerAllocator};
|
||||||
use nalgebra::base::storage::Storage;
|
use nalgebra::base::storage::Storage;
|
||||||
use nalgebra::constraint::{DimEq, ShapeConstraint};
|
use nalgebra::constraint::{DimEq, ShapeConstraint};
|
||||||
use nalgebra::{
|
use nalgebra::{
|
||||||
|
@ -28,7 +28,7 @@ macro_rules! impl_bin_op {
|
||||||
// Note: The Neg bound is currently required because we delegate e.g.
|
// Note: The Neg bound is currently required because we delegate e.g.
|
||||||
// Sub to SpAdd with negative coefficients. This is not well-defined for
|
// Sub to SpAdd with negative coefficients. This is not well-defined for
|
||||||
// unsigned data types.
|
// unsigned data types.
|
||||||
$($scalar_type: $($bounds + )? Scalar + ClosedAdd + ClosedSub + ClosedMul + Zero + One + Neg<Output=T>)?
|
$($scalar_type: $($bounds + )? Scalar + ClosedAdd + ClosedSub + ClosedMul + Zero + One + Neg<Output=T> + PartialEq)?
|
||||||
{
|
{
|
||||||
type Output = $ret;
|
type Output = $ret;
|
||||||
fn $method(self, $b: $b_type) -> Self::Output {
|
fn $method(self, $b: $b_type) -> Self::Output {
|
||||||
|
@ -306,9 +306,9 @@ macro_rules! impl_spmm_cs_dense {
|
||||||
// TODO: Is it possible to simplify these bounds?
|
// TODO: Is it possible to simplify these bounds?
|
||||||
ShapeConstraint:
|
ShapeConstraint:
|
||||||
// Bounds so that we can turn OMatrix<T, Dynamic, C> into a DMatrixSliceMut
|
// Bounds so that we can turn OMatrix<T, Dynamic, C> into a DMatrixSliceMut
|
||||||
DimEq<U1, <<DefaultAllocator as Allocator<T, Dynamic, C>>::Buffer as Storage<T, Dynamic, C>>::RStride>
|
DimEq<U1, <<DefaultAllocator as InnerAllocator<T, Dynamic, C>>::Buffer as Storage<T, Dynamic, C>>::RStride>
|
||||||
+ DimEq<C, Dynamic>
|
+ DimEq<C, Dynamic>
|
||||||
+ DimEq<Dynamic, <<DefaultAllocator as Allocator<T, Dynamic, C>>::Buffer as Storage<T, Dynamic, C>>::CStride>
|
+ DimEq<Dynamic, <<DefaultAllocator as InnerAllocator<T, Dynamic, C>>::Buffer as Storage<T, Dynamic, C>>::CStride>
|
||||||
// Bounds so that we can turn &Matrix<T, R, C, S> into a DMatrixSlice
|
// Bounds so that we can turn &Matrix<T, R, C, S> into a DMatrixSlice
|
||||||
+ DimEq<U1, S::RStride>
|
+ DimEq<U1, S::RStride>
|
||||||
+ DimEq<R, Dynamic>
|
+ DimEq<R, Dynamic>
|
||||||
|
|
|
@ -74,7 +74,7 @@ pub fn spadd_cs_prealloc<T>(
|
||||||
a: Op<&CsMatrix<T>>,
|
a: Op<&CsMatrix<T>>,
|
||||||
) -> Result<(), OperationError>
|
) -> Result<(), OperationError>
|
||||||
where
|
where
|
||||||
T: Scalar + ClosedAdd + ClosedMul + Zero + One,
|
T: Scalar + ClosedAdd + ClosedMul + Zero + One+PartialEq,
|
||||||
{
|
{
|
||||||
match a {
|
match a {
|
||||||
Op::NoOp(a) => {
|
Op::NoOp(a) => {
|
||||||
|
|
|
@ -55,7 +55,7 @@ pub fn spadd_csc_prealloc<T>(
|
||||||
a: Op<&CscMatrix<T>>,
|
a: Op<&CscMatrix<T>>,
|
||||||
) -> Result<(), OperationError>
|
) -> Result<(), OperationError>
|
||||||
where
|
where
|
||||||
T: Scalar + ClosedAdd + ClosedMul + Zero + One,
|
T: Scalar + ClosedAdd + ClosedMul + Zero + One+PartialEq,
|
||||||
{
|
{
|
||||||
assert_compatible_spadd_dims!(c, a);
|
assert_compatible_spadd_dims!(c, a);
|
||||||
spadd_cs_prealloc(beta, &mut c.cs, alpha, a.map_same_op(|a| &a.cs))
|
spadd_cs_prealloc(beta, &mut c.cs, alpha, a.map_same_op(|a| &a.cs))
|
||||||
|
|
|
@ -50,7 +50,7 @@ pub fn spadd_csr_prealloc<T>(
|
||||||
a: Op<&CsrMatrix<T>>,
|
a: Op<&CsrMatrix<T>>,
|
||||||
) -> Result<(), OperationError>
|
) -> Result<(), OperationError>
|
||||||
where
|
where
|
||||||
T: Scalar + ClosedAdd + ClosedMul + Zero + One,
|
T: Scalar + ClosedAdd + ClosedMul + Zero + One + PartialEq,
|
||||||
{
|
{
|
||||||
assert_compatible_spadd_dims!(c, a);
|
assert_compatible_spadd_dims!(c, a);
|
||||||
spadd_cs_prealloc(beta, &mut c.cs, alpha, a.map_same_op(|a| &a.cs))
|
spadd_cs_prealloc(beta, &mut c.cs, alpha, a.map_same_op(|a| &a.cs))
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
//! Abstract definition of a matrix data storage allocator.
|
//! Abstract definition of a matrix data storage allocator.
|
||||||
|
|
||||||
use std::mem::MaybeUninit;
|
use std::mem::{ManuallyDrop, MaybeUninit};
|
||||||
|
|
||||||
use crate::base::constraint::{SameNumberOfColumns, SameNumberOfRows, ShapeConstraint};
|
use crate::base::constraint::{SameNumberOfColumns, SameNumberOfRows, ShapeConstraint};
|
||||||
use crate::base::dimension::{Dim, U1};
|
use crate::base::dimension::{Dim, U1};
|
||||||
|
@ -30,9 +30,12 @@ pub trait InnerAllocator<T, R: Dim, C: Dim = U1>: 'static + Sized {
|
||||||
) -> Self::Buffer;
|
) -> Self::Buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Same as the [`InnerAllocator`] trait, but also provides methods to build uninitialized buffers.
|
/// Same as the [`InnerAllocator`] trait, but also provides methods to build uninitialized buffers,
|
||||||
|
/// or buffers whose entries must be manually dropped.
|
||||||
pub trait Allocator<T, R: Dim, C: Dim = U1>:
|
pub trait Allocator<T, R: Dim, C: Dim = U1>:
|
||||||
InnerAllocator<T, R, C> + InnerAllocator<MaybeUninit<T>, R, C>
|
InnerAllocator<T, R, C>
|
||||||
|
+ InnerAllocator<MaybeUninit<T>, R, C>
|
||||||
|
+ InnerAllocator<ManuallyDrop<T>, R, C>
|
||||||
{
|
{
|
||||||
/// 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.
|
||||||
fn allocate_uninitialized(
|
fn allocate_uninitialized(
|
||||||
|
@ -44,6 +47,11 @@ pub trait Allocator<T, R: Dim, C: Dim = U1>:
|
||||||
unsafe fn assume_init(
|
unsafe fn assume_init(
|
||||||
uninit: <Self as InnerAllocator<MaybeUninit<T>, R, C>>::Buffer,
|
uninit: <Self as InnerAllocator<MaybeUninit<T>, R, C>>::Buffer,
|
||||||
) -> <Self as InnerAllocator<T, R, C>>::Buffer;
|
) -> <Self as InnerAllocator<T, R, C>>::Buffer;
|
||||||
|
|
||||||
|
/// Specifies that a given buffer's entries should be manually dropped.
|
||||||
|
fn manually_drop(
|
||||||
|
buf: <Self as InnerAllocator<T, R, C>>::Buffer,
|
||||||
|
) -> <Self as InnerAllocator<ManuallyDrop<T>, R, C>>::Buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A matrix reallocator. Changes the size of the memory buffer that initially contains (RFrom ×
|
/// A matrix reallocator. Changes the size of the memory buffer that initially contains (RFrom ×
|
||||||
|
@ -84,8 +92,7 @@ where
|
||||||
impl<T, R1: Dim, R2: Dim, C1: Dim, C2: Dim> SameShapeAllocator<T, R1, C1, R2, C2>
|
impl<T, R1: Dim, R2: Dim, C1: Dim, C2: Dim> SameShapeAllocator<T, R1, C1, R2, C2>
|
||||||
for DefaultAllocator
|
for DefaultAllocator
|
||||||
where
|
where
|
||||||
DefaultAllocator:
|
DefaultAllocator: Allocator<T, R1, C1> + Allocator<T, SameShapeR<R1, R2>, SameShapeC<C1, C2>>,
|
||||||
Allocator<T, R1, C1> + Allocator<T, SameShapeR<R1, R2>, SameShapeC<C1, C2>>,
|
|
||||||
ShapeConstraint: SameNumberOfRows<R1, R2> + SameNumberOfColumns<C1, C2>,
|
ShapeConstraint: SameNumberOfRows<R1, R2> + SameNumberOfColumns<C1, C2>,
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -93,9 +100,7 @@ where
|
||||||
// XXX: Bad name.
|
// XXX: Bad name.
|
||||||
/// Restricts the given number of rows to be equal.
|
/// Restricts the given number of rows to be equal.
|
||||||
pub trait SameShapeVectorAllocator<T, R1: Dim, R2: Dim>:
|
pub trait SameShapeVectorAllocator<T, R1: Dim, R2: Dim>:
|
||||||
Allocator<T, R1>
|
Allocator<T, R1> + Allocator<T, SameShapeR<R1, R2>> + SameShapeAllocator<T, R1, U1, R2, U1>
|
||||||
+ Allocator<T, SameShapeR<R1, R2>>
|
|
||||||
+ SameShapeAllocator<T, R1, U1, R2, U1>
|
|
||||||
where
|
where
|
||||||
ShapeConstraint: SameNumberOfRows<R1, R2>,
|
ShapeConstraint: SameNumberOfRows<R1, R2>,
|
||||||
{
|
{
|
||||||
|
|
|
@ -329,22 +329,18 @@ where
|
||||||
|
|
||||||
if !b.is_zero() {
|
if !b.is_zero() {
|
||||||
for i in 0..x.len() {
|
for i in 0..x.len() {
|
||||||
|
|
||||||
let y = y.get_unchecked_mut(i * rstride1);
|
let y = y.get_unchecked_mut(i * rstride1);
|
||||||
*y = a.inlined_clone()
|
*y = a.inlined_clone()
|
||||||
* x.get_unchecked(i * rstride2).inlined_clone()
|
* x.get_unchecked(i * rstride2).inlined_clone()
|
||||||
* c.inlined_clone()
|
* c.inlined_clone()
|
||||||
+ b.inlined_clone() * y.inlined_clone();
|
+ b.inlined_clone() * y.inlined_clone();
|
||||||
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for i in 0..x.len() {
|
for i in 0..x.len() {
|
||||||
|
|
||||||
let y = y.get_unchecked_mut(i * rstride1);
|
let y = y.get_unchecked_mut(i * rstride1);
|
||||||
*y = a.inlined_clone()
|
*y = a.inlined_clone()
|
||||||
* x.get_unchecked(i * rstride2).inlined_clone()
|
* x.get_unchecked(i * rstride2).inlined_clone()
|
||||||
* c.inlined_clone();
|
* c.inlined_clone();
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -852,6 +848,8 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Computes `self = alpha * a * x`, where `a` is an **hermitian** matrix, `x` a
|
||||||
|
/// vector, and `alpha, beta` two scalars.
|
||||||
pub fn hegemv_z<D2: Dim, D3: Dim, SB, SC>(
|
pub fn hegemv_z<D2: Dim, D3: Dim, SB, SC>(
|
||||||
&mut self,
|
&mut self,
|
||||||
alpha: T,
|
alpha: T,
|
||||||
|
@ -1574,7 +1572,8 @@ where
|
||||||
ShapeConstraint: DimEq<D1, R3> + DimEq<C3, D4>,
|
ShapeConstraint: DimEq<D1, R3> + DimEq<C3, D4>,
|
||||||
DefaultAllocator: Allocator<T, R3>,
|
DefaultAllocator: Allocator<T, R3>,
|
||||||
{
|
{
|
||||||
let mut work = Matrix::new_uninitialized_generic(R3::from_usize(self.shape().0), Const::<1>);
|
let mut work =
|
||||||
|
Matrix::new_uninitialized_generic(R3::from_usize(self.shape().0), Const::<1>);
|
||||||
work.gemv_z(T::one(), lhs, &mid.column(0));
|
work.gemv_z(T::one(), lhs, &mid.column(0));
|
||||||
let mut work = unsafe { work.assume_init() };
|
let mut work = unsafe { work.assume_init() };
|
||||||
|
|
||||||
|
@ -1624,7 +1623,8 @@ where
|
||||||
DefaultAllocator: Allocator<T, D3>,
|
DefaultAllocator: Allocator<T, D3>,
|
||||||
{
|
{
|
||||||
// TODO: figure out why type inference wasn't doing its job.
|
// TODO: figure out why type inference wasn't doing its job.
|
||||||
let mut work = Matrix::new_uninitialized_generic(D3::from_usize(self.shape().0), Const::<1>);
|
let mut work =
|
||||||
|
Matrix::new_uninitialized_generic(D3::from_usize(self.shape().0), Const::<1>);
|
||||||
work.gemv_z::<D3, D3, R4, S3, _>(T::one(), mid, &rhs.column(0));
|
work.gemv_z::<D3, D3, R4, S3, _>(T::one(), mid, &rhs.column(0));
|
||||||
let mut work = unsafe { work.assume_init() };
|
let mut work = unsafe { work.assume_init() };
|
||||||
|
|
||||||
|
|
|
@ -361,7 +361,7 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T: Dim, R: Dim, C: Dim, RSlice: Dim, CSlice: Dim, RStride: Dim, CStride: Dim, S>
|
impl<'a, T, R: Dim, C: Dim, RSlice: Dim, CSlice: Dim, RStride: Dim, CStride: Dim, S>
|
||||||
From<&'a mut Matrix<T, R, C, S>> for MatrixSliceMut<'a, T, RSlice, CSlice, RStride, CStride>
|
From<&'a mut Matrix<T, R, C, S>> for MatrixSliceMut<'a, T, RSlice, CSlice, RStride, CStride>
|
||||||
where
|
where
|
||||||
S: StorageMut<T, R, C>,
|
S: StorageMut<T, R, C>,
|
||||||
|
|
|
@ -4,8 +4,7 @@
|
||||||
//! heap-allocated buffers for matrices with at least one dimension unknown at compile-time.
|
//! heap-allocated buffers for matrices with at least one dimension unknown at compile-time.
|
||||||
|
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
use std::mem::ManuallyDrop;
|
use std::mem::{self, ManuallyDrop, MaybeUninit};
|
||||||
use std::mem::MaybeUninit;
|
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
|
|
||||||
#[cfg(all(feature = "alloc", not(feature = "std")))]
|
#[cfg(all(feature = "alloc", not(feature = "std")))]
|
||||||
|
@ -22,10 +21,6 @@ use crate::base::storage::{ContiguousStorageMut, Storage, StorageMut};
|
||||||
use crate::base::vec_storage::VecStorage;
|
use crate::base::vec_storage::VecStorage;
|
||||||
use crate::storage::Owned;
|
use crate::storage::Owned;
|
||||||
|
|
||||||
type DefaultBuffer<T, R, C> = <DefaultAllocator as InnerAllocator<T, R, C>>::Buffer;
|
|
||||||
type DefaultUninitBuffer<T, R, C> =
|
|
||||||
<DefaultAllocator as InnerAllocator<MaybeUninit<T>, R, C>>::Buffer;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
* Allocator.
|
* Allocator.
|
||||||
|
@ -72,7 +67,7 @@ impl<T, const R: usize, const C: usize> Allocator<T, Const<R>, Const<C>> for Def
|
||||||
_: Const<R>,
|
_: Const<R>,
|
||||||
_: Const<C>,
|
_: Const<C>,
|
||||||
) -> Owned<MaybeUninit<T>, Const<R>, Const<C>> {
|
) -> Owned<MaybeUninit<T>, Const<R>, Const<C>> {
|
||||||
// SAFETY: An uninitialized `[MaybeUninit<_>; LEN]` is valid.
|
// SAFETY: An uninitialized `[MaybeUninit<_>; _]` is valid.
|
||||||
let array = unsafe { MaybeUninit::uninit().assume_init() };
|
let array = unsafe { MaybeUninit::uninit().assume_init() };
|
||||||
ArrayStorage(array)
|
ArrayStorage(array)
|
||||||
}
|
}
|
||||||
|
@ -84,11 +79,24 @@ impl<T, const R: usize, const C: usize> Allocator<T, Const<R>, Const<C>> for Def
|
||||||
// SAFETY:
|
// SAFETY:
|
||||||
// * The caller guarantees that all elements of the array are initialized
|
// * The caller guarantees that all elements of the array are initialized
|
||||||
// * `MaybeUninit<T>` and T are guaranteed to have the same layout
|
// * `MaybeUninit<T>` and T are guaranteed to have the same layout
|
||||||
// * MaybeUnint does not drop, so there are no double-frees
|
// * `MaybeUnint` does not drop, so there are no double-frees
|
||||||
// * `ArrayStorage` is transparent.
|
// * `ArrayStorage` is transparent.
|
||||||
// And thus the conversion is safe
|
// And thus the conversion is safe
|
||||||
ArrayStorage((&uninit as *const _ as *const [_; C]).read())
|
ArrayStorage((&uninit as *const _ as *const [_; C]).read())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Specifies that a given buffer's entries should be manually dropped.
|
||||||
|
#[inline]
|
||||||
|
fn manually_drop(
|
||||||
|
buf: <Self as InnerAllocator<T, Const<R>, Const<C>>>::Buffer,
|
||||||
|
) -> <Self as InnerAllocator<ManuallyDrop<T>, Const<R>, Const<C>>>::Buffer {
|
||||||
|
// SAFETY:
|
||||||
|
// * `ManuallyDrop<T>` and T are guaranteed to have the same layout
|
||||||
|
// * `ManuallyDrop` does not drop, so there are no double-frees
|
||||||
|
// * `ArrayStorage` is transparent.
|
||||||
|
// And thus the conversion is safe
|
||||||
|
ArrayStorage(unsafe { mem::transmute_copy(&ManuallyDrop::new(buf.0)) })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dynamic - Static
|
// Dynamic - Static
|
||||||
|
@ -133,6 +141,25 @@ impl<T, C: Dim> Allocator<T, Dynamic, C> for DefaultAllocator {
|
||||||
|
|
||||||
VecStorage::new(uninit.nrows, uninit.ncols, new_data)
|
VecStorage::new(uninit.nrows, uninit.ncols, new_data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn manually_drop(
|
||||||
|
buf: <Self as InnerAllocator<T, Dynamic, C>>::Buffer,
|
||||||
|
) -> <Self as InnerAllocator<ManuallyDrop<T>, Dynamic, C>>::Buffer {
|
||||||
|
// Avoids dropping the buffer that will be used for the result.
|
||||||
|
let mut data = ManuallyDrop::new(buf.data);
|
||||||
|
|
||||||
|
// Safety: ManuallyDrop<T> has the same alignment and layout as T.
|
||||||
|
let new_data = unsafe {
|
||||||
|
Vec::from_raw_parts(
|
||||||
|
data.as_mut_ptr() as *mut ManuallyDrop<T>,
|
||||||
|
data.len(),
|
||||||
|
data.capacity(),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
VecStorage::new(buf.nrows, buf.ncols, new_data)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Static - Dynamic
|
// Static - Dynamic
|
||||||
|
@ -176,6 +203,25 @@ impl<T, R: DimName> Allocator<T, R, Dynamic> for DefaultAllocator {
|
||||||
|
|
||||||
VecStorage::new(uninit.nrows, uninit.ncols, new_data)
|
VecStorage::new(uninit.nrows, uninit.ncols, new_data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn manually_drop(
|
||||||
|
buf: <Self as InnerAllocator<T, R, Dynamic>>::Buffer,
|
||||||
|
) -> <Self as InnerAllocator<ManuallyDrop<T>, R, Dynamic>>::Buffer {
|
||||||
|
// Avoids dropping the buffer that will be used for the result.
|
||||||
|
let mut data = ManuallyDrop::new(buf.data);
|
||||||
|
|
||||||
|
// Safety: ManuallyDrop<T> has the same alignment and layout as T.
|
||||||
|
let new_data = unsafe {
|
||||||
|
Vec::from_raw_parts(
|
||||||
|
data.as_mut_ptr() as *mut ManuallyDrop<T>,
|
||||||
|
data.len(),
|
||||||
|
data.capacity(),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
VecStorage::new(buf.nrows, buf.ncols, new_data)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -8,7 +8,7 @@ use std::cmp::Ordering;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::hash::{Hash, Hasher};
|
use std::hash::{Hash, Hasher};
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use std::mem::{self, MaybeUninit};
|
use std::mem::{self, ManuallyDrop, MaybeUninit};
|
||||||
|
|
||||||
#[cfg(feature = "serde-serialize-no-std")]
|
#[cfg(feature = "serde-serialize-no-std")]
|
||||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||||
|
@ -194,10 +194,7 @@ pub struct Matrix<T, R, C, S> {
|
||||||
|
|
||||||
impl<T, R: Dim, C: Dim, S: Default> Default for Matrix<T, R, C, S> {
|
impl<T, R: Dim, C: Dim, S: Default> Default for Matrix<T, R, C, S> {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Matrix {
|
unsafe { Matrix::from_data_statically_unchecked(Default::default()) }
|
||||||
data: Default::default(),
|
|
||||||
_phantoms: PhantomData,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -212,7 +209,7 @@ impl<T, R: Dim, C: Dim, S: Serialize> Serialize for Matrix<T, R, C, S> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "serde-serialize-no-std")]
|
#[cfg(feature = "serde-serialize-no-std")]
|
||||||
impl<'de, T: Dim, R: Dim, C, S: Serialize<'de>> Deserialize<'de> for Matrix<T, R, C, S> {
|
impl<'de, T, R: Dim, C, S: Serialize<'de>> Deserialize<'de> for Matrix<T, R, C, S> {
|
||||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
where
|
where
|
||||||
D: Deserializer<'de>,
|
D: Deserializer<'de>,
|
||||||
|
@ -344,9 +341,20 @@ where
|
||||||
{
|
{
|
||||||
/// 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, ncols: C) -> OMatrix<MaybeUninit<T>, R, C> {
|
pub fn new_uninitialized_generic(nrows: R, ncols: C) -> OMatrix<MaybeUninit<T>, R, C> {
|
||||||
OMatrix {
|
unsafe {
|
||||||
data: <DefaultAllocator as Allocator<T, R, C>>::allocate_uninitialized(nrows, ncols),
|
OMatrix::from_data_statically_unchecked(
|
||||||
_phantoms: PhantomData,
|
<DefaultAllocator as Allocator<T, R, C>>::allocate_uninitialized(nrows, ncols),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Converts this matrix into one whose entries need to be manually dropped. This should be
|
||||||
|
/// near zero-cost.
|
||||||
|
pub fn manually_drop(self) -> OMatrix<ManuallyDrop<T>, R, C> {
|
||||||
|
unsafe {
|
||||||
|
OMatrix::from_data_statically_unchecked(
|
||||||
|
<DefaultAllocator as Allocator<T, R, C>>::manually_drop(self.data),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -356,11 +364,12 @@ where
|
||||||
DefaultAllocator: Allocator<T, R, C>,
|
DefaultAllocator: Allocator<T, R, C>,
|
||||||
{
|
{
|
||||||
/// 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.
|
||||||
|
///
|
||||||
|
/// For the similar method that operates on matrix slices, see [`slice_assume_init`].
|
||||||
pub unsafe fn assume_init(self) -> OMatrix<T, R, C> {
|
pub unsafe fn assume_init(self) -> OMatrix<T, R, C> {
|
||||||
OMatrix {
|
OMatrix::from_data_statically_unchecked(
|
||||||
data: <DefaultAllocator as Allocator<T, R, C>>::assume_init(self.data),
|
<DefaultAllocator as Allocator<T, R, C>>::assume_init(self.data),
|
||||||
_phantoms: PhantomData,
|
)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -711,30 +720,35 @@ impl<T, R: Dim, C: Dim, S: Storage<T, R, C>> Matrix<T, R, C, S> {
|
||||||
res.assume_init()
|
res.assume_init()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Transposes `self`. Does not require `T: Clone` like its other counteparts.
|
impl<T, R: Dim, C: Dim> OMatrix<T, R, C>
|
||||||
pub fn transpose_into(self) -> OMatrix<T, C, R>
|
|
||||||
where
|
where
|
||||||
DefaultAllocator: Allocator<T, C, R>,
|
DefaultAllocator: Allocator<T, C, R> + Allocator<T, R, C>,
|
||||||
{
|
{
|
||||||
|
/// Transposes `self`. Does not require `T: Clone` like its other counterparts.
|
||||||
|
pub fn transpose_into(self) -> OMatrix<T, C, R> {
|
||||||
let (nrows, ncols) = self.data.shape();
|
let (nrows, ncols) = self.data.shape();
|
||||||
let mut res = OMatrix::new_uninitialized_generic(ncols, nrows);
|
let mut res = OMatrix::new_uninitialized_generic(ncols, nrows);
|
||||||
|
let mut md = self.manually_drop();
|
||||||
|
|
||||||
let (nrows, ncols) = res.shape();
|
let (nrows, ncols) = res.shape();
|
||||||
|
|
||||||
// TODO: optimize that.
|
// TODO: optimize that.
|
||||||
for i in 0..nrows {
|
for i in 0..nrows {
|
||||||
for j in 0..ncols {
|
for j in 0..ncols {
|
||||||
|
// Safety: the indices are within range, and since the indices
|
||||||
|
// don't repeat, we don't do any double-drops.
|
||||||
unsafe {
|
unsafe {
|
||||||
*res.get_unchecked_mut((j, i)) = MaybeUninit::new(*self.get_unchecked((i, j)));
|
*res.get_unchecked_mut((j, i)) =
|
||||||
|
MaybeUninit::new(ManuallyDrop::take(md.get_unchecked_mut((i, j))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// BEEP! BEEP! There's a double drop here that needs to be fixed.
|
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
// Safety: res is now fully initialized due to the guarantees of transpose_to.
|
// Safety: res is now fully initialized, since we've initialized
|
||||||
|
// every single entry.
|
||||||
res.assume_init()
|
res.assume_init()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -956,7 +970,6 @@ impl<T, R: Dim, C: Dim, S: Storage<T, R, C>> Matrix<T, R, C, S> {
|
||||||
ShapeConstraint: SameNumberOfRows<R, R2> + SameNumberOfColumns<C, C2>,
|
ShapeConstraint: SameNumberOfRows<R, R2> + SameNumberOfColumns<C, C2>,
|
||||||
{
|
{
|
||||||
let (nrows, ncols) = self.data.shape();
|
let (nrows, ncols) = self.data.shape();
|
||||||
|
|
||||||
let mut res = init;
|
let mut res = init;
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -982,6 +995,7 @@ impl<T, R: Dim, C: Dim, S: Storage<T, R, C>> Matrix<T, R, C, S> {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn apply<F: FnMut(T) -> T>(&mut self, mut f: F)
|
pub fn apply<F: FnMut(T) -> T>(&mut self, mut f: F)
|
||||||
where
|
where
|
||||||
|
T: Clone, // This could be removed by changing the function signature.
|
||||||
S: StorageMut<T, R, C>,
|
S: StorageMut<T, R, C>,
|
||||||
{
|
{
|
||||||
let (nrows, ncols) = self.shape();
|
let (nrows, ncols) = self.shape();
|
||||||
|
@ -990,7 +1004,7 @@ 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 {
|
||||||
unsafe {
|
unsafe {
|
||||||
let e = self.data.get_unchecked_mut(i, j);
|
let e = self.data.get_unchecked_mut(i, j);
|
||||||
*e = f(*e)
|
*e = f(e.clone())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1004,6 +1018,7 @@ impl<T, R: Dim, C: Dim, S: Storage<T, R, C>> Matrix<T, R, C, S> {
|
||||||
rhs: &Matrix<T2, R2, C2, S2>,
|
rhs: &Matrix<T2, R2, C2, S2>,
|
||||||
mut f: impl FnMut(T, T2) -> T,
|
mut f: impl FnMut(T, T2) -> T,
|
||||||
) where
|
) where
|
||||||
|
T: Clone, // This could be removed by changing the function signature.
|
||||||
S: StorageMut<T, R, C>,
|
S: StorageMut<T, R, C>,
|
||||||
S2: Storage<T2, R2, C2>,
|
S2: Storage<T2, R2, C2>,
|
||||||
ShapeConstraint: SameNumberOfRows<R, R2> + SameNumberOfColumns<C, C2>,
|
ShapeConstraint: SameNumberOfRows<R, R2> + SameNumberOfColumns<C, C2>,
|
||||||
|
@ -1021,7 +1036,7 @@ impl<T, R: Dim, C: Dim, S: Storage<T, R, C>> Matrix<T, R, C, S> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let e = self.data.get_unchecked_mut(i, j);
|
let e = self.data.get_unchecked_mut(i, j);
|
||||||
let rhs = rhs.get_unchecked((i, j)).clone();
|
let rhs = rhs.get_unchecked((i, j)).clone();
|
||||||
*e = f(*e, rhs)
|
*e = f(e.clone(), rhs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1036,6 +1051,7 @@ impl<T, R: Dim, C: Dim, S: Storage<T, R, C>> Matrix<T, R, C, S> {
|
||||||
c: &Matrix<N3, R3, C3, S3>,
|
c: &Matrix<N3, R3, C3, S3>,
|
||||||
mut f: impl FnMut(T, T2, N3) -> T,
|
mut f: impl FnMut(T, T2, N3) -> T,
|
||||||
) where
|
) where
|
||||||
|
T: Clone, // This could be removed by changing the function signature.
|
||||||
S: StorageMut<T, R, C>,
|
S: StorageMut<T, R, C>,
|
||||||
S2: Storage<T2, R2, C2>,
|
S2: Storage<T2, R2, C2>,
|
||||||
S3: Storage<N3, R3, C3>,
|
S3: Storage<N3, R3, C3>,
|
||||||
|
@ -1061,7 +1077,7 @@ impl<T, R: Dim, C: Dim, S: Storage<T, R, C>> Matrix<T, R, C, S> {
|
||||||
let e = self.data.get_unchecked_mut(i, j);
|
let e = self.data.get_unchecked_mut(i, j);
|
||||||
let b = b.get_unchecked((i, j)).clone();
|
let b = b.get_unchecked((i, j)).clone();
|
||||||
let c = c.get_unchecked((i, j)).clone();
|
let c = c.get_unchecked((i, j)).clone();
|
||||||
*e = f(*e, b, c)
|
*e = f(e.clone(), b, c)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1249,8 +1265,11 @@ impl<T, R: Dim, C: Dim, S: StorageMut<T, R, C>> Matrix<T, R, C, S> {
|
||||||
/// Fills this matrix with the content of another one, after applying a function to
|
/// Fills this matrix with the content of another one, after applying a function to
|
||||||
/// the references of the entries of the other matrix. Both must have the same shape.
|
/// the references of the entries of the other matrix. Both must have the same shape.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn copy_from_fn<U, R2: Dim, C2: Dim, SB, F>(&mut self, other: &Matrix<U, R2, C2, SB>,mut f: F)
|
pub fn copy_from_fn<U, R2: Dim, C2: Dim, SB, F>(
|
||||||
where
|
&mut self,
|
||||||
|
other: &Matrix<U, R2, C2, SB>,
|
||||||
|
mut f: F,
|
||||||
|
) where
|
||||||
SB: Storage<U, R2, C2>,
|
SB: Storage<U, R2, C2>,
|
||||||
ShapeConstraint: SameNumberOfRows<R, R2> + SameNumberOfColumns<C, C2>,
|
ShapeConstraint: SameNumberOfRows<R, R2> + SameNumberOfColumns<C, C2>,
|
||||||
F: FnMut(&U) -> T,
|
F: FnMut(&U) -> T,
|
||||||
|
@ -1272,20 +1291,20 @@ impl<T, R: Dim, C: Dim, S: StorageMut<T, R, C>> Matrix<T, R, C, S> {
|
||||||
/// Fills this matrix with the content of another one, after applying a function to
|
/// Fills this matrix with the content of another one, after applying a function to
|
||||||
/// the entries of the other matrix. Both must have the same shape.
|
/// the entries of the other matrix. Both must have the same shape.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn move_from<R2: Dim, C2: Dim, SB>(&mut self, other: Matrix<T, R2, C2, SB>)
|
pub fn move_from<R2: Dim, C2: Dim>(&mut self, other: OMatrix<T, R2, C2>)
|
||||||
where
|
where
|
||||||
SB: Storage<T, R2, C2>,
|
|
||||||
ShapeConstraint: SameNumberOfRows<R, R2> + SameNumberOfColumns<C, C2>,
|
ShapeConstraint: SameNumberOfRows<R, R2> + SameNumberOfColumns<C, C2>,
|
||||||
|
DefaultAllocator: Allocator<T, R2, C2>,
|
||||||
{
|
{
|
||||||
self.move_from_fn(other, |e| e)
|
self.move_from_fn(other, |e| e)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Fills this matrix with the content of another one via moves. Both must have the same shape.
|
/// Fills this matrix with the content of another one via moves. Both must have the same shape.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn move_from_fn<U, R2: Dim, C2: Dim, SB, F>(&mut self, other: Matrix<U, R2, C2, SB>, mut f: F)
|
pub fn move_from_fn<U, R2: Dim, C2: Dim, F>(&mut self, other: OMatrix<U, R2, C2>, mut f: F)
|
||||||
where
|
where
|
||||||
SB: Storage<U, R2, C2>,
|
|
||||||
ShapeConstraint: SameNumberOfRows<R, R2> + SameNumberOfColumns<C, C2>,
|
ShapeConstraint: SameNumberOfRows<R, R2> + SameNumberOfColumns<C, C2>,
|
||||||
|
DefaultAllocator: Allocator<U, R2, C2>,
|
||||||
F: FnMut(U) -> T,
|
F: FnMut(U) -> T,
|
||||||
{
|
{
|
||||||
assert!(
|
assert!(
|
||||||
|
@ -1293,15 +1312,16 @@ impl<T, R: Dim, C: Dim, S: StorageMut<T, R, C>> Matrix<T, R, C, S> {
|
||||||
"Unable to move from a matrix with a different shape."
|
"Unable to move from a matrix with a different shape."
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let mut md = other.manually_drop();
|
||||||
|
|
||||||
for j in 0..self.ncols() {
|
for j in 0..self.ncols() {
|
||||||
for i in 0..self.nrows() {
|
for i in 0..self.nrows() {
|
||||||
unsafe {
|
unsafe {
|
||||||
*self.get_unchecked_mut((i, j)) = f(*other.get_unchecked((i, j)));
|
*self.get_unchecked_mut((i, j)) =
|
||||||
|
f(ManuallyDrop::take(md.get_unchecked_mut((i, j))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// BEEP BEEEP!!!!! I'm double-freeing! OH NO!!!! (todo)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Fills this matrix with the content of the transpose another one via clones.
|
/// Fills this matrix with the content of the transpose another one via clones.
|
||||||
|
@ -1345,9 +1365,9 @@ impl<T, R: Dim, C: Dim, S: StorageMut<T, R, C>> Matrix<T, R, C, S> {
|
||||||
|
|
||||||
/// Fills this matrix with the content of the transpose another one via moves.
|
/// Fills this matrix with the content of the transpose another one via moves.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn tr_move_from<R2: Dim, C2: Dim, SB>(&mut self, other: Matrix<T, R2, C2, SB>)
|
pub fn tr_move_from<R2: Dim, C2: Dim>(&mut self, other: OMatrix<T, R2, C2>)
|
||||||
where
|
where
|
||||||
SB: Storage<T, R2, C2>,
|
DefaultAllocator: Allocator<T, R2, C2>,
|
||||||
ShapeConstraint: DimEq<R, C2> + SameNumberOfColumns<C, R2>,
|
ShapeConstraint: DimEq<R, C2> + SameNumberOfColumns<C, R2>,
|
||||||
{
|
{
|
||||||
self.tr_move_from_fn(other, |e| e)
|
self.tr_move_from_fn(other, |e| e)
|
||||||
|
@ -1356,13 +1376,10 @@ impl<T, R: Dim, C: Dim, S: StorageMut<T, R, C>> Matrix<T, R, C, S> {
|
||||||
/// Fills this matrix with the content of the transpose of another one, after applying
|
/// Fills this matrix with the content of the transpose of another one, after applying
|
||||||
/// a function to the entries of the other matrix. Both must have the same shape.
|
/// a function to the entries of the other matrix. Both must have the same shape.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn tr_move_from_fn<U, R2: Dim, C2: Dim, SB, F>(
|
pub fn tr_move_from_fn<U, R2: Dim, C2: Dim, F>(&mut self, other: OMatrix<U, R2, C2>, mut f: F)
|
||||||
&mut self,
|
where
|
||||||
other: Matrix<U, R2, C2, SB>,
|
|
||||||
mut f: F,
|
|
||||||
) where
|
|
||||||
SB: Storage<U, R2, C2>,
|
|
||||||
ShapeConstraint: DimEq<R, C2> + SameNumberOfColumns<C, R2>,
|
ShapeConstraint: DimEq<R, C2> + SameNumberOfColumns<C, R2>,
|
||||||
|
DefaultAllocator: Allocator<U, R2, C2>,
|
||||||
F: FnMut(U) -> T,
|
F: FnMut(U) -> T,
|
||||||
{
|
{
|
||||||
let (nrows, ncols) = self.shape();
|
let (nrows, ncols) = self.shape();
|
||||||
|
@ -1371,21 +1388,25 @@ impl<T, R: Dim, C: Dim, S: StorageMut<T, R, C>> Matrix<T, R, C, S> {
|
||||||
"Unable to move from a matrix with incompatible shape."
|
"Unable to move from a matrix with incompatible shape."
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let mut md = other.manually_drop();
|
||||||
|
|
||||||
for j in 0..ncols {
|
for j in 0..ncols {
|
||||||
for i in 0..nrows {
|
for i in 0..nrows {
|
||||||
unsafe {
|
unsafe {
|
||||||
*self.get_unchecked_mut((i, j)) = f(*other.get_unchecked((j, i)));
|
*self.get_unchecked_mut((i, j)) =
|
||||||
|
f(ManuallyDrop::take(md.get_unchecked_mut((j, i))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// BEEP BEEPP! Same thing as the non-transpose method, this is UB.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: rename `apply` to `apply_mut` and `apply_into` to `apply`?
|
// TODO: rename `apply` to `apply_mut` and `apply_into` to `apply`?
|
||||||
/// Returns `self` with each of its components replaced by the result of a closure `f` applied on it.
|
/// Returns `self` with each of its components replaced by the result of a closure `f` applied on it.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn apply_into<F: FnMut(T) -> T>(mut self, f: F) -> Self {
|
pub fn apply_into<F: FnMut(T) -> T>(mut self, f: F) -> Self
|
||||||
|
where
|
||||||
|
T: Clone,
|
||||||
|
{
|
||||||
self.apply(f);
|
self.apply(f);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
@ -1406,9 +1427,10 @@ impl<T, R: Dim, C: Dim, S: StorageMut<MaybeUninit<T>, R, C>> Matrix<MaybeUninit<
|
||||||
/// Initializes this matrix with the content of another one, after applying a function to
|
/// Initializes this matrix with the content of another one, after applying a function to
|
||||||
/// the entries of the other matrix. Both must have the same shape.
|
/// the entries of the other matrix. Both must have the same shape.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn move_init_from<R2: Dim, C2: Dim, SB>(&mut self, other: Matrix<T, R2, C2, SB>)
|
pub fn move_init_from<R2: Dim, C2: Dim, SB>(&mut self, other: OMatrix<T, R2, C2>)
|
||||||
where
|
where
|
||||||
SB: Storage<T, R2, C2>,
|
SB: Storage<T, R2, C2>,
|
||||||
|
DefaultAllocator: Allocator<T, R2, C2>,
|
||||||
ShapeConstraint: SameNumberOfRows<R, R2> + SameNumberOfColumns<C, C2>,
|
ShapeConstraint: SameNumberOfRows<R, R2> + SameNumberOfColumns<C, C2>,
|
||||||
{
|
{
|
||||||
self.move_from_fn(other, MaybeUninit::new)
|
self.move_from_fn(other, MaybeUninit::new)
|
||||||
|
@ -1427,9 +1449,9 @@ impl<T, R: Dim, C: Dim, S: StorageMut<MaybeUninit<T>, R, C>> Matrix<MaybeUninit<
|
||||||
|
|
||||||
/// Initializes this matrix with the content of the transpose another one via moves.
|
/// Initializes this matrix with the content of the transpose another one via moves.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn tr_move_init_from<R2: Dim, C2: Dim, SB>(&mut self, other: Matrix<T, R2, C2, SB>)
|
pub fn tr_move_init_from<R2: Dim, C2: Dim>(&mut self, other: OMatrix<T, R2, C2>)
|
||||||
where
|
where
|
||||||
SB: Storage<T, R2, C2>,
|
DefaultAllocator: Allocator<T, R2, C2>,
|
||||||
ShapeConstraint: DimEq<R, C2> + SameNumberOfColumns<C, R2>,
|
ShapeConstraint: DimEq<R, C2> + SameNumberOfColumns<C, R2>,
|
||||||
{
|
{
|
||||||
self.tr_move_from_fn(other, MaybeUninit::new)
|
self.tr_move_from_fn(other, MaybeUninit::new)
|
||||||
|
|
|
@ -222,6 +222,7 @@ storage_impl!(SliceStorage, SliceStorageMut);
|
||||||
impl<'a, T, R: Dim, C: Dim, RStride: Dim, CStride: Dim>
|
impl<'a, T, R: Dim, C: Dim, RStride: Dim, CStride: Dim>
|
||||||
SliceStorage<'a, MaybeUninit<T>, R, C, RStride, CStride>
|
SliceStorage<'a, MaybeUninit<T>, R, C, RStride, CStride>
|
||||||
{
|
{
|
||||||
|
/// Assumes a slice storage's entries to be initialized. This operation should be near zero-cost.
|
||||||
pub unsafe fn assume_init(self) -> SliceStorage<'a, T, R, C, RStride, CStride> {
|
pub unsafe fn assume_init(self) -> SliceStorage<'a, T, R, C, RStride, CStride> {
|
||||||
SliceStorage::from_raw_parts(self.ptr as *const T, self.shape, self.strides)
|
SliceStorage::from_raw_parts(self.ptr as *const T, self.shape, self.strides)
|
||||||
}
|
}
|
||||||
|
@ -230,6 +231,7 @@ impl<'a, T, R: Dim, C: Dim, RStride: Dim, CStride: Dim>
|
||||||
impl<'a, T, R: Dim, C: Dim, RStride: Dim, CStride: Dim>
|
impl<'a, T, R: Dim, C: Dim, RStride: Dim, CStride: Dim>
|
||||||
SliceStorageMut<'a, MaybeUninit<T>, R, C, RStride, CStride>
|
SliceStorageMut<'a, MaybeUninit<T>, R, C, RStride, CStride>
|
||||||
{
|
{
|
||||||
|
/// Assumes a slice storage's entries to be initialized. This operation should be near zero-cost.
|
||||||
pub unsafe fn assume_init(self) -> SliceStorageMut<'a, T, R, C, RStride, CStride> {
|
pub unsafe fn assume_init(self) -> SliceStorageMut<'a, T, R, C, RStride, CStride> {
|
||||||
SliceStorageMut::from_raw_parts(self.ptr as *mut T, self.shape, self.strides)
|
SliceStorageMut::from_raw_parts(self.ptr as *mut T, self.shape, self.strides)
|
||||||
}
|
}
|
||||||
|
@ -760,6 +762,7 @@ impl<T, R: Dim, C: Dim, S: StorageMut<T, R, C>> Matrix<T, R, C, S> {
|
||||||
impl<'a, T, R: Dim, C: Dim, RStride: Dim, CStride: Dim>
|
impl<'a, T, R: Dim, C: Dim, RStride: Dim, CStride: Dim>
|
||||||
MatrixSlice<'a, MaybeUninit<T>, R, C, RStride, CStride>
|
MatrixSlice<'a, MaybeUninit<T>, R, C, RStride, CStride>
|
||||||
{
|
{
|
||||||
|
/// Assumes a matrix slices's entries to be initialized. This operation should be near zero-cost.
|
||||||
pub unsafe fn slice_assume_init(self) -> MatrixSlice<'a, T, R, C, RStride, CStride> {
|
pub unsafe fn slice_assume_init(self) -> MatrixSlice<'a, T, R, C, RStride, CStride> {
|
||||||
Matrix::from_data(self.data.assume_init())
|
Matrix::from_data(self.data.assume_init())
|
||||||
}
|
}
|
||||||
|
@ -768,6 +771,7 @@ impl<'a, T, R: Dim, C: Dim, RStride: Dim, CStride: Dim>
|
||||||
impl<'a, T, R: Dim, C: Dim, RStride: Dim, CStride: Dim>
|
impl<'a, T, R: Dim, C: Dim, RStride: Dim, CStride: Dim>
|
||||||
MatrixSliceMut<'a, MaybeUninit<T>, R, C, RStride, CStride>
|
MatrixSliceMut<'a, MaybeUninit<T>, R, C, RStride, CStride>
|
||||||
{
|
{
|
||||||
|
/// Assumes a matrix slices's entries to be initialized. This operation should be near zero-cost.
|
||||||
pub unsafe fn slice_assume_init(self) -> MatrixSliceMut<'a, T, R, C, RStride, CStride> {
|
pub unsafe fn slice_assume_init(self) -> MatrixSliceMut<'a, T, R, C, RStride, CStride> {
|
||||||
Matrix::from_data(self.data.assume_init())
|
Matrix::from_data(self.data.assume_init())
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
#[cfg(feature = "arbitrary")]
|
#[cfg(feature = "arbitrary")]
|
||||||
use crate::base::storage::Owned;
|
use crate::base::storage::Owned;
|
||||||
#[cfg(feature = "arbitrary")]
|
#[cfg(feature = "arbitrary")]
|
||||||
|
@ -5,20 +7,48 @@ use quickcheck::{Arbitrary, Gen};
|
||||||
|
|
||||||
use crate::base::allocator::Allocator;
|
use crate::base::allocator::Allocator;
|
||||||
use crate::base::dimension::{Dim, Dynamic};
|
use crate::base::dimension::{Dim, Dynamic};
|
||||||
use crate::base::Scalar;
|
|
||||||
use crate::base::{DefaultAllocator, OMatrix};
|
use crate::base::{DefaultAllocator, OMatrix};
|
||||||
use crate::linalg::givens::GivensRotation;
|
use crate::linalg::givens::GivensRotation;
|
||||||
|
use crate::storage::Owned;
|
||||||
use simba::scalar::ComplexField;
|
use simba::scalar::ComplexField;
|
||||||
|
|
||||||
/// A random orthogonal matrix.
|
/// A random orthogonal matrix.
|
||||||
#[derive(Clone, Debug)]
|
pub struct RandomOrthogonal<T, D: Dim = Dynamic>
|
||||||
pub struct RandomOrthogonal<T: Scalar, D: Dim = Dynamic>
|
|
||||||
where
|
where
|
||||||
DefaultAllocator: Allocator<T, D, D>,
|
DefaultAllocator: Allocator<T, D, D>,
|
||||||
{
|
{
|
||||||
m: OMatrix<T, D, D>,
|
m: OMatrix<T, D, D>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T: Copy, D: Dim> Copy for RandomOrthogonal<T, D>
|
||||||
|
where
|
||||||
|
DefaultAllocator: Allocator<T, D, D>,
|
||||||
|
Owned<T, D, D>: Copy,
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Clone, D: Dim> Clone for RandomOrthogonal<T, D>
|
||||||
|
where
|
||||||
|
DefaultAllocator: Allocator<T, D, D>,
|
||||||
|
Owned<T, D, D>: Clone,
|
||||||
|
{
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
Self { m: self.m.clone() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: fmt::Debug, D: Dim> fmt::Debug for RandomOrthogonal<T, D>
|
||||||
|
where
|
||||||
|
DefaultAllocator: Allocator<T, D, D>,
|
||||||
|
Owned<T, D, D>: fmt::Debug,
|
||||||
|
{
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
f.debug_struct("RandomOrthogonal")
|
||||||
|
.field("m", &self.m)
|
||||||
|
.finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T: ComplexField, D: Dim> RandomOrthogonal<T, D>
|
impl<T: ComplexField, D: Dim> RandomOrthogonal<T, D>
|
||||||
where
|
where
|
||||||
DefaultAllocator: Allocator<T, D, D>,
|
DefaultAllocator: Allocator<T, D, D>,
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
#[cfg(feature = "arbitrary")]
|
#[cfg(feature = "arbitrary")]
|
||||||
use crate::base::storage::Owned;
|
use crate::base::storage::Owned;
|
||||||
#[cfg(feature = "arbitrary")]
|
#[cfg(feature = "arbitrary")]
|
||||||
|
@ -5,21 +7,47 @@ use quickcheck::{Arbitrary, Gen};
|
||||||
|
|
||||||
use crate::base::allocator::Allocator;
|
use crate::base::allocator::Allocator;
|
||||||
use crate::base::dimension::{Dim, Dynamic};
|
use crate::base::dimension::{Dim, Dynamic};
|
||||||
use crate::base::Scalar;
|
|
||||||
use crate::base::{DefaultAllocator, OMatrix};
|
use crate::base::{DefaultAllocator, OMatrix};
|
||||||
|
use crate::storage::Owned;
|
||||||
use simba::scalar::ComplexField;
|
use simba::scalar::ComplexField;
|
||||||
|
|
||||||
use crate::debug::RandomOrthogonal;
|
use crate::debug::RandomOrthogonal;
|
||||||
|
|
||||||
/// A random, well-conditioned, symmetric definite-positive matrix.
|
/// A random, well-conditioned, symmetric definite-positive matrix.
|
||||||
#[derive(Clone, Debug)]
|
pub struct RandomSDP<T, D: Dim = Dynamic>
|
||||||
pub struct RandomSDP<T: Scalar, D: Dim = Dynamic>
|
|
||||||
where
|
where
|
||||||
DefaultAllocator: Allocator<T, D, D>,
|
DefaultAllocator: Allocator<T, D, D>,
|
||||||
{
|
{
|
||||||
m: OMatrix<T, D, D>,
|
m: OMatrix<T, D, D>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T: Copy, D: Dim> Copy for RandomSDP<T, D>
|
||||||
|
where
|
||||||
|
DefaultAllocator: Allocator<T, D, D>,
|
||||||
|
Owned<T, D, D>: Copy,
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Clone, D: Dim> Clone for RandomSDP<T, D>
|
||||||
|
where
|
||||||
|
DefaultAllocator: Allocator<T, D, D>,
|
||||||
|
Owned<T, D, D>: Clone,
|
||||||
|
{
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
Self { m: self.m.clone() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: fmt::Debug, D: Dim> fmt::Debug for RandomSDP<T, D>
|
||||||
|
where
|
||||||
|
DefaultAllocator: Allocator<T, D, D>,
|
||||||
|
Owned<T, D, D>: fmt::Debug,
|
||||||
|
{
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
f.debug_struct("RandomSDP").field("m", &self.m).finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T: ComplexField, D: Dim> RandomSDP<T, D>
|
impl<T: ComplexField, D: Dim> RandomSDP<T, D>
|
||||||
where
|
where
|
||||||
DefaultAllocator: Allocator<T, D, D>,
|
DefaultAllocator: Allocator<T, D, D>,
|
||||||
|
|
|
@ -279,8 +279,11 @@ impl<'a, T: Deserialize<'a>> Deserialize<'a> for DualQuaternion<T> {
|
||||||
|
|
||||||
impl<T> DualQuaternion<T> {
|
impl<T> DualQuaternion<T> {
|
||||||
// TODO: Cloning shouldn't be necessary.
|
// TODO: Cloning shouldn't be necessary.
|
||||||
fn to_vector(self) -> OVector<T, U8>where T:Clone {
|
fn to_vector(self) -> OVector<T, U8>
|
||||||
(*self.as_ref()).into()
|
where
|
||||||
|
T: Clone,
|
||||||
|
{
|
||||||
|
(self.as_ref().clone()).into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ use std::fmt;
|
||||||
use std::hash;
|
use std::hash;
|
||||||
#[cfg(feature = "abomonation-serialize")]
|
#[cfg(feature = "abomonation-serialize")]
|
||||||
use std::io::{Result as IOResult, Write};
|
use std::io::{Result as IOResult, Write};
|
||||||
use std::mem::MaybeUninit;
|
use std::mem::{ManuallyDrop, MaybeUninit};
|
||||||
|
|
||||||
#[cfg(feature = "serde-serialize-no-std")]
|
#[cfg(feature = "serde-serialize-no-std")]
|
||||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||||
|
@ -43,7 +43,6 @@ use crate::Scalar;
|
||||||
/// may have some other methods, e.g., `isometry.inverse_transform_point(&point)`. See the documentation
|
/// may have some other methods, e.g., `isometry.inverse_transform_point(&point)`. See the documentation
|
||||||
/// of said transformations for details.
|
/// of said transformations for details.
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
// TODO: figure out why #[derive(Clone, Debug)] doesn't work!
|
|
||||||
pub struct OPoint<T, D: DimName>
|
pub struct OPoint<T, D: DimName>
|
||||||
where
|
where
|
||||||
DefaultAllocator: InnerAllocator<T, D>,
|
DefaultAllocator: InnerAllocator<T, D>,
|
||||||
|
@ -78,6 +77,16 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T: fmt::Debug, D: DimName> fmt::Debug for OPoint<T, D>
|
||||||
|
where
|
||||||
|
DefaultAllocator: Allocator<T, D>,
|
||||||
|
OVector<T, D>: fmt::Debug,
|
||||||
|
{
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
f.debug_struct("OPoint").field("coords",&self.coords).finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(feature = "bytemuck")]
|
#[cfg(feature = "bytemuck")]
|
||||||
unsafe impl<T, D: DimName> bytemuck::Zeroable for OPoint<T, D>
|
unsafe impl<T, D: DimName> bytemuck::Zeroable for OPoint<T, D>
|
||||||
where
|
where
|
||||||
|
@ -185,7 +194,10 @@ where
|
||||||
/// assert_eq!(p, Point3::new(10.0, 20.0, 30.0));
|
/// assert_eq!(p, Point3::new(10.0, 20.0, 30.0));
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn apply<F: FnMut(T) -> T>(&mut self, f: F) {
|
pub fn apply<F: FnMut(T) -> T>(&mut self, f: F)
|
||||||
|
where
|
||||||
|
T: Clone,
|
||||||
|
{
|
||||||
self.coords.apply(f)
|
self.coords.apply(f)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -224,6 +236,8 @@ where
|
||||||
unsafe { res.assume_init() }
|
unsafe { res.assume_init() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Converts this point into a vector in homogeneous coordinates, i.e., appends a `1` at the
|
||||||
|
/// end of it. Unlike [`to_homogeneous`], this method does not require `T: Clone`.
|
||||||
pub fn into_homogeneous(self) -> OVector<T, DimNameSum<D, U1>>
|
pub fn into_homogeneous(self) -> OVector<T, DimNameSum<D, U1>>
|
||||||
where
|
where
|
||||||
T: One,
|
T: One,
|
||||||
|
@ -231,17 +245,15 @@ where
|
||||||
DefaultAllocator: Allocator<T, DimNameSum<D, U1>>,
|
DefaultAllocator: Allocator<T, DimNameSum<D, U1>>,
|
||||||
{
|
{
|
||||||
let mut res = OVector::<_, DimNameSum<D, U1>>::new_uninitialized();
|
let mut res = OVector::<_, DimNameSum<D, U1>>::new_uninitialized();
|
||||||
|
let mut md = self.manually_drop();
|
||||||
|
|
||||||
// TODO: maybe we can move the whole array at once? Or use `into_iter`
|
|
||||||
// to avoid double-dropping.
|
|
||||||
for i in 0..D::dim() {
|
for i in 0..D::dim() {
|
||||||
unsafe {
|
unsafe {
|
||||||
*res.get_unchecked_mut(i) = MaybeUninit::new(*self.coords.get_unchecked(i));
|
*res.get_unchecked_mut(i) =
|
||||||
|
MaybeUninit::new(ManuallyDrop::take(md.coords.get_unchecked_mut(i)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fix double drop
|
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
*res.get_unchecked_mut(D::dim()) = MaybeUninit::new(T::one());
|
*res.get_unchecked_mut(D::dim()) = MaybeUninit::new(T::one());
|
||||||
res.assume_init()
|
res.assume_init()
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use std::mem::MaybeUninit;
|
use std::mem::{ManuallyDrop, MaybeUninit};
|
||||||
|
|
||||||
#[cfg(feature = "arbitrary")]
|
#[cfg(feature = "arbitrary")]
|
||||||
use quickcheck::{Arbitrary, Gen};
|
use quickcheck::{Arbitrary, Gen};
|
||||||
|
@ -32,6 +32,13 @@ where
|
||||||
OPoint::from(OVector::new_uninitialized_generic(D::name(), Const::<1>))
|
OPoint::from(OVector::new_uninitialized_generic(D::name(), Const::<1>))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Converts `self` into a point whose coordinates must be manually dropped.
|
||||||
|
/// This should be zero-cost.
|
||||||
|
#[inline]
|
||||||
|
pub fn manually_drop(self) -> OPoint<ManuallyDrop<T>, D> {
|
||||||
|
OPoint::from(self.coords.manually_drop())
|
||||||
|
}
|
||||||
|
|
||||||
/// Creates a new point with all coordinates equal to zero.
|
/// Creates a new point with all coordinates equal to zero.
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
|
|
|
@ -91,8 +91,10 @@ impl<T, const D: usize> From<[T; D]> for Point<T, D> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T, const D: usize> From<Point<T, D>> for [T; D] where
|
impl<T, const D: usize> From<Point<T, D>> for [T; D]
|
||||||
T: Clone,{
|
where
|
||||||
|
T: Clone,
|
||||||
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from(p: Point<T, D>) -> Self {
|
fn from(p: Point<T, D>) -> Self {
|
||||||
p.coords.into()
|
p.coords.into()
|
||||||
|
|
|
@ -8,7 +8,8 @@ use simba::scalar::{ClosedAdd, ClosedMul, RealField, SubsetOf};
|
||||||
|
|
||||||
use crate::base::allocator::Allocator;
|
use crate::base::allocator::Allocator;
|
||||||
use crate::base::dimension::{DimNameAdd, DimNameSum, U1};
|
use crate::base::dimension::{DimNameAdd, DimNameSum, U1};
|
||||||
use crate::base::{Const, DefaultAllocator, OMatrix, SVector, Scalar};use crate::storage::Owned;
|
use crate::base::{Const, DefaultAllocator, OMatrix, SVector, Scalar};
|
||||||
|
use crate::storage::Owned;
|
||||||
|
|
||||||
use crate::geometry::{
|
use crate::geometry::{
|
||||||
Isometry, Point, Rotation, Similarity, SubTCategoryOf, SuperTCategoryOf, TAffine, TCategory,
|
Isometry, Point, Rotation, Similarity, SubTCategoryOf, SuperTCategoryOf, TAffine, TCategory,
|
||||||
|
@ -344,7 +345,8 @@ md_impl_all!(
|
||||||
const D;
|
const D;
|
||||||
for CA, CB;
|
for CA, CB;
|
||||||
where Const<D>: DimNameAdd<U1>, CA: TCategoryMul<CB>, CB: SubTCategoryOf<TProjective>,
|
where Const<D>: DimNameAdd<U1>, CA: TCategoryMul<CB>, CB: SubTCategoryOf<TProjective>,
|
||||||
DefaultAllocator: Allocator<T, DimNameSum<Const<D>, U1>, DimNameSum<Const<D>, U1>>;
|
DefaultAllocator: Allocator<T, DimNameSum<Const<D>, U1>, DimNameSum<Const<D>, U1>>,
|
||||||
|
Transform<T, CB, D>: Clone; // There's probably a better bound here.
|
||||||
self: Transform<T, CA, D>, rhs: Transform<T, CB, D>, Output = Transform<T, CA::Representative, D>;
|
self: Transform<T, CA, D>, rhs: Transform<T, CB, D>, Output = Transform<T, CA::Representative, D>;
|
||||||
[val val] => #[allow(clippy::suspicious_arithmetic_impl)] { self * rhs.inverse() };
|
[val val] => #[allow(clippy::suspicious_arithmetic_impl)] { self * rhs.inverse() };
|
||||||
[ref val] => #[allow(clippy::suspicious_arithmetic_impl)] { self * rhs.inverse() };
|
[ref val] => #[allow(clippy::suspicious_arithmetic_impl)] { self * rhs.inverse() };
|
||||||
|
|
|
@ -99,11 +99,9 @@ where
|
||||||
/// Creates a new sequence of D identity permutations.
|
/// Creates a new sequence of D identity permutations.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn identity_generic(dim: D) -> Self {
|
pub fn identity_generic(dim: D) -> Self {
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
len: 0,
|
len: 0,
|
||||||
ipiv: OVector::new_uninitialized_generic(dim, Const::<1>),
|
ipiv: OVector::new_uninitialized_generic(dim, Const::<1>),
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -329,7 +329,7 @@ where
|
||||||
D: Dim,
|
D: Dim,
|
||||||
DefaultAllocator: Allocator<ScalarStrategy::Value, D>,
|
DefaultAllocator: Allocator<ScalarStrategy::Value, D>,
|
||||||
{
|
{
|
||||||
matrix_(value_strategy, length.into(), Const::<1>.into())
|
matrix_(value_strategy, length.into(), U1.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<NParameters, R, C> Default for MatrixParameters<NParameters, R, C>
|
impl<NParameters, R, C> Default for MatrixParameters<NParameters, R, C>
|
||||||
|
|
|
@ -279,7 +279,7 @@ where
|
||||||
CsMatrix {
|
CsMatrix {
|
||||||
data: CsVecStorage {
|
data: CsVecStorage {
|
||||||
shape: (nrows, ncols),
|
shape: (nrows, ncols),
|
||||||
p: OVector::zeros_generic(ncols, Const::<1>),
|
p: OVector::zeros_generic(ncols, U1),
|
||||||
i,
|
i,
|
||||||
vals,
|
vals,
|
||||||
},
|
},
|
||||||
|
@ -429,7 +429,7 @@ impl<T: Scalar, R: Dim, C: Dim, S: CsStorage<T, R, C>> CsMatrix<T, R, C, S> {
|
||||||
|
|
||||||
let nvals = self.len();
|
let nvals = self.len();
|
||||||
let mut res = CsMatrix::new_uninitialized_generic(ncols, nrows, nvals);
|
let mut res = CsMatrix::new_uninitialized_generic(ncols, nrows, nvals);
|
||||||
let mut workspace = Vector::zeros_generic(nrows, Const::<1>);
|
let mut workspace = Vector::zeros_generic(nrows, U1);
|
||||||
|
|
||||||
// Compute p.
|
// Compute p.
|
||||||
for i in 0..nvals {
|
for i in 0..nvals {
|
||||||
|
@ -473,7 +473,7 @@ where
|
||||||
// Size = R
|
// Size = R
|
||||||
let nrows = self.data.shape().0;
|
let nrows = self.data.shape().0;
|
||||||
let mut workspace =
|
let mut workspace =
|
||||||
unsafe { crate::unimplemented_or_uninitialized_generic!(nrows, Const::<1>) };
|
unsafe { crate::unimplemented_or_uninitialized_generic!(nrows, U1) };
|
||||||
self.sort_with_workspace(workspace.as_mut_slice());
|
self.sort_with_workspace(workspace.as_mut_slice());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -49,9 +49,9 @@ where
|
||||||
|
|
||||||
// Workspaces.
|
// Workspaces.
|
||||||
let work_x =
|
let work_x =
|
||||||
unsafe { crate::unimplemented_or_uninitialized_generic!(m.data.shape().0, Const::<1>) };
|
unsafe { crate::unimplemented_or_uninitialized_generic!(m.data.shape().0, U1) };
|
||||||
let work_c =
|
let work_c =
|
||||||
unsafe { crate::unimplemented_or_uninitialized_generic!(m.data.shape().1, Const::<1>) };
|
unsafe { crate::unimplemented_or_uninitialized_generic!(m.data.shape().1, U1) };
|
||||||
let mut original_p = m.data.p.as_slice().to_vec();
|
let mut original_p = m.data.p.as_slice().to_vec();
|
||||||
original_p.push(m.data.i.len());
|
original_p.push(m.data.i.len());
|
||||||
|
|
||||||
|
@ -295,7 +295,7 @@ where
|
||||||
let (nrows, ncols) = m.data.shape();
|
let (nrows, ncols) = m.data.shape();
|
||||||
let mut rows = Vec::with_capacity(m.len());
|
let mut rows = Vec::with_capacity(m.len());
|
||||||
let mut cols =
|
let mut cols =
|
||||||
unsafe { crate::unimplemented_or_uninitialized_generic!(m.data.shape().0, Const::<1>) };
|
unsafe { crate::unimplemented_or_uninitialized_generic!(m.data.shape().0, U1) };
|
||||||
let mut marks = Vec::new();
|
let mut marks = Vec::new();
|
||||||
|
|
||||||
// NOTE: the following will actually compute the non-zero pattern of
|
// NOTE: the following will actually compute the non-zero pattern of
|
||||||
|
|
|
@ -148,7 +148,7 @@ where
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut res = CsMatrix::new_uninitialized_generic(nrows1, ncols2, self.len() + rhs.len());
|
let mut res = CsMatrix::new_uninitialized_generic(nrows1, ncols2, self.len() + rhs.len());
|
||||||
let mut workspace = OVector::<T, R1>::zeros_generic(nrows1, Const::<1>);
|
let mut workspace = OVector::<T, R1>::zeros_generic(nrows1, U1);
|
||||||
let mut nz = 0;
|
let mut nz = 0;
|
||||||
|
|
||||||
for j in 0..ncols2.value() {
|
for j in 0..ncols2.value() {
|
||||||
|
@ -241,9 +241,9 @@ where
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut res = CsMatrix::new_uninitialized_generic(nrows1, ncols2, self.len() + rhs.len());
|
let mut res = CsMatrix::new_uninitialized_generic(nrows1, ncols2, self.len() + rhs.len());
|
||||||
let mut timestamps = OVector::zeros_generic(nrows1, Const::<1>);
|
let mut timestamps = OVector::zeros_generic(nrows1, U1);
|
||||||
let mut workspace =
|
let mut workspace =
|
||||||
unsafe { crate::unimplemented_or_uninitialized_generic!(nrows1, Const::<1>) };
|
unsafe { crate::unimplemented_or_uninitialized_generic!(nrows1, U1) };
|
||||||
let mut nz = 0;
|
let mut nz = 0;
|
||||||
|
|
||||||
for j in 0..ncols2.value() {
|
for j in 0..ncols2.value() {
|
||||||
|
|
|
@ -153,7 +153,7 @@ impl<T: RealField, D: Dim, S: CsStorage<T, D, D>> CsMatrix<T, D, D, S> {
|
||||||
// We sort the reach so the result matrix has sorted indices.
|
// We sort the reach so the result matrix has sorted indices.
|
||||||
reach.sort_unstable();
|
reach.sort_unstable();
|
||||||
let mut workspace =
|
let mut workspace =
|
||||||
unsafe { crate::unimplemented_or_uninitialized_generic!(b.data.shape().0, Const::<1>) };
|
unsafe { crate::unimplemented_or_uninitialized_generic!(b.data.shape().0, U1) };
|
||||||
|
|
||||||
for i in reach.iter().cloned() {
|
for i in reach.iter().cloned() {
|
||||||
workspace[i] = T::zero();
|
workspace[i] = T::zero();
|
||||||
|
@ -191,7 +191,7 @@ impl<T: RealField, D: Dim, S: CsStorage<T, D, D>> CsMatrix<T, D, D, S> {
|
||||||
|
|
||||||
// Copy the result into a sparse vector.
|
// Copy the result into a sparse vector.
|
||||||
let mut result =
|
let mut result =
|
||||||
CsVector::new_uninitialized_generic(b.data.shape().0, Const::<1>, reach.len());
|
CsVector::new_uninitialized_generic(b.data.shape().0, U1, reach.len());
|
||||||
|
|
||||||
for (i, val) in reach.iter().zip(result.data.vals.iter_mut()) {
|
for (i, val) in reach.iter().zip(result.data.vals.iter_mut()) {
|
||||||
*val = workspace[*i];
|
*val = workspace[*i];
|
||||||
|
@ -255,7 +255,7 @@ impl<T: RealField, D: Dim, S: CsStorage<T, D, D>> CsMatrix<T, D, D, S> {
|
||||||
S2: CsStorage<T, D2>,
|
S2: CsStorage<T, D2>,
|
||||||
DefaultAllocator: Allocator<bool, D>,
|
DefaultAllocator: Allocator<bool, D>,
|
||||||
{
|
{
|
||||||
let mut visited = OVector::repeat_generic(self.data.shape().1, Const::<1>, false);
|
let mut visited = OVector::repeat_generic(self.data.shape().1, U1, false);
|
||||||
let mut stack = Vec::new();
|
let mut stack = Vec::new();
|
||||||
|
|
||||||
for irow in b.data.column_row_indices(0) {
|
for irow in b.data.column_row_indices(0) {
|
||||||
|
|
|
@ -180,11 +180,11 @@ macro_rules! generate_matrix_sanity_test {
|
||||||
|
|
||||||
// Test all fixed-size matrices with row/col dimensions up to 3
|
// Test all fixed-size matrices with row/col dimensions up to 3
|
||||||
generate_matrix_sanity_test!(test_matrix_u0_u0, Const::<0>, Const::<0>);
|
generate_matrix_sanity_test!(test_matrix_u0_u0, Const::<0>, Const::<0>);
|
||||||
generate_matrix_sanity_test!(test_matrix_u1_u0, Const::<1>, Const::<0>);
|
generate_matrix_sanity_test!(test_matrix_u1_u0, U1, Const::<0>);
|
||||||
generate_matrix_sanity_test!(test_matrix_u0_u1, Const::<0>, Const::<1>);
|
generate_matrix_sanity_test!(test_matrix_u0_u1, Const::<0>, U1);
|
||||||
generate_matrix_sanity_test!(test_matrix_u1_u1, Const::<1>, Const::<1>);
|
generate_matrix_sanity_test!(test_matrix_u1_u1, U1, U1);
|
||||||
generate_matrix_sanity_test!(test_matrix_u2_u1, Const::<2>, Const::<1>);
|
generate_matrix_sanity_test!(test_matrix_u2_u1, Const::<2>, U1);
|
||||||
generate_matrix_sanity_test!(test_matrix_u1_u2, Const::<1>, Const::<2>);
|
generate_matrix_sanity_test!(test_matrix_u1_u2, U1, Const::<2>);
|
||||||
generate_matrix_sanity_test!(test_matrix_u2_u2, Const::<2>, Const::<2>);
|
generate_matrix_sanity_test!(test_matrix_u2_u2, Const::<2>, Const::<2>);
|
||||||
generate_matrix_sanity_test!(test_matrix_u3_u2, Const::<3>, Const::<2>);
|
generate_matrix_sanity_test!(test_matrix_u3_u2, Const::<3>, Const::<2>);
|
||||||
generate_matrix_sanity_test!(test_matrix_u2_u3, Const::<2>, Const::<3>);
|
generate_matrix_sanity_test!(test_matrix_u2_u3, Const::<2>, Const::<3>);
|
||||||
|
|
Loading…
Reference in New Issue