Checkpoint #9

This commit is contained in:
Violeta Hernández 2021-07-16 23:17:56 -05:00
parent c3f869e017
commit 87fe2b30df
34 changed files with 511 additions and 323 deletions

View File

@ -311,7 +311,7 @@ impl From<SparsityPatternFormatError> for SparseFormatError {
} }
impl fmt::Display for SparsityPatternFormatError { impl fmt::Display for SparsityPatternFormatError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self { match self {
SparsityPatternFormatError::InvalidOffsetArrayLength => { SparsityPatternFormatError::InvalidOffsetArrayLength => {
write!(f, "Length of offset array is not equal to (major_dim + 1).") write!(f, "Length of offset array is not equal to (major_dim + 1).")

View File

@ -798,7 +798,7 @@ where
impl<T, R1: Dim, C1: Dim, S: StorageMut<MaybeUninit<T>, R1, C1>> Matrix<MaybeUninit<T>, R1, C1, S> impl<T, R1: Dim, C1: Dim, S: StorageMut<MaybeUninit<T>, R1, C1>> Matrix<MaybeUninit<T>, R1, C1, S>
where where
T: Scalar + Zero + One + ClosedAdd + ClosedMul, T: Scalar + Zero + One + ClosedAdd + ClosedMul,
DefaultAllocator: Allocator<T, R1, C1>, // DefaultAllocator: Allocator<T, R1, C1>,
{ {
/// Computes `alpha * a * b`, where `a` and `b` are matrices, and `alpha` is /// Computes `alpha * a * b`, where `a` and `b` are matrices, and `alpha` is
/// a scalar. /// a scalar.

View File

@ -146,7 +146,7 @@ macro_rules! component_binop_impl(
); );
/// # Componentwise operations /// # Componentwise operations
impl<T: Scalar, R1: Dim, C1: Dim, SA: Storage<T, R1, C1>> Matrix<T, R1, C1, SA> { impl<T:Scalar, R1: Dim, C1: Dim, SA: Storage<T, R1, C1>> Matrix<T, R1, C1, SA> {
component_binop_impl!( component_binop_impl!(
component_mul, component_mul_mut, component_mul_assign, cmpy, ClosedMul.mul.mul_assign, component_mul, component_mul_mut, component_mul_assign, cmpy, ClosedMul.mul.mul_assign,
r" r"

View File

@ -705,7 +705,10 @@ where
{ {
/// Creates a new uninitialized matrix or vector. /// Creates a new uninitialized matrix or vector.
#[inline] #[inline]
pub fn new_uninitialized(nrows: usize, ncols: usize) -> OMatrix<MaybeUninit<T>, Dynamic, Dynamic> { pub fn new_uninitialized(
nrows: usize,
ncols: usize,
) -> OMatrix<MaybeUninit<T>, Dynamic, Dynamic> {
Self::new_uninitialized_generic(Dynamic::new(nrows), Dynamic::new(ncols)) Self::new_uninitialized_generic(Dynamic::new(nrows), Dynamic::new(ncols))
} }
} }
@ -899,13 +902,11 @@ where
} }
#[cfg(feature = "arbitrary")] #[cfg(feature = "arbitrary")]
impl<T, R, C> Arbitrary for OMatrix<T, R, C> impl<T, R: Dim, C: Dim> Arbitrary for OMatrix<T, R, C>
where where
R: Dim,
C: Dim,
T: Arbitrary + Send, T: Arbitrary + Send,
DefaultAllocator: Allocator<T, R, C>, DefaultAllocator: Allocator<T, R, C>,
Owned<T, R, C>: Clone + Send, Owned<T, R, C>: Clone+Send,
{ {
#[inline] #[inline]
fn arbitrary(g: &mut Gen) -> Self { fn arbitrary(g: &mut Gen) -> Self {

View File

@ -82,7 +82,7 @@ where
} }
} }
impl<'a, T: Scalar, R: Dim, C: Dim, S: Storage<T, R, C>> IntoIterator for &'a Matrix<T, R, C, S> { impl<'a, T, R: Dim, C: Dim, S: Storage<T, R, C>> IntoIterator for &'a Matrix<T, R, C, S> {
type Item = &'a T; type Item = &'a T;
type IntoIter = MatrixIter<'a, T, R, C, S>; type IntoIter = MatrixIter<'a, T, R, C, S>;
@ -92,9 +92,7 @@ impl<'a, T: Scalar, R: Dim, C: Dim, S: Storage<T, R, C>> IntoIterator for &'a Ma
} }
} }
impl<'a, T: Scalar, R: Dim, C: Dim, S: StorageMut<T, R, C>> IntoIterator impl<'a, T, R: Dim, C: Dim, S: StorageMut<T, R, C>> IntoIterator for &'a mut Matrix<T, R, C, S> {
for &'a mut Matrix<T, R, C, S>
{
type Item = &'a mut T; type Item = &'a mut T;
type IntoIter = MatrixIterMut<'a, T, R, C, S>; type IntoIter = MatrixIterMut<'a, T, R, C, S>;
@ -111,11 +109,13 @@ impl<T, const D: usize> From<[T; D]> for SVector<T, D> {
} }
} }
impl<T: Clone, const D: usize> From<SVector<T, D>> for [T; D] { impl<T, const D: usize> From<SVector<T, D>> for [T; D] {
#[inline] #[inline]
fn from(vec: SVector<T, D>) -> Self { fn from(vec: SVector<T, D>) -> Self {
// TODO: unfortunately, we must clone because we can move out of an array. // TODO: unfortunately, we must clone because we can move out of an array.
vec.data.0[0].clone()
// Counterpoint: this seems to work?
vec.data.0[0]
} }
} }
@ -125,7 +125,7 @@ where
{ {
#[inline] #[inline]
fn from(arr: [T; D]) -> Self { fn from(arr: [T; D]) -> Self {
SVector::<T, D>::from(arr).transpose() SVector::<T, D>::from(arr).transpose_into()
} }
} }

View File

@ -8,7 +8,7 @@ use std::ops::{Deref, DerefMut};
use crate::base::dimension::{U1, U2, U3, U4, U5, U6}; use crate::base::dimension::{U1, U2, U3, U4, U5, U6};
use crate::base::storage::{ContiguousStorage, ContiguousStorageMut}; use crate::base::storage::{ContiguousStorage, ContiguousStorageMut};
use crate::base::{Matrix, Scalar}; use crate::base::Matrix;
/* /*
* *
@ -23,7 +23,7 @@ macro_rules! coords_impl(
#[repr(C)] #[repr(C)]
#[derive(Eq, PartialEq, Clone, Hash, Debug, Copy)] #[derive(Eq, PartialEq, Clone, Hash, Debug, Copy)]
#[cfg_attr(feature = "serde-serialize-no-std", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde-serialize-no-std", derive(Serialize, Deserialize))]
pub struct $T<T: Scalar> { pub struct $T<T> {
$(pub $comps: T),* $(pub $comps: T),*
} }
} }
@ -31,7 +31,7 @@ macro_rules! coords_impl(
macro_rules! deref_impl( macro_rules! deref_impl(
($R: ty, $C: ty; $Target: ident) => { ($R: ty, $C: ty; $Target: ident) => {
impl<T: Scalar, S> Deref for Matrix<T, $R, $C, S> impl<T, S> Deref for Matrix<T, $R, $C, S>
where S: ContiguousStorage<T, $R, $C> { where S: ContiguousStorage<T, $R, $C> {
type Target = $Target<T>; type Target = $Target<T>;
@ -41,7 +41,7 @@ macro_rules! deref_impl(
} }
} }
impl<T: Scalar, S> DerefMut for Matrix<T, $R, $C, S> impl<T, S> DerefMut for Matrix<T, $R, $C, S>
where S: ContiguousStorageMut<T, $R, $C> { where S: ContiguousStorageMut<T, $R, $C> {
#[inline] #[inline]
fn deref_mut(&mut self) -> &mut Self::Target { fn deref_mut(&mut self) -> &mut Self::Target {

View File

@ -70,7 +70,7 @@ impl<T: Scalar + Zero, R: Dim, C: Dim, S: Storage<T, R, C>> Matrix<T, R, C, S> {
for (destination, source) in irows.clone().enumerate() { for (destination, source) in irows.clone().enumerate() {
unsafe { unsafe {
*res.vget_unchecked_mut(destination) = *res.vget_unchecked_mut(destination) =
MaybeUninit::new(src.vget_unchecked(*source).inlined_clone()); MaybeUninit::new(src.vget_unchecked(*source).clone());
} }
} }
} }
@ -106,11 +106,12 @@ impl<T: Scalar + Zero, R: Dim, C: Dim, S: Storage<T, R, C>> Matrix<T, R, C, S> {
} }
/// # Set rows, columns, and diagonal /// # Set rows, columns, and diagonal
impl<T: Scalar, R: Dim, C: Dim, S: StorageMut<T, R, C>> Matrix<T, R, C, S> { impl<T, R: Dim, C: Dim, S: StorageMut<T, R, C>> Matrix<T, R, C, S> {
/// Fills the diagonal of this matrix with the content of the given vector. /// Fills the diagonal of this matrix with the content of the given vector.
#[inline] #[inline]
pub fn set_diagonal<R2: Dim, S2>(&mut self, diag: &Vector<T, R2, S2>) pub fn set_diagonal<R2: Dim, S2>(&mut self, diag: &Vector<T, R2, S2>)
where where
T: Clone,
R: DimMin<C>, R: DimMin<C>,
S2: Storage<T, R2>, S2: Storage<T, R2>,
ShapeConstraint: DimEq<DimMinimum<R, C>, R2>, ShapeConstraint: DimEq<DimMinimum<R, C>, R2>,
@ -120,7 +121,7 @@ impl<T: Scalar, R: Dim, C: Dim, S: StorageMut<T, R, C>> Matrix<T, R, C, S> {
assert_eq!(diag.len(), min_nrows_ncols, "Mismatched dimensions."); assert_eq!(diag.len(), min_nrows_ncols, "Mismatched dimensions.");
for i in 0..min_nrows_ncols { for i in 0..min_nrows_ncols {
unsafe { *self.get_unchecked_mut((i, i)) = diag.vget_unchecked(i).inlined_clone() } unsafe { *self.get_unchecked_mut((i, i)) = diag.vget_unchecked(i).clone() }
} }
} }
@ -143,6 +144,7 @@ impl<T: Scalar, R: Dim, C: Dim, S: StorageMut<T, R, C>> Matrix<T, R, C, S> {
#[inline] #[inline]
pub fn set_row<C2: Dim, S2>(&mut self, i: usize, row: &RowVector<T, C2, S2>) pub fn set_row<C2: Dim, S2>(&mut self, i: usize, row: &RowVector<T, C2, S2>)
where where
T: Clone,
S2: Storage<T, U1, C2>, S2: Storage<T, U1, C2>,
ShapeConstraint: SameNumberOfColumns<C, C2>, ShapeConstraint: SameNumberOfColumns<C, C2>,
{ {
@ -153,6 +155,7 @@ impl<T: Scalar, R: Dim, C: Dim, S: StorageMut<T, R, C>> Matrix<T, R, C, S> {
#[inline] #[inline]
pub fn set_column<R2: Dim, S2>(&mut self, i: usize, column: &Vector<T, R2, S2>) pub fn set_column<R2: Dim, S2>(&mut self, i: usize, column: &Vector<T, R2, S2>)
where where
T: Clone,
S2: Storage<T, R2, U1>, S2: Storage<T, R2, U1>,
ShapeConstraint: SameNumberOfRows<R, R2>, ShapeConstraint: SameNumberOfRows<R, R2>,
{ {
@ -270,7 +273,7 @@ impl<T, R: Dim, C: Dim, S: StorageMut<T, R, C>> Matrix<T, R, C, S> {
} }
} }
impl<T: Scalar, D: Dim, S: StorageMut<T, D, D>> Matrix<T, D, D, S> { impl<T: Clone, D: Dim, S: StorageMut<T, D, D>> Matrix<T, D, D, S> {
/// Copies the upper-triangle of this matrix to its lower-triangular part. /// Copies the upper-triangle of this matrix to its lower-triangular part.
/// ///
/// This makes the matrix symmetric. Panics if the matrix is not square. /// This makes the matrix symmetric. Panics if the matrix is not square.
@ -281,7 +284,7 @@ impl<T: Scalar, D: Dim, S: StorageMut<T, D, D>> Matrix<T, D, D, S> {
for j in 0..dim { for j in 0..dim {
for i in j + 1..dim { for i in j + 1..dim {
unsafe { unsafe {
*self.get_unchecked_mut((i, j)) = self.get_unchecked((j, i)).inlined_clone(); *self.get_unchecked_mut((i, j)) = self.get_unchecked((j, i)).clone();
} }
} }
} }
@ -296,7 +299,7 @@ impl<T: Scalar, D: Dim, S: StorageMut<T, D, D>> Matrix<T, D, D, S> {
for j in 1..self.ncols() { for j in 1..self.ncols() {
for i in 0..j { for i in 0..j {
unsafe { unsafe {
*self.get_unchecked_mut((i, j)) = self.get_unchecked((j, i)).inlined_clone(); *self.get_unchecked_mut((i, j)) = self.get_unchecked((j, i)).clone();
} }
} }
} }
@ -304,7 +307,7 @@ impl<T: Scalar, D: Dim, S: StorageMut<T, D, D>> Matrix<T, D, D, S> {
} }
/// # In-place swapping /// # In-place swapping
impl<T: Scalar, R: Dim, C: Dim, S: StorageMut<T, R, C>> Matrix<T, R, C, S> { impl<T, R: Dim, C: Dim, S: StorageMut<T, R, C>> Matrix<T, R, C, S> {
/// Swaps two rows in-place. /// Swaps two rows in-place.
#[inline] #[inline]
pub fn swap_rows(&mut self, irow1: usize, irow2: usize) { pub fn swap_rows(&mut self, irow1: usize, irow2: usize) {
@ -340,7 +343,7 @@ impl<T: Scalar, R: Dim, C: Dim, S: StorageMut<T, R, C>> Matrix<T, R, C, S> {
* *
*/ */
/// # Rows and columns removal /// # Rows and columns removal
impl<T: Scalar, R: Dim, C: Dim, S: Storage<T, R, C>> Matrix<T, R, C, S> { impl<T: Clone, R: Dim, C: Dim, S: Storage<T, R, C>> Matrix<T, R, C, S> {
/* /*
* *
* Column removal. * Column removal.
@ -569,7 +572,7 @@ impl<T: Scalar, R: Dim, C: Dim, S: Storage<T, R, C>> Matrix<T, R, C, S> {
} }
/// # Rows and columns insertion /// # Rows and columns insertion
impl<T: Scalar, R: Dim, C: Dim, S: Storage<T, R, C>> Matrix<T, R, C, S> { impl<T: Clone, R: Dim, C: Dim, S: Storage<T, R, C>> Matrix<T, R, C, S> {
/* /*
* *
* Columns insertion. * Columns insertion.
@ -738,7 +741,7 @@ impl<T: Scalar, R: Dim, C: Dim, S: Storage<T, R, C>> Matrix<T, R, C, S> {
} }
/// # Resizing and reshaping /// # Resizing and reshaping
impl<T: Scalar, R: Dim, C: Dim, S: Storage<T, R, C>> Matrix<T, R, C, S> { impl<T: Clone, R: Dim, C: Dim, S: Storage<T, R, C>> Matrix<T, R, C, S> {
/// Resizes this matrix so that it contains `new_nrows` rows and `new_ncols` columns. /// Resizes this matrix so that it contains `new_nrows` rows and `new_ncols` columns.
/// ///
/// The values are copied such that `self[(i, j)] == result[(i, j)]`. If the result has more /// The values are copied such that `self[(i, j)] == result[(i, j)]`. If the result has more
@ -846,7 +849,7 @@ impl<T: Scalar, R: Dim, C: Dim, S: Storage<T, R, C>> Matrix<T, R, C, S> {
} }
if new_ncols.value() > ncols { if new_ncols.value() > ncols {
res.columns_range_mut(ncols..).fill(val.inlined_clone()); res.columns_range_mut(ncols..).fill(val.clone());
} }
if new_nrows.value() > nrows { if new_nrows.value() > nrows {
@ -928,7 +931,7 @@ impl<T: Scalar, R: Dim, C: Dim, S: Storage<T, R, C>> Matrix<T, R, C, S> {
/// # In-place resizing /// # In-place resizing
#[cfg(any(feature = "std", feature = "alloc"))] #[cfg(any(feature = "std", feature = "alloc"))]
impl<T: Scalar> OMatrix<T, Dynamic, Dynamic> { impl<T: Clone> OMatrix<T, Dynamic, Dynamic> {
/// Resizes this matrix in-place. /// Resizes this matrix in-place.
/// ///
/// The values are copied such that `self[(i, j)] == result[(i, j)]`. If the result has more /// The values are copied such that `self[(i, j)] == result[(i, j)]`. If the result has more
@ -948,7 +951,7 @@ impl<T: Scalar> OMatrix<T, Dynamic, Dynamic> {
} }
#[cfg(any(feature = "std", feature = "alloc"))] #[cfg(any(feature = "std", feature = "alloc"))]
impl<T: Scalar, C: Dim> OMatrix<T, Dynamic, C> impl<T: Clone, C: Dim> OMatrix<T, Dynamic, C>
where where
DefaultAllocator: Allocator<T, Dynamic, C>, DefaultAllocator: Allocator<T, Dynamic, C>,
{ {
@ -971,7 +974,7 @@ where
} }
#[cfg(any(feature = "std", feature = "alloc"))] #[cfg(any(feature = "std", feature = "alloc"))]
impl<T: Scalar, R: Dim> OMatrix<T, R, Dynamic> impl<T: Clone, R: Dim> OMatrix<T, R, Dynamic>
where where
DefaultAllocator: Allocator<T, R, Dynamic>, DefaultAllocator: Allocator<T, R, Dynamic>,
{ {
@ -993,13 +996,7 @@ where
} }
} }
unsafe fn compress_rows<T: Scalar>( unsafe fn compress_rows<T>(data: &mut [T], nrows: usize, ncols: usize, i: usize, nremove: usize) {
data: &mut [T],
nrows: usize,
ncols: usize,
i: usize,
nremove: usize,
) {
let new_nrows = nrows - nremove; let new_nrows = nrows - nremove;
if new_nrows == 0 || ncols == 0 { if new_nrows == 0 || ncols == 0 {
@ -1032,13 +1029,7 @@ unsafe fn compress_rows<T: Scalar>(
// Moves entries of a matrix buffer to make place for `ninsert` emty rows starting at the `i-th` row index. // Moves entries of a matrix buffer to make place for `ninsert` emty rows starting at the `i-th` row index.
// The `data` buffer is assumed to contained at least `(nrows + ninsert) * ncols` elements. // The `data` buffer is assumed to contained at least `(nrows + ninsert) * ncols` elements.
unsafe fn extend_rows<T: Scalar>( unsafe fn extend_rows<T>(data: &mut [T], nrows: usize, ncols: usize, i: usize, ninsert: usize) {
data: &mut [T],
nrows: usize,
ncols: usize,
i: usize,
ninsert: usize,
) {
let new_nrows = nrows + ninsert; let new_nrows = nrows + ninsert;
if new_nrows == 0 || ncols == 0 { if new_nrows == 0 || ncols == 0 {
@ -1070,7 +1061,6 @@ unsafe fn extend_rows<T: Scalar>(
#[cfg(any(feature = "std", feature = "alloc"))] #[cfg(any(feature = "std", feature = "alloc"))]
impl<T, R, S> Extend<T> for Matrix<T, R, Dynamic, S> impl<T, R, S> Extend<T> for Matrix<T, R, Dynamic, S>
where where
T: Scalar,
R: Dim, R: Dim,
S: Extend<T>, S: Extend<T>,
{ {
@ -1118,7 +1108,6 @@ where
#[cfg(any(feature = "std", feature = "alloc"))] #[cfg(any(feature = "std", feature = "alloc"))]
impl<T, S> Extend<T> for Matrix<T, Dynamic, U1, S> impl<T, S> Extend<T> for Matrix<T, Dynamic, U1, S>
where where
T: Scalar,
S: Extend<T>, S: Extend<T>,
{ {
/// Extend the number of rows of a `Vector` with elements /// Extend the number of rows of a `Vector` with elements
@ -1137,12 +1126,9 @@ where
} }
#[cfg(any(feature = "std", feature = "alloc"))] #[cfg(any(feature = "std", feature = "alloc"))]
impl<T, R, S, RV, SV> Extend<Vector<T, RV, SV>> for Matrix<T, R, Dynamic, S> impl<T, R: Dim, S, RV: Dim, SV> Extend<Vector<T, RV, SV>> for Matrix<T, R, Dynamic, S>
where where
T: Scalar,
R: Dim,
S: Extend<Vector<T, RV, SV>>, S: Extend<Vector<T, RV, SV>>,
RV: Dim,
SV: Storage<T, RV>, SV: Storage<T, RV>,
ShapeConstraint: SameNumberOfRows<R, RV>, ShapeConstraint: SameNumberOfRows<R, RV>,
{ {

View File

@ -720,6 +720,33 @@ 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.
pub fn transpose_into(self) -> OMatrix<T, C, R>
where
DefaultAllocator: Allocator<T, C, R>,
{
let (nrows, ncols) = self.data.shape();
let mut res = OMatrix::new_uninitialized_generic(ncols, nrows);
let (nrows, ncols) = res.shape();
// TODO: optimize that.
for i in 0..nrows {
for j in 0..ncols {
unsafe {
*res.get_unchecked_mut((j, i)) = MaybeUninit::new(*self.get_unchecked((i, j)));
}
}
}
// BEEP! BEEP! There's a double drop here that needs to be fixed.
unsafe {
// Safety: res is now fully initialized due to the guarantees of transpose_to.
res.assume_init()
}
}
} }
/// # Elementwise mapping and folding /// # Elementwise mapping and folding
@ -728,13 +755,12 @@ impl<T, R: Dim, C: Dim, S: Storage<T, R, C>> Matrix<T, R, C, S> {
/// Returns a matrix containing the result of `f` applied to each of its entries. /// Returns a matrix containing the result of `f` applied to each of its entries.
#[inline] #[inline]
#[must_use] #[must_use]
pub fn map<T2: Clone, F: FnMut(T) -> T2>(&self, mut f: F) -> OMatrix<T2, R, C> pub fn map<T2, F: FnMut(T) -> T2>(&self, mut f: F) -> OMatrix<T2, R, C>
where where
T: Clone, T: Clone,
DefaultAllocator: Allocator<T2, R, C>, DefaultAllocator: Allocator<T2, R, C>,
{ {
let (nrows, ncols) = self.data.shape(); let (nrows, ncols) = self.data.shape();
let mut res = OMatrix::new_uninitialized_generic(nrows, ncols); let mut res = OMatrix::new_uninitialized_generic(nrows, ncols);
for j in 0..ncols.value() { for j in 0..ncols.value() {
@ -1283,6 +1309,8 @@ impl<T, R: Dim, C: Dim, S: StorageMut<T, R, C>> Matrix<T, R, C, S> {
} }
} }
} }
// 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.
@ -1359,6 +1387,8 @@ impl<T, R: Dim, C: Dim, S: StorageMut<T, R, C>> Matrix<T, R, C, S> {
} }
} }
} }
// 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`?
@ -1370,6 +1400,51 @@ impl<T, R: Dim, C: Dim, S: StorageMut<T, R, C>> Matrix<T, R, C, S> {
} }
} }
impl<T, R: Dim, C: Dim, S: StorageMut<MaybeUninit<T>, R, C>> Matrix<MaybeUninit<T>, R, C, S> {
/// Initializes this matrix with the content of another one via clones. Both must have the same shape.
#[inline]
pub fn copy_init_from<R2: Dim, C2: Dim, SB>(&mut self, other: &Matrix<T, R2, C2, SB>)
where
T: Clone,
SB: Storage<T, R2, C2>,
ShapeConstraint: SameNumberOfRows<R, R2> + SameNumberOfColumns<C, C2>,
{
self.copy_from_fn(other, |e| MaybeUninit::new(e.clone()))
}
/// 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.
#[inline]
pub fn move_init_from<R2: Dim, C2: Dim, SB>(&mut self, other: Matrix<T, R2, C2, SB>)
where
SB: Storage<T, R2, C2>,
ShapeConstraint: SameNumberOfRows<R, R2> + SameNumberOfColumns<C, C2>,
{
self.move_from_fn(other, MaybeUninit::new)
}
/// Initializes this matrix with the content of the transpose another one via clones.
#[inline]
pub fn tr_copy_init_from<R2: Dim, C2: Dim, SB>(&mut self, other: &Matrix<T, R2, C2, SB>)
where
T: Clone,
SB: Storage<T, R2, C2>,
ShapeConstraint: DimEq<R, C2> + SameNumberOfColumns<C, R2>,
{
self.tr_copy_from_fn(other, |e| MaybeUninit::new(e.clone()))
}
/// Initializes this matrix with the content of the transpose another one via moves.
#[inline]
pub fn tr_move_init_from<R2: Dim, C2: Dim, SB>(&mut self, other: Matrix<T, R2, C2, SB>)
where
SB: Storage<T, R2, C2>,
ShapeConstraint: DimEq<R, C2> + SameNumberOfColumns<C, R2>,
{
self.tr_move_from_fn(other, MaybeUninit::new)
}
}
impl<T, D: Dim, S: Storage<T, D>> Vector<T, D, S> { impl<T, D: Dim, S: Storage<T, D>> Vector<T, D, S> {
/// Gets a reference to the i-th element of this column vector without bound checking. /// Gets a reference to the i-th element of this column vector without bound checking.
#[inline] #[inline]
@ -2185,9 +2260,8 @@ impl<T: SimdComplexField, R: Dim, C: Dim, S: Storage<T, R, C>> Matrix<T, R, C, S
} }
} }
impl<T, R: Dim, C: Dim, S> AbsDiffEq for Unit<Matrix<T, R, C, S>> impl<T: AbsDiffEq, R: Dim, C: Dim, S> AbsDiffEq for Unit<Matrix<T, R, C, S>>
where where
T: Scalar + AbsDiffEq,
S: Storage<T, R, C>, S: Storage<T, R, C>,
T::Epsilon: Copy, T::Epsilon: Copy,
{ {
@ -2204,9 +2278,8 @@ where
} }
} }
impl<T, R: Dim, C: Dim, S> RelativeEq for Unit<Matrix<T, R, C, S>> impl<T: RelativeEq, R: Dim, C: Dim, S> RelativeEq for Unit<Matrix<T, R, C, S>>
where where
T: Scalar + RelativeEq,
S: Storage<T, R, C>, S: Storage<T, R, C>,
T::Epsilon: Copy, T::Epsilon: Copy,
{ {
@ -2227,9 +2300,8 @@ where
} }
} }
impl<T, R: Dim, C: Dim, S> UlpsEq for Unit<Matrix<T, R, C, S>> impl<T: UlpsEq, R: Dim, C: Dim, S> UlpsEq for Unit<Matrix<T, R, C, S>>
where where
T: Scalar + UlpsEq,
S: Storage<T, R, C>, S: Storage<T, R, C>,
T::Epsilon: Copy, T::Epsilon: Copy,
{ {
@ -2244,9 +2316,8 @@ where
} }
} }
impl<T, R: Dim, C: Dim, S> Hash for Matrix<T, R, C, S> impl<T: Hash, R: Dim, C: Dim, S> Hash for Matrix<T, R, C, S>
where where
T: Hash,
S: Storage<T, R, C>, S: Storage<T, R, C>,
{ {
fn hash<H: Hasher>(&self, state: &mut H) { fn hash<H: Hasher>(&self, state: &mut H) {

View File

@ -9,11 +9,9 @@ use crate::base::{DefaultAllocator, OMatrix, Scalar};
* Simd structures. * Simd structures.
* *
*/ */
impl<T, R, C> SimdValue for OMatrix<T, R, C> impl<T, R: Dim, C: Dim> SimdValue for OMatrix<T, R, C>
where where
T: Scalar + SimdValue, T: Scalar + SimdValue,
R: Dim,
C: Dim,
T::Element: Scalar, T::Element: Scalar,
DefaultAllocator: Allocator<T, R, C> + Allocator<T::Element, R, C>, DefaultAllocator: Allocator<T, R, C> + Allocator<T::Element, R, C>,
{ {

View File

@ -645,7 +645,7 @@ impl<T, R1: Dim, C1: Dim, R2: Dim, SA, SB> MulAssign<Matrix<T, R2, C1, SB>>
where where
T: Scalar + Zero + One + ClosedAdd + ClosedMul, T: Scalar + Zero + One + ClosedAdd + ClosedMul,
SB: Storage<T, R2, C1>, SB: Storage<T, R2, C1>,
SA: ContiguousStorageMut<T, R1, C1> + Clone, SA: ContiguousStorageMut<T, R1, C1> ,
ShapeConstraint: AreMultipliable<R1, C1, R2, C1>, ShapeConstraint: AreMultipliable<R1, C1, R2, C1>,
DefaultAllocator: Allocator<T, R1, C1> + InnerAllocator<T, R1, C1, Buffer = SA>, DefaultAllocator: Allocator<T, R1, C1> + InnerAllocator<T, R1, C1, Buffer = SA>,
{ {
@ -660,7 +660,7 @@ impl<'b, T, R1: Dim, C1: Dim, R2: Dim, SA, SB> MulAssign<&'b Matrix<T, R2, C1, S
where where
T: Scalar + Zero + One + ClosedAdd + ClosedMul, T: Scalar + Zero + One + ClosedAdd + ClosedMul,
SB: Storage<T, R2, C1>, SB: Storage<T, R2, C1>,
SA: ContiguousStorageMut<T, R1, C1> + Clone, SA: ContiguousStorageMut<T, R1, C1> ,
ShapeConstraint: AreMultipliable<R1, C1, R2, C1>, ShapeConstraint: AreMultipliable<R1, C1, R2, C1>,
// TODO: this is too restrictive. See comments for the non-ref version. // TODO: this is too restrictive. See comments for the non-ref version.
DefaultAllocator: Allocator<T, R1, C1> + InnerAllocator<T, R1, C1, Buffer = SA>, DefaultAllocator: Allocator<T, R1, C1> + InnerAllocator<T, R1, C1, Buffer = SA>,
@ -796,7 +796,6 @@ where
ShapeConstraint: SameNumberOfRows<R3, R1> ShapeConstraint: SameNumberOfRows<R3, R1>
+ SameNumberOfColumns<C3, C2> + SameNumberOfColumns<C3, C2>
+ AreMultipliable<R1, C1, R2, C2>, + AreMultipliable<R1, C1, R2, C2>,
DefaultAllocator: Allocator<T, R3, C3>,
{ {
out.gemm_z(T::one(), self, rhs); out.gemm_z(T::one(), self, rhs);
} }

View File

@ -26,6 +26,8 @@ pub trait Scalar: 'static + Clone + Debug {
fn inlined_clone(&self) -> Self; fn inlined_clone(&self) -> Self;
} }
// Unfortunately, this blanket impl leads to many misleading compiler messages
// telling you to implement Copy, even though Scalar is what's really needed.
impl<T: 'static + Copy + Debug> Scalar for T { impl<T: 'static + Copy + Debug> Scalar for T {
#[inline(always)] #[inline(always)]
fn inlined_clone(&self) -> T { fn inlined_clone(&self) -> T {

View File

@ -7,7 +7,7 @@ use num::Zero;
use simba::scalar::{ClosedAdd, Field, SupersetOf}; use simba::scalar::{ClosedAdd, Field, SupersetOf};
/// # Folding on columns and rows /// # Folding on columns and rows
impl<T: Scalar, R: Dim, C: Dim, S: Storage<T, R, C>> Matrix<T, R, C, S> { impl<T, R: Dim, C: Dim, S: Storage<T, R, C>> Matrix<T, R, C, S> {
/// Returns a row vector where each element is the result of the application of `f` on the /// Returns a row vector where each element is the result of the application of `f` on the
/// corresponding column of the original matrix. /// corresponding column of the original matrix.
#[inline] #[inline]

View File

@ -1,4 +1,4 @@
use crate::base::{DimName, Scalar, ToTypenum, Vector, Vector2, Vector3}; use crate::base::{DimName, ToTypenum, Vector, Vector2, Vector3};
use crate::storage::Storage; use crate::storage::Storage;
use typenum::{self, Cmp, Greater}; use typenum::{self, Cmp, Greater};
@ -11,7 +11,7 @@ macro_rules! impl_swizzle {
#[must_use] #[must_use]
pub fn $name(&self) -> $Result<T> pub fn $name(&self) -> $Result<T>
where D::Typenum: Cmp<typenum::$BaseDim, Output=Greater> { where D::Typenum: Cmp<typenum::$BaseDim, Output=Greater> {
$Result::new($(self[$i].inlined_clone()),*) $Result::new($(self[$i].clone()),*)
} }
)* )*
)* )*
@ -19,7 +19,7 @@ macro_rules! impl_swizzle {
} }
/// # Swizzling /// # Swizzling
impl<T: Scalar, D, S: Storage<T, D>> Vector<T, D, S> impl<T: Clone, D, S: Storage<T, D>> Vector<T, D, S>
where where
D: DimName + ToTypenum, D: DimName + ToTypenum,
{ {

View File

@ -2,15 +2,15 @@
#![allow(clippy::op_ref)] #![allow(clippy::op_ref)]
use crate::{ use crate::{
Isometry3, Matrix4, Normed, OVector, Point3, Quaternion, Scalar, SimdRealField, Translation3, Isometry3, Matrix4, Normed, OVector, Point3, Quaternion, SimdRealField, Translation3, Unit,
Unit, UnitQuaternion, Vector3, Zero, U8, UnitQuaternion, Vector3, Zero, U8,
}; };
use approx::{AbsDiffEq, RelativeEq, UlpsEq}; use approx::{AbsDiffEq, RelativeEq, UlpsEq};
#[cfg(feature = "serde-serialize-no-std")] #[cfg(feature = "serde-serialize-no-std")]
use serde::{Deserialize, Deserializer, Serialize, Serializer}; use serde::{Deserialize, Deserializer, Serialize, Serializer};
use std::fmt; use std::fmt;
use simba::scalar::{ClosedNeg, RealField}; use simba::scalar::RealField;
/// A dual quaternion. /// A dual quaternion.
/// ///
@ -251,10 +251,7 @@ where
} }
#[cfg(feature = "serde-serialize-no-std")] #[cfg(feature = "serde-serialize-no-std")]
impl<T: SimdRealField> Serialize for DualQuaternion<T> impl<T: Serialize> Serialize for DualQuaternion<T> {
where
T: Serialize,
{
fn serialize<S>(&self, serializer: S) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error> fn serialize<S>(&self, serializer: S) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error>
where where
S: Serializer, S: Serializer,
@ -264,10 +261,7 @@ where
} }
#[cfg(feature = "serde-serialize-no-std")] #[cfg(feature = "serde-serialize-no-std")]
impl<'a, T: SimdRealField> Deserialize<'a> for DualQuaternion<T> impl<'a, T: Deserialize<'a>> Deserialize<'a> for DualQuaternion<T> {
where
T: Deserialize<'a>,
{
fn deserialize<Des>(deserializer: Des) -> Result<Self, Des::Error> fn deserialize<Des>(deserializer: Des) -> Result<Self, Des::Error>
where where
Des: Deserializer<'a>, Des: Deserializer<'a>,
@ -283,7 +277,7 @@ where
} }
} }
impl<T: RealField> DualQuaternion<T> { impl<T> DualQuaternion<T> {
fn to_vector(self) -> OVector<T, U8> { fn to_vector(self) -> OVector<T, U8> {
(*self.as_ref()).into() (*self.as_ref()).into()
} }
@ -341,14 +335,14 @@ impl<T: RealField + UlpsEq<Epsilon = T>> UlpsEq for DualQuaternion<T> {
/// A unit quaternions. May be used to represent a rotation followed by a translation. /// A unit quaternions. May be used to represent a rotation followed by a translation.
pub type UnitDualQuaternion<T> = Unit<DualQuaternion<T>>; pub type UnitDualQuaternion<T> = Unit<DualQuaternion<T>>;
impl<T: Scalar + ClosedNeg + PartialEq + SimdRealField> PartialEq for UnitDualQuaternion<T> { impl<T: PartialEq> PartialEq for UnitDualQuaternion<T> {
#[inline] #[inline]
fn eq(&self, rhs: &Self) -> bool { fn eq(&self, rhs: &Self) -> bool {
self.as_ref().eq(rhs.as_ref()) self.as_ref().eq(rhs.as_ref())
} }
} }
impl<T: Scalar + ClosedNeg + Eq + SimdRealField> Eq for UnitDualQuaternion<T> {} impl<T: Eq> Eq for UnitDualQuaternion<T> {}
impl<T: SimdRealField> Normed for DualQuaternion<T> { impl<T: SimdRealField> Normed for DualQuaternion<T> {
type Norm = T::SimdRealField; type Norm = T::SimdRealField;
@ -376,10 +370,7 @@ impl<T: SimdRealField> Normed for DualQuaternion<T> {
} }
} }
impl<T: SimdRealField> UnitDualQuaternion<T> impl<T> UnitDualQuaternion<T> {
where
T::Element: SimdRealField,
{
/// The underlying dual quaternion. /// The underlying dual quaternion.
/// ///
/// Same as `self.as_ref()`. /// Same as `self.as_ref()`.
@ -398,7 +389,12 @@ where
pub fn dual_quaternion(&self) -> &DualQuaternion<T> { pub fn dual_quaternion(&self) -> &DualQuaternion<T> {
self.as_ref() self.as_ref()
} }
}
impl<T: SimdRealField> UnitDualQuaternion<T>
where
T::Element: SimdRealField,
{
/// Compute the conjugate of this unit quaternion. /// Compute the conjugate of this unit quaternion.
/// ///
/// # Example /// # Example
@ -600,7 +596,7 @@ where
#[must_use] #[must_use]
pub fn sclerp(&self, other: &Self, t: T) -> Self pub fn sclerp(&self, other: &Self, t: T) -> Self
where where
T: RealField, T: RealField + RelativeEq<Epsilon = T>,
{ {
self.try_sclerp(other, t, T::default_epsilon()) self.try_sclerp(other, t, T::default_epsilon())
.expect("DualQuaternion sclerp: ambiguous configuration.") .expect("DualQuaternion sclerp: ambiguous configuration.")
@ -620,7 +616,7 @@ where
#[must_use] #[must_use]
pub fn try_sclerp(&self, other: &Self, t: T, epsilon: T) -> Option<Self> pub fn try_sclerp(&self, other: &Self, t: T, epsilon: T) -> Option<Self>
where where
T: RealField, T: RealField + RelativeEq<Epsilon = T>,
{ {
let two = T::one() + T::one(); let two = T::one() + T::one();
let half = T::one() / two; let half = T::one() / two;
@ -895,7 +891,7 @@ impl<T: RealField> Default for UnitDualQuaternion<T> {
} }
} }
impl<T: RealField + fmt::Display> fmt::Display for UnitDualQuaternion<T> { impl<T: RealField+fmt::Display> fmt::Display for UnitDualQuaternion<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if let Some(axis) = self.rotation().axis() { if let Some(axis) = self.rotation().axis() {
let axis = axis.into_inner(); let axis = axis.into_inner();

View File

@ -1,5 +1,5 @@
use crate::{ use crate::{
DualQuaternion, Isometry3, Quaternion, Scalar, SimdRealField, Translation3, UnitDualQuaternion, DualQuaternion, Isometry3, Quaternion, SimdRealField, Translation3, UnitDualQuaternion,
UnitQuaternion, UnitQuaternion,
}; };
use num::{One, Zero}; use num::{One, Zero};
@ -7,7 +7,7 @@ use num::{One, Zero};
use quickcheck::{Arbitrary, Gen}; use quickcheck::{Arbitrary, Gen};
use simba::scalar::SupersetOf; use simba::scalar::SupersetOf;
impl<T: Scalar> DualQuaternion<T> { impl<T> DualQuaternion<T> {
/// Creates a dual quaternion from its rotation and translation components. /// Creates a dual quaternion from its rotation and translation components.
/// ///
/// # Example /// # Example
@ -60,7 +60,7 @@ impl<T: Scalar> DualQuaternion<T> {
/// let q2 = q.cast::<f32>(); /// let q2 = q.cast::<f32>();
/// assert_eq!(q2, DualQuaternion::from_real(Quaternion::new(1.0f32, 2.0, 3.0, 4.0))); /// assert_eq!(q2, DualQuaternion::from_real(Quaternion::new(1.0f32, 2.0, 3.0, 4.0)));
/// ``` /// ```
pub fn cast<To: Scalar>(self) -> DualQuaternion<To> pub fn cast<To>(self) -> DualQuaternion<To>
where where
DualQuaternion<To>: SupersetOf<Self>, DualQuaternion<To>: SupersetOf<Self>,
{ {
@ -156,7 +156,7 @@ impl<T: SimdRealField> UnitDualQuaternion<T> {
/// let q2 = q.cast::<f32>(); /// let q2 = q.cast::<f32>();
/// assert_eq!(q2, UnitDualQuaternion::<f32>::identity()); /// assert_eq!(q2, UnitDualQuaternion::<f32>::identity());
/// ``` /// ```
pub fn cast<To: Scalar>(self) -> UnitDualQuaternion<To> pub fn cast<To>(self) -> UnitDualQuaternion<To>
where where
UnitDualQuaternion<To>: SupersetOf<Self>, UnitDualQuaternion<To>: SupersetOf<Self>,
{ {

View File

@ -24,8 +24,7 @@ use crate::geometry::{
impl<T1, T2> SubsetOf<DualQuaternion<T2>> for DualQuaternion<T1> impl<T1, T2> SubsetOf<DualQuaternion<T2>> for DualQuaternion<T1>
where where
T1: SimdRealField, T2: SupersetOf<T1>,
T2: SimdRealField + SupersetOf<T1>,
{ {
#[inline] #[inline]
fn to_superset(&self) -> DualQuaternion<T2> { fn to_superset(&self) -> DualQuaternion<T2> {
@ -49,8 +48,7 @@ where
impl<T1, T2> SubsetOf<UnitDualQuaternion<T2>> for UnitDualQuaternion<T1> impl<T1, T2> SubsetOf<UnitDualQuaternion<T2>> for UnitDualQuaternion<T1>
where where
T1: SimdRealField, T2: SupersetOf<T1>,
T2: SimdRealField + SupersetOf<T1>,
{ {
#[inline] #[inline]
fn to_superset(&self) -> UnitDualQuaternion<T2> { fn to_superset(&self) -> UnitDualQuaternion<T2> {

View File

@ -56,21 +56,21 @@ use std::ops::{
Add, AddAssign, Div, DivAssign, Index, IndexMut, Mul, MulAssign, Neg, Sub, SubAssign, Add, AddAssign, Div, DivAssign, Index, IndexMut, Mul, MulAssign, Neg, Sub, SubAssign,
}; };
impl<T: SimdRealField> AsRef<[T; 8]> for DualQuaternion<T> { impl<T> AsRef<[T; 8]> for DualQuaternion<T> {
#[inline] #[inline]
fn as_ref(&self) -> &[T; 8] { fn as_ref(&self) -> &[T; 8] {
unsafe { &*(self as *const Self as *const [T; 8]) } unsafe { &*(self as *const Self as *const [T; 8]) }
} }
} }
impl<T: SimdRealField> AsMut<[T; 8]> for DualQuaternion<T> { impl<T> AsMut<[T; 8]> for DualQuaternion<T> {
#[inline] #[inline]
fn as_mut(&mut self) -> &mut [T; 8] { fn as_mut(&mut self) -> &mut [T; 8] {
unsafe { &mut *(self as *mut Self as *mut [T; 8]) } unsafe { &mut *(self as *mut Self as *mut [T; 8]) }
} }
} }
impl<T: SimdRealField> Index<usize> for DualQuaternion<T> { impl<T> Index<usize> for DualQuaternion<T> {
type Output = T; type Output = T;
#[inline] #[inline]
@ -79,7 +79,7 @@ impl<T: SimdRealField> Index<usize> for DualQuaternion<T> {
} }
} }
impl<T: SimdRealField> IndexMut<usize> for DualQuaternion<T> { impl<T> IndexMut<usize> for DualQuaternion<T> {
#[inline] #[inline]
fn index_mut(&mut self, i: usize) -> &mut T { fn index_mut(&mut self, i: usize) -> &mut T {
&mut self.as_mut()[i] &mut self.as_mut()[i]

View File

@ -80,7 +80,6 @@ pub struct Isometry<T, R, const D: usize> {
#[cfg(feature = "abomonation-serialize")] #[cfg(feature = "abomonation-serialize")]
impl<T, R, const D: usize> Abomonation for Isometry<T, R, D> impl<T, R, const D: usize> Abomonation for Isometry<T, R, D>
where where
T: SimdRealField,
R: Abomonation, R: Abomonation,
Translation<T, D>: Abomonation, Translation<T, D>: Abomonation,
{ {
@ -106,10 +105,7 @@ mod rkyv_impl {
use crate::{base::Scalar, geometry::Translation}; use crate::{base::Scalar, geometry::Translation};
use rkyv::{offset_of, project_struct, Archive, Deserialize, Fallible, Serialize}; use rkyv::{offset_of, project_struct, Archive, Deserialize, Fallible, Serialize};
impl<T: Scalar + Archive, R: Archive, const D: usize> Archive for Isometry<T, R, D> impl<T: Archive, R: Archive, const D: usize> Archive for Isometry<T, R, D> {
where
T::Archived: Scalar,
{
type Archived = Isometry<T::Archived, R::Archived, D>; type Archived = Isometry<T::Archived, R::Archived, D>;
type Resolver = (R::Resolver, <Translation<T, D> as Archive>::Resolver); type Resolver = (R::Resolver, <Translation<T, D> as Archive>::Resolver);
@ -132,8 +128,8 @@ mod rkyv_impl {
} }
} }
impl<T: Scalar + Serialize<S>, R: Serialize<S>, S: Fallible + ?Sized, const D: usize> impl<T: Serialize<S>, R: Serialize<S>, S: Fallible + ?Sized, const D: usize> Serialize<S>
Serialize<S> for Isometry<T, R, D> for Isometry<T, R, D>
where where
T::Archived: Scalar, T::Archived: Scalar,
{ {
@ -145,7 +141,7 @@ mod rkyv_impl {
} }
} }
impl<T: Scalar + Archive, R: Archive, _D: Fallible + ?Sized, const D: usize> impl<T: Archive, R: Archive, _D: Fallible + ?Sized, const D: usize>
Deserialize<Isometry<T, R, D>, _D> for Isometry<T::Archived, R::Archived, D> Deserialize<Isometry<T, R, D>, _D> for Isometry<T::Archived, R::Archived, D>
where where
T::Archived: Scalar + Deserialize<T, _D>, T::Archived: Scalar + Deserialize<T, _D>,
@ -160,7 +156,7 @@ mod rkyv_impl {
} }
} }
impl<T: Scalar + hash::Hash, R: hash::Hash, const D: usize> hash::Hash for Isometry<T, R, D> impl<T: hash::Hash, R: hash::Hash, const D: usize> hash::Hash for Isometry<T, R, D>
where where
Owned<T, Const<D>>: hash::Hash, Owned<T, Const<D>>: hash::Hash,
{ {
@ -170,12 +166,9 @@ where
} }
} }
impl<T: Scalar + Copy, R: Copy, const D: usize> Copy for Isometry<T, R, D> where impl<T: Copy, R: Copy, const D: usize> Copy for Isometry<T, R, D> where Owned<T, Const<D>>: Copy {}
Owned<T, Const<D>>: Copy
{
}
impl<T: Scalar, R: Clone, const D: usize> Clone for Isometry<T, R, D> { impl<T: Clone, R: Clone, const D: usize> Clone for Isometry<T, R, D> {
#[inline] #[inline]
fn clone(&self) -> Self { fn clone(&self) -> Self {
Self { Self {
@ -638,7 +631,7 @@ where
* Display * Display
* *
*/ */
impl<T: RealField + fmt::Display, R, const D: usize> fmt::Display for Isometry<T, R, D> impl<T: Scalar + fmt::Display, R, const D: usize> fmt::Display for Isometry<T, R, D>
where where
R: fmt::Display, R: fmt::Display,
{ {

View File

@ -5,6 +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;
#[cfg(feature = "serde-serialize-no-std")] #[cfg(feature = "serde-serialize-no-std")]
use serde::{Deserialize, Deserializer, Serialize, Serializer}; use serde::{Deserialize, Deserializer, Serialize, Serializer};
@ -20,6 +21,7 @@ use crate::base::dimension::{DimName, DimNameAdd, DimNameSum, U1};
use crate::base::iter::{MatrixIter, MatrixIterMut}; use crate::base::iter::{MatrixIter, MatrixIterMut};
use crate::base::{Const, DefaultAllocator, OVector}; use crate::base::{Const, DefaultAllocator, OVector};
use crate::storage::Owned; use crate::storage::Owned;
use crate::Scalar;
/// A point in an euclidean space. /// A point in an euclidean space.
/// ///
@ -41,7 +43,7 @@ use crate::storage::Owned;
/// 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)]
#[derive(Debug, Clone)] // 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>,
@ -66,6 +68,16 @@ where
{ {
} }
impl<T: Clone, D: DimName> Clone for OPoint<T, D>
where
DefaultAllocator: Allocator<T, D>,
OVector<T, D>: Clone,
{
fn clone(&self) -> Self {
Self::from(self.coords.clone())
}
}
#[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
@ -151,7 +163,8 @@ where
#[inline] #[inline]
#[must_use] #[must_use]
pub fn map<T2, F: FnMut(T) -> T2>(&self, f: F) -> OPoint<T2, D> pub fn map<T2, F: FnMut(T) -> T2>(&self, f: F) -> OPoint<T2, D>
where T:Clone, where
T: Clone,
DefaultAllocator: Allocator<T2, D>, DefaultAllocator: Allocator<T2, D>,
{ {
self.coords.map(f).into() self.coords.map(f).into()
@ -194,22 +207,44 @@ where
#[inline] #[inline]
#[must_use] #[must_use]
pub fn to_homogeneous(&self) -> OVector<T, DimNameSum<D, U1>> pub fn to_homogeneous(&self) -> OVector<T, DimNameSum<D, U1>>
where
T: One + Clone,
D: DimNameAdd<U1>,
DefaultAllocator: Allocator<T, DimNameSum<D, U1>>,
{
let mut res = OVector::<_, DimNameSum<D, U1>>::new_uninitialized();
for i in 0..D::dim() {
unsafe {
*res.get_unchecked(i) = MaybeUninit::new(self.coords[i].clone());
}
}
res[(D::dim(), 0)] = MaybeUninit::new(T::one());
unsafe { res.assume_init() }
}
pub fn into_homogeneous(self) -> OVector<T, DimNameSum<D, U1>>
where where
T: One, T: One,
D: DimNameAdd<U1>, D: DimNameAdd<U1>,
DefaultAllocator: Allocator<T, DimNameSum<D, U1>>, DefaultAllocator: Allocator<T, DimNameSum<D, U1>>,
{ {
let mut res = unsafe { let mut res = OVector::<_, DimNameSum<D, U1>>::new_uninitialized();
crate::unimplemented_or_uninitialized_generic!(
<DimNameSum<D, U1> as DimName>::name(),
Const::<1>
)
};
res.generic_slice_mut((0, 0), (D::name(), Const::<1>))
.copy_from(&self.coords);
res[(D::dim(), 0)] = T::one();
res // TODO: maybe we can move the whole array at once? Or use `into_iter`
// to avoid double-dropping.
for i in 0..D::dim() {
unsafe {
*res.get_unchecked(i) = MaybeUninit::new(self.coords[i]);
}
}
// Fix double drop
res[(D::dim(), 0)] = MaybeUninit::new(T::one());
unsafe { res.assume_init() }
} }
/// Creates a new point with the given coordinates. /// Creates a new point with the given coordinates.
@ -415,7 +450,7 @@ where
/* /*
* inf/sup * inf/sup
*/ */
impl<T: SimdPartialOrd, D: DimName> OPoint<T, D> impl<T: Scalar + SimdPartialOrd, D: DimName> OPoint<T, D>
where where
DefaultAllocator: Allocator<T, D>, DefaultAllocator: Allocator<T, D>,
{ {

View File

@ -50,9 +50,9 @@ where
#[inline] #[inline]
pub fn origin() -> Self pub fn origin() -> Self
where where
T: Zero, T: Zero + Clone,
{ {
Self::from(OVector::from_element(T::zero())) Self::from(OVector::<_, D>::zeros())
} }
/// Creates a new point from a slice. /// Creates a new point from a slice.
@ -70,8 +70,11 @@ where
/// assert_eq!(pt, Point3::new(1.0, 2.0, 3.0)); /// assert_eq!(pt, Point3::new(1.0, 2.0, 3.0));
/// ``` /// ```
#[inline] #[inline]
pub fn from_slice(components: &[T]) -> Self { pub fn from_slice(components: &[T]) -> Self
Self::from(OVector::from_row_slice(components)) where
T: Clone,
{
Self::from(OVector::<_, D>::from_row_slice(components))
} }
/// Creates a new point from its homogeneous vector representation. /// Creates a new point from its homogeneous vector representation.
@ -175,7 +178,7 @@ where
impl<T: Arbitrary + Send, D: DimName> Arbitrary for OPoint<T, D> impl<T: Arbitrary + Send, D: DimName> Arbitrary for OPoint<T, D>
where where
DefaultAllocator: Allocator<T, D>, DefaultAllocator: Allocator<T, D>,
crate::base::storage::Owned<T, D>: Send, crate::base::storage::Owned<T, D>: Clone + Send,
{ {
#[inline] #[inline]
fn arbitrary(g: &mut Gen) -> Self { fn arbitrary(g: &mut Gen) -> Self {

View File

@ -2,12 +2,11 @@ use num::{One, Zero};
use simba::scalar::{ClosedDiv, SubsetOf, SupersetOf}; use simba::scalar::{ClosedDiv, SubsetOf, SupersetOf};
use simba::simd::PrimitiveSimdValue; use simba::simd::PrimitiveSimdValue;
use crate::base::allocator::Allocator; use crate::base::allocator::{Allocator, InnerAllocator};
use crate::base::dimension::{DimNameAdd, DimNameSum, U1}; use crate::base::dimension::{DimNameAdd, DimNameSum, U1};
use crate::base::{Const, DefaultAllocator, Matrix, OVector, Scalar}; use crate::base::{Const, DefaultAllocator, Matrix, OVector, Scalar};
use crate::geometry::Point; use crate::geometry::Point;
use crate::storage::Owned;
use crate::{DimName, OPoint}; use crate::{DimName, OPoint};
/* /*
@ -55,7 +54,7 @@ where
#[inline] #[inline]
fn to_superset(&self) -> OVector<T2, DimNameSum<D, U1>> { fn to_superset(&self) -> OVector<T2, DimNameSum<D, U1>> {
let p: OPoint<T2, D> = self.to_superset(); let p: OPoint<T2, D> = self.to_superset();
p.to_homogeneous() p.into_homogeneous()
} }
#[inline] #[inline]
@ -79,7 +78,7 @@ where
{ {
#[inline] #[inline]
fn from(t: OPoint<T, D>) -> Self { fn from(t: OPoint<T, D>) -> Self {
t.to_homogeneous() t.into_homogeneous()
} }
} }
@ -101,7 +100,7 @@ impl<T, const D: usize> From<Point<T, D>> for [T; D] {
impl<T, D: DimName> From<OVector<T, D>> for OPoint<T, D> impl<T, D: DimName> From<OVector<T, D>> for OPoint<T, D>
where where
DefaultAllocator: Allocator<T, D>, DefaultAllocator: InnerAllocator<T, D>,
{ {
#[inline] #[inline]
fn from(coords: OVector<T, D>) -> Self { fn from(coords: OVector<T, D>) -> Self {
@ -109,81 +108,81 @@ where
} }
} }
impl<T: Copy + PrimitiveSimdValue, const D: usize> From<[Point<T::Element, D>; 2]> for Point<T, D> impl<T: Scalar + PrimitiveSimdValue, const D: usize> From<[Point<T::Element, D>; 2]> for Point<T, D>
where where
T: From<[<T as simba::simd::SimdValue>::Element; 2]>, T: From<[<T as simba::simd::SimdValue>::Element; 2]>,
T::Element: Copy, T::Element: Scalar,
Owned<T::Element, Const<D>>: Copy,
{ {
#[inline] #[inline]
fn from(arr: [Point<T::Element, D>; 2]) -> Self { fn from(arr: [Point<T::Element, D>; 2]) -> Self {
Self::from(OVector::from([arr[0].coords, arr[1].coords])) Self::from(OVector::from([
arr[0].coords.clone(),
arr[1].coords.clone(),
]))
} }
} }
impl<T: Copy + PrimitiveSimdValue, const D: usize> From<[Point<T::Element, D>; 4]> for Point<T, D> impl<T: Scalar + PrimitiveSimdValue, const D: usize> From<[Point<T::Element, D>; 4]> for Point<T, D>
where where
T: From<[<T as simba::simd::SimdValue>::Element; 4]>, T: From<[<T as simba::simd::SimdValue>::Element; 4]>,
T::Element: Copy, T::Element: Scalar,
Owned<T::Element, Const<D>>: Copy,
{ {
#[inline] #[inline]
fn from(arr: [Point<T::Element, D>; 4]) -> Self { fn from(arr: [Point<T::Element, D>; 4]) -> Self {
Self::from(OVector::from([ Self::from(OVector::from([
arr[0].coords, arr[0].coords.clone(),
arr[1].coords, arr[1].coords.clone(),
arr[2].coords, arr[2].coords.clone(),
arr[3].coords, arr[3].coords.clone(),
])) ]))
} }
} }
impl<T: Copy + PrimitiveSimdValue, const D: usize> From<[Point<T::Element, D>; 8]> for Point<T, D> impl<T: Scalar + PrimitiveSimdValue, const D: usize> From<[Point<T::Element, D>; 8]> for Point<T, D>
where where
T: From<[<T as simba::simd::SimdValue>::Element; 8]>, T: From<[<T as simba::simd::SimdValue>::Element; 8]>,
T::Element: Copy, T::Element: Scalar,
Owned<T::Element, Const<D>>: Copy,
{ {
#[inline] #[inline]
fn from(arr: [Point<T::Element, D>; 8]) -> Self { fn from(arr: [Point<T::Element, D>; 8]) -> Self {
Self::from(OVector::from([ Self::from(OVector::from([
arr[0].coords, arr[0].coords.clone(),
arr[1].coords, arr[1].coords.clone(),
arr[2].coords, arr[2].coords.clone(),
arr[3].coords, arr[3].coords.clone(),
arr[4].coords, arr[4].coords.clone(),
arr[5].coords, arr[5].coords.clone(),
arr[6].coords, arr[6].coords.clone(),
arr[7].coords, arr[7].coords.clone(),
])) ]))
} }
} }
impl<T: Copy + PrimitiveSimdValue, const D: usize> From<[Point<T::Element, D>; 16]> for Point<T, D> impl<T: Scalar + PrimitiveSimdValue, const D: usize> From<[Point<T::Element, D>; 16]>
for Point<T, D>
where where
T: From<[<T as simba::simd::SimdValue>::Element; 16]>, T: From<[<T as simba::simd::SimdValue>::Element; 16]>,
T::Element: Copy, T::Element: Scalar,
Owned<T::Element, Const<D>>: Copy,
{ {
#[inline] #[inline]
fn from(arr: [Point<T::Element, D>; 16]) -> Self { fn from(arr: [Point<T::Element, D>; 16]) -> Self {
Self::from(OVector::from([ Self::from(OVector::from([
arr[0].coords, arr[0].coords.clone(),
arr[1].coords, arr[1].coords.clone(),
arr[2].coords, arr[2].coords.clone(),
arr[3].coords, arr[3].coords.clone(),
arr[4].coords, arr[4].coords.clone(),
arr[5].coords, arr[5].coords.clone(),
arr[6].coords, arr[6].coords.clone(),
arr[7].coords, arr[7].coords.clone(),
arr[8].coords, arr[8].coords.clone(),
arr[9].coords, arr[9].coords.clone(),
arr[10].coords, arr[10].coords.clone(),
arr[11].coords, arr[11].coords.clone(),
arr[12].coords, arr[12].coords.clone(),
arr[13].coords, arr[13].coords.clone(),
arr[14].coords, arr[14].coords.clone(),
arr[15].coords, arr[15].coords.clone(),
])) ]))
} }
} }

View File

@ -1,7 +1,7 @@
use std::ops::{Deref, DerefMut}; use std::ops::{Deref, DerefMut};
use crate::base::coordinates::{X, XY, XYZ, XYZW, XYZWA, XYZWAB}; use crate::base::coordinates::{X, XY, XYZ, XYZW, XYZWA, XYZWAB};
use crate::base::{Scalar, U1, U2, U3, U4, U5, U6}; use crate::base::{U1, U2, U3, U4, U5, U6};
use crate::geometry::OPoint; use crate::geometry::OPoint;
@ -13,7 +13,7 @@ use crate::geometry::OPoint;
macro_rules! deref_impl( macro_rules! deref_impl(
($D: ty, $Target: ident $(, $comps: ident)*) => { ($D: ty, $Target: ident $(, $comps: ident)*) => {
impl<T: Scalar> Deref for OPoint<T, $D> impl<T> Deref for OPoint<T, $D>
{ {
type Target = $Target<T>; type Target = $Target<T>;
@ -23,7 +23,7 @@ macro_rules! deref_impl(
} }
} }
impl<T: Scalar> DerefMut for OPoint<T, $D> impl<T> DerefMut for OPoint<T, $D>
{ {
#[inline] #[inline]
fn deref_mut(&mut self) -> &mut Self::Target { fn deref_mut(&mut self) -> &mut Self::Target {

View File

@ -1,10 +1,13 @@
use simba::simd::SimdValue; use simba::simd::SimdValue;
use crate::base::OVector; use crate::base::OVector;
use crate::geometry::Point; use crate::geometry::Point;
use crate::Scalar;
impl<T: SimdValue, const D: usize> SimdValue for Point<T, D> { impl<T: Scalar + SimdValue, const D: usize> SimdValue for Point<T, D>
where
T::Element: Scalar,
{
type Element = Point<T::Element, D>; type Element = Point<T::Element, D>;
type SimdBool = T::SimdBool; type SimdBool = T::SimdBool;

View File

@ -57,10 +57,10 @@ impl<T: Zero + Clone> Default for Quaternion<T> {
} }
#[cfg(feature = "bytemuck")] #[cfg(feature = "bytemuck")]
unsafe impl<T: Scalar> bytemuck::Zeroable for Quaternion<T> where Vector4<T>: bytemuck::Zeroable {} unsafe impl<T> bytemuck::Zeroable for Quaternion<T> where Vector4<T>: bytemuck::Zeroable {}
#[cfg(feature = "bytemuck")] #[cfg(feature = "bytemuck")]
unsafe impl<T: Scalar> bytemuck::Pod for Quaternion<T> unsafe impl<T> bytemuck::Pod for Quaternion<T>
where where
Vector4<T>: bytemuck::Pod, Vector4<T>: bytemuck::Pod,
T: Copy, T: Copy,
@ -68,7 +68,7 @@ where
} }
#[cfg(feature = "abomonation-serialize")] #[cfg(feature = "abomonation-serialize")]
impl<T: Scalar> Abomonation for Quaternion<T> impl<T> Abomonation for Quaternion<T>
where where
Vector4<T>: Abomonation, Vector4<T>: Abomonation,
{ {
@ -86,7 +86,7 @@ where
} }
#[cfg(feature = "serde-serialize-no-std")] #[cfg(feature = "serde-serialize-no-std")]
impl<T: Scalar> Serialize for Quaternion<T> impl<T> Serialize for Quaternion<T>
where where
Owned<T, U4>: Serialize, Owned<T, U4>: Serialize,
{ {
@ -99,7 +99,7 @@ where
} }
#[cfg(feature = "serde-serialize-no-std")] #[cfg(feature = "serde-serialize-no-std")]
impl<'a, T: Scalar> Deserialize<'a> for Quaternion<T> impl<'a, T> Deserialize<'a> for Quaternion<T>
where where
Owned<T, U4>: Deserialize<'a>, Owned<T, U4>: Deserialize<'a>,
{ {
@ -1045,7 +1045,7 @@ impl<T: RealField + UlpsEq<Epsilon = T>> UlpsEq for Quaternion<T> {
} }
} }
impl<T: RealField + fmt::Display> fmt::Display for Quaternion<T> { impl<T: fmt::Display> fmt::Display for Quaternion<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!( write!(
f, f,
@ -1097,7 +1097,7 @@ impl<T: SimdRealField> UnitQuaternion<T>
where where
T::Element: SimdRealField, T::Element: SimdRealField,
{ {
/// The rotation angle in [0; pi] of this unit quaternion. /// The rotation angle in \[0; pi\] of this unit quaternion.
/// ///
/// # Example /// # Example
/// ``` /// ```

View File

@ -28,8 +28,7 @@ use crate::geometry::{
impl<T1, T2> SubsetOf<Quaternion<T2>> for Quaternion<T1> impl<T1, T2> SubsetOf<Quaternion<T2>> for Quaternion<T1>
where where
T1: Scalar, T2 : SupersetOf<T1>,
T2: Scalar + SupersetOf<T1>,
{ {
#[inline] #[inline]
fn to_superset(&self) -> Quaternion<T2> { fn to_superset(&self) -> Quaternion<T2> {
@ -51,8 +50,7 @@ where
impl<T1, T2> SubsetOf<UnitQuaternion<T2>> for UnitQuaternion<T1> impl<T1, T2> SubsetOf<UnitQuaternion<T2>> for UnitQuaternion<T1>
where where
T1: Scalar, T2: SupersetOf<T1>,
T2: Scalar + SupersetOf<T1>,
{ {
#[inline] #[inline]
fn to_superset(&self) -> UnitQuaternion<T2> { fn to_superset(&self) -> UnitQuaternion<T2> {
@ -239,14 +237,14 @@ where
} }
} }
impl<T: Scalar> From<Vector4<T>> for Quaternion<T> { impl<T> From<Vector4<T>> for Quaternion<T> {
#[inline] #[inline]
fn from(coords: Vector4<T>) -> Self { fn from(coords: Vector4<T>) -> Self {
Self { coords } Self { coords }
} }
} }
impl<T: Scalar> From<[T; 4]> for Quaternion<T> { impl<T> From<[T; 4]> for Quaternion<T> {
#[inline] #[inline]
fn from(coords: [T; 4]) -> Self { fn from(coords: [T; 4]) -> Self {
Self { Self {

View File

@ -59,12 +59,12 @@ use std::ops::{
use crate::base::dimension::U3; use crate::base::dimension::U3;
use crate::base::storage::Storage; use crate::base::storage::Storage;
use crate::base::{Const, Scalar, Unit, Vector, Vector3}; use crate::base::{Const, Unit, Vector, Vector3};
use crate::SimdRealField; use crate::SimdRealField;
use crate::geometry::{Point3, Quaternion, Rotation, UnitQuaternion}; use crate::geometry::{Point3, Quaternion, Rotation, UnitQuaternion};
impl<T: Scalar> Index<usize> for Quaternion<T> { impl<T> Index<usize> for Quaternion<T> {
type Output = T; type Output = T;
#[inline] #[inline]
@ -73,7 +73,7 @@ impl<T: Scalar> Index<usize> for Quaternion<T> {
} }
} }
impl<T: Scalar> IndexMut<usize> for Quaternion<T> { impl<T> IndexMut<usize> for Quaternion<T> {
#[inline] #[inline]
fn index_mut(&mut self, i: usize) -> &mut T { fn index_mut(&mut self, i: usize) -> &mut T {
&mut self.coords[i] &mut self.coords[i]
@ -371,12 +371,12 @@ quaternion_op_impl!(
; ;
self: Rotation<T, 3>, rhs: UnitQuaternion<T>, self: Rotation<T, 3>, rhs: UnitQuaternion<T>,
Output = UnitQuaternion<T>; Output = UnitQuaternion<T>;
UnitQuaternion::<T>::from_rotation_matrix(&self) / rhs; ); UnitQuaternion::<T>::from_rotation_matrix(&self) / rhs;);
// UnitQuaternion × Vector // UnitQuaternion × Vector
quaternion_op_impl!( quaternion_op_impl!(
Mul, mul; Mul, mul;
SB: Storage<T, Const<3>> ; SB: Storage<T, Const<3>>;
self: &'a UnitQuaternion<T>, rhs: &'b Vector<T, Const<3>, SB>, self: &'a UnitQuaternion<T>, rhs: &'b Vector<T, Const<3>, SB>,
Output = Vector3<T>; Output = Vector3<T>;
{ {

View File

@ -1,3 +1,5 @@
use std::mem::MaybeUninit;
use crate::base::constraint::{AreMultipliable, DimEq, SameNumberOfRows, ShapeConstraint}; use crate::base::constraint::{AreMultipliable, DimEq, SameNumberOfRows, ShapeConstraint};
use crate::base::{Const, Matrix, Unit, Vector}; use crate::base::{Const, Matrix, Unit, Vector};
use crate::dimension::{Dim, U1}; use crate::dimension::{Dim, U1};
@ -77,40 +79,42 @@ impl<T: ComplexField, D: Dim, S: Storage<T, D>> Reflection<T, D, S> {
pub fn reflect_rows<R2: Dim, C2: Dim, S2, S3>( pub fn reflect_rows<R2: Dim, C2: Dim, S2, S3>(
&self, &self,
lhs: &mut Matrix<T, R2, C2, S2>, lhs: &mut Matrix<T, R2, C2, S2>,
work: &mut Vector<T, R2, S3>, work: &mut Vector<MaybeUninit<T>, R2, S3>,
) where ) where
S2: StorageMut<T, R2, C2>, S2: StorageMut<T, R2, C2>,
S3: StorageMut<T, R2>, S3: StorageMut<MaybeUninit<T>, R2>,
ShapeConstraint: DimEq<C2, D> + AreMultipliable<R2, C2, D, U1>, ShapeConstraint: DimEq<C2, D> + AreMultipliable<R2, C2, D, U1>,
{ {
lhs.mul_to(&self.axis, work); lhs.mul_to(&self.axis, work);
let mut work = unsafe { work.assume_init_mut() };
if !self.bias.is_zero() { if !self.bias.is_zero() {
work.add_scalar_mut(-self.bias); work.add_scalar_mut(-self.bias);
} }
let m_two: T = crate::convert(-2.0f64); let m_two: T = crate::convert(-2.0f64);
lhs.gerc(m_two, work, &self.axis, T::one()); lhs.gerc(m_two, &work, &self.axis, T::one());
} }
/// Applies the reflection to the rows of `lhs`. /// Applies the reflection to the rows of `lhs`.
pub fn reflect_rows_with_sign<R2: Dim, C2: Dim, S2, S3>( pub fn reflect_rows_with_sign<R2: Dim, C2: Dim, S2, S3>(
&self, &self,
lhs: &mut Matrix<T, R2, C2, S2>, lhs: &mut Matrix<T, R2, C2, S2>,
work: &mut Vector<T, R2, S3>, work: &mut Vector<MaybeUninit<T>, R2, S3>,
sign: T, sign: T,
) where ) where
S2: StorageMut<T, R2, C2>, S2: StorageMut<T, R2, C2>,
S3: StorageMut<T, R2>, S3: StorageMut<MaybeUninit<T>, R2>,
ShapeConstraint: DimEq<C2, D> + AreMultipliable<R2, C2, D, U1>, ShapeConstraint: DimEq<C2, D> + AreMultipliable<R2, C2, D, U1>,
{ {
lhs.mul_to(&self.axis, work); lhs.mul_to(&self.axis, work);
let mut work = unsafe { work.assume_init_mut() };
if !self.bias.is_zero() { if !self.bias.is_zero() {
work.add_scalar_mut(-self.bias); work.add_scalar_mut(-self.bias);
} }
let m_two = sign.scale(crate::convert(-2.0f64)); let m_two = sign.scale(crate::convert(-2.0f64));
lhs.gerc(m_two, work, &self.axis, sign); lhs.gerc(m_two, &work, &self.axis, sign);
} }
} }

View File

@ -71,7 +71,7 @@ where
impl<T: Copy, const D: usize> Copy for Rotation<T, D> where Owned<T, Const<D>, Const<D>>: Copy {} impl<T: Copy, const D: usize> Copy for Rotation<T, D> where Owned<T, Const<D>, Const<D>>: Copy {}
impl<T, const D: usize> Clone for Rotation<T, D> impl<T: Clone, const D: usize> Clone for Rotation<T, D>
where where
Owned<T, Const<D>, Const<D>>: Clone, Owned<T, Const<D>, Const<D>>: Clone,
{ {
@ -127,7 +127,7 @@ where
} }
} }
impl<T: Scalar, const D: usize> Rotation<T, D> { impl<T, const D: usize> Rotation<T, D> {
/// Creates a new rotation from the given square matrix. /// Creates a new rotation from the given square matrix.
/// ///
/// The matrix squareness is checked but not its orthonormality. /// The matrix squareness is checked but not its orthonormality.
@ -162,7 +162,7 @@ impl<T: Scalar, const D: usize> Rotation<T, D> {
} }
/// # Conversion to a matrix /// # Conversion to a matrix
impl<T: Scalar, const D: usize> Rotation<T, D> { impl<T, const D: usize> Rotation<T, D> {
/// A reference to the underlying matrix representation of this rotation. /// A reference to the underlying matrix representation of this rotation.
/// ///
/// # Example /// # Example
@ -263,7 +263,7 @@ impl<T: Scalar, const D: usize> Rotation<T, D> {
#[must_use] #[must_use]
pub fn to_homogeneous(&self) -> OMatrix<T, DimNameSum<Const<D>, U1>, DimNameSum<Const<D>, U1>> pub fn to_homogeneous(&self) -> OMatrix<T, DimNameSum<Const<D>, U1>, DimNameSum<Const<D>, U1>>
where where
T: Zero + One, T: Zero + One + Scalar,
Const<D>: DimNameAdd<U1>, Const<D>: DimNameAdd<U1>,
DefaultAllocator: Allocator<T, DimNameSum<Const<D>, U1>, DimNameSum<Const<D>, U1>>, DefaultAllocator: Allocator<T, DimNameSum<Const<D>, U1>, DimNameSum<Const<D>, U1>>,
{ {

View File

@ -1,5 +1,6 @@
use approx::{AbsDiffEq, RelativeEq, UlpsEq}; use approx::{AbsDiffEq, RelativeEq, UlpsEq};
use std::any::Any; use std::any::Any;
use std::fmt;
use std::fmt::Debug; use std::fmt::Debug;
use std::hash; use std::hash;
use std::marker::PhantomData; use std::marker::PhantomData;
@ -7,7 +8,7 @@ use std::marker::PhantomData;
#[cfg(feature = "serde-serialize-no-std")] #[cfg(feature = "serde-serialize-no-std")]
use serde::{Deserialize, Deserializer, Serialize, Serializer}; use serde::{Deserialize, Deserializer, Serialize, Serializer};
use simba::scalar::RealField; use simba::scalar::{ComplexField, RealField};
use crate::base::allocator::Allocator; use crate::base::allocator::Allocator;
use crate::base::dimension::{DimNameAdd, DimNameSum, U1}; use crate::base::dimension::{DimNameAdd, DimNameSum, U1};
@ -119,7 +120,7 @@ macro_rules! category_mul_impl(
)*} )*}
); );
// We require stability uppon multiplication. // We require stability upon multiplication.
impl<T: TCategory> TCategoryMul<T> for T { impl<T: TCategory> TCategoryMul<T> for T {
type Representative = T; type Representative = T;
} }
@ -157,8 +158,7 @@ super_tcategory_impl!(
/// It is stored as a matrix with dimensions `(D + 1, D + 1)`, e.g., it stores a 4x4 matrix for a /// It is stored as a matrix with dimensions `(D + 1, D + 1)`, e.g., it stores a 4x4 matrix for a
/// 3D transformation. /// 3D transformation.
#[repr(C)] #[repr(C)]
#[derive(Debug)] pub struct Transform<T, C: TCategory, const D: usize>
pub struct Transform<T: RealField, C: TCategory, const D: usize>
where where
Const<D>: DimNameAdd<U1>, Const<D>: DimNameAdd<U1>,
DefaultAllocator: Allocator<T, DimNameSum<Const<D>, U1>, DimNameSum<Const<D>, U1>>, DefaultAllocator: Allocator<T, DimNameSum<Const<D>, U1>, DimNameSum<Const<D>, U1>>,
@ -167,7 +167,7 @@ where
_phantom: PhantomData<C>, _phantom: PhantomData<C>,
} }
impl<T: RealField + hash::Hash, C: TCategory, const D: usize> hash::Hash for Transform<T, C, D> impl<T: hash::Hash, C: TCategory, const D: usize> hash::Hash for Transform<T, C, D>
where where
Const<D>: DimNameAdd<U1>, Const<D>: DimNameAdd<U1>,
DefaultAllocator: Allocator<T, DimNameSum<Const<D>, U1>, DimNameSum<Const<D>, U1>>, DefaultAllocator: Allocator<T, DimNameSum<Const<D>, U1>, DimNameSum<Const<D>, U1>>,
@ -178,7 +178,7 @@ where
} }
} }
impl<T: RealField, C: TCategory, const D: usize> Copy for Transform<T, C, D> impl<T: Copy, C: TCategory, const D: usize> Copy for Transform<T, C, D>
where where
Const<D>: DimNameAdd<U1>, Const<D>: DimNameAdd<U1>,
DefaultAllocator: Allocator<T, DimNameSum<Const<D>, U1>, DimNameSum<Const<D>, U1>>, DefaultAllocator: Allocator<T, DimNameSum<Const<D>, U1>, DimNameSum<Const<D>, U1>>,
@ -186,10 +186,11 @@ where
{ {
} }
impl<T: RealField, C: TCategory, const D: usize> Clone for Transform<T, C, D> impl<T: Clone, C: TCategory, const D: usize> Clone for Transform<T, C, D>
where where
Const<D>: DimNameAdd<U1>, Const<D>: DimNameAdd<U1>,
DefaultAllocator: Allocator<T, DimNameSum<Const<D>, U1>, DimNameSum<Const<D>, U1>>, DefaultAllocator: Allocator<T, DimNameSum<Const<D>, U1>, DimNameSum<Const<D>, U1>>,
Owned<T, DimNameSum<Const<D>, U1>, DimNameSum<Const<D>, U1>>: Clone,
{ {
#[inline] #[inline]
fn clone(&self) -> Self { fn clone(&self) -> Self {
@ -197,8 +198,21 @@ where
} }
} }
impl<T: Debug, C: TCategory, const D: usize> Debug for Transform<T, C, D>
where
Const<D>: DimNameAdd<U1>,
DefaultAllocator: Allocator<T, DimNameSum<Const<D>, U1>, DimNameSum<Const<D>, U1>>,
Owned<T, DimNameSum<Const<D>, U1>, DimNameSum<Const<D>, U1>>: Debug,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("Transform")
.field("matrix", &self.matrix)
.finish()
}
}
#[cfg(feature = "serde-serialize-no-std")] #[cfg(feature = "serde-serialize-no-std")]
impl<T: RealField, C: TCategory, const D: usize> Serialize for Transform<T, C, D> impl<T, C: TCategory, const D: usize> Serialize for Transform<T, C, D>
where where
Const<D>: DimNameAdd<U1>, Const<D>: DimNameAdd<U1>,
DefaultAllocator: Allocator<T, DimNameSum<Const<D>, U1>, DimNameSum<Const<D>, U1>>, DefaultAllocator: Allocator<T, DimNameSum<Const<D>, U1>, DimNameSum<Const<D>, U1>>,
@ -213,7 +227,7 @@ where
} }
#[cfg(feature = "serde-serialize-no-std")] #[cfg(feature = "serde-serialize-no-std")]
impl<'a, T: RealField, C: TCategory, const D: usize> Deserialize<'a> for Transform<T, C, D> impl<'a, T, C: TCategory, const D: usize> Deserialize<'a> for Transform<T, C, D>
where where
Const<D>: DimNameAdd<U1>, Const<D>: DimNameAdd<U1>,
DefaultAllocator: Allocator<T, DimNameSum<Const<D>, U1>, DimNameSum<Const<D>, U1>>, DefaultAllocator: Allocator<T, DimNameSum<Const<D>, U1>, DimNameSum<Const<D>, U1>>,
@ -231,14 +245,14 @@ where
} }
} }
impl<T: RealField + Eq, C: TCategory, const D: usize> Eq for Transform<T, C, D> impl<T: Eq, C: TCategory, const D: usize> Eq for Transform<T, C, D>
where where
Const<D>: DimNameAdd<U1>, Const<D>: DimNameAdd<U1>,
DefaultAllocator: Allocator<T, DimNameSum<Const<D>, U1>, DimNameSum<Const<D>, U1>>, DefaultAllocator: Allocator<T, DimNameSum<Const<D>, U1>, DimNameSum<Const<D>, U1>>,
{ {
} }
impl<T: RealField, C: TCategory, const D: usize> PartialEq for Transform<T, C, D> impl<T: PartialEq, C: TCategory, const D: usize> PartialEq for Transform<T, C, D>
where where
Const<D>: DimNameAdd<U1>, Const<D>: DimNameAdd<U1>,
DefaultAllocator: Allocator<T, DimNameSum<Const<D>, U1>, DimNameSum<Const<D>, U1>>, DefaultAllocator: Allocator<T, DimNameSum<Const<D>, U1>, DimNameSum<Const<D>, U1>>,
@ -249,7 +263,7 @@ where
} }
} }
impl<T: RealField, C: TCategory, const D: usize> Transform<T, C, D> impl<T, C: TCategory, const D: usize> Transform<T, C, D>
where where
Const<D>: DimNameAdd<U1>, Const<D>: DimNameAdd<U1>,
DefaultAllocator: Allocator<T, DimNameSum<Const<D>, U1>, DimNameSum<Const<D>, U1>>, DefaultAllocator: Allocator<T, DimNameSum<Const<D>, U1>, DimNameSum<Const<D>, U1>>,
@ -354,7 +368,10 @@ where
#[deprecated( #[deprecated(
note = "This method is redundant with automatic `Copy` and the `.clone()` method and will be removed in a future release." note = "This method is redundant with automatic `Copy` and the `.clone()` method and will be removed in a future release."
)] )]
pub fn clone_owned(&self) -> Transform<T, C, D> { pub fn clone_owned(&self) -> Transform<T, C, D>
where
T: Clone,
{
Transform::from_matrix_unchecked(self.matrix.clone_owned()) Transform::from_matrix_unchecked(self.matrix.clone_owned())
} }
@ -372,7 +389,10 @@ where
/// ``` /// ```
#[inline] #[inline]
#[must_use] #[must_use]
pub fn to_homogeneous(&self) -> OMatrix<T, DimNameSum<Const<D>, U1>, DimNameSum<Const<D>, U1>> { pub fn to_homogeneous(&self) -> OMatrix<T, DimNameSum<Const<D>, U1>, DimNameSum<Const<D>, U1>>
where
T: Clone,
{
self.matrix().clone_owned() self.matrix().clone_owned()
} }
@ -401,7 +421,10 @@ where
/// ``` /// ```
#[inline] #[inline]
#[must_use = "Did you mean to use try_inverse_mut()?"] #[must_use = "Did you mean to use try_inverse_mut()?"]
pub fn try_inverse(self) -> Option<Transform<T, C, D>> { pub fn try_inverse(self) -> Option<Transform<T, C, D>>
where
T: ComplexField,
{
self.matrix self.matrix
.try_inverse() .try_inverse()
.map(Transform::from_matrix_unchecked) .map(Transform::from_matrix_unchecked)
@ -427,6 +450,7 @@ where
#[must_use = "Did you mean to use inverse_mut()?"] #[must_use = "Did you mean to use inverse_mut()?"]
pub fn inverse(self) -> Transform<T, C, D> pub fn inverse(self) -> Transform<T, C, D>
where where
T: ComplexField,
C: SubTCategoryOf<TProjective>, C: SubTCategoryOf<TProjective>,
{ {
// TODO: specialize for TAffine? // TODO: specialize for TAffine?
@ -458,7 +482,10 @@ where
/// assert!(!t.try_inverse_mut()); /// assert!(!t.try_inverse_mut());
/// ``` /// ```
#[inline] #[inline]
pub fn try_inverse_mut(&mut self) -> bool { pub fn try_inverse_mut(&mut self) -> bool
where
T: ComplexField,
{
self.matrix.try_inverse_mut() self.matrix.try_inverse_mut()
} }
@ -482,6 +509,7 @@ where
#[inline] #[inline]
pub fn inverse_mut(&mut self) pub fn inverse_mut(&mut self)
where where
T: ComplexField,
C: SubTCategoryOf<TProjective>, C: SubTCategoryOf<TProjective>,
{ {
let _ = self.matrix.try_inverse_mut(); let _ = self.matrix.try_inverse_mut();

View File

@ -29,7 +29,7 @@ pub struct Translation<T, const D: usize> {
pub vector: SVector<T, D>, pub vector: SVector<T, D>,
} }
impl<T: Scalar + hash::Hash, const D: usize> hash::Hash for Translation<T, D> impl<T: hash::Hash, const D: usize> hash::Hash for Translation<T, D>
where where
Owned<T, Const<D>>: hash::Hash, Owned<T, Const<D>>: hash::Hash,
{ {
@ -38,9 +38,9 @@ where
} }
} }
impl<T: Scalar + Copy, const D: usize> Copy for Translation<T, D> {} impl<T: Copy, const D: usize> Copy for Translation<T, D> {}
impl<T: Scalar, const D: usize> Clone for Translation<T, D> impl<T: Clone, const D: usize> Clone for Translation<T, D>
where where
Owned<T, Const<D>>: Clone, Owned<T, Const<D>>: Clone,
{ {
@ -53,7 +53,6 @@ where
#[cfg(feature = "abomonation-serialize")] #[cfg(feature = "abomonation-serialize")]
impl<T, const D: usize> Abomonation for Translation<T, D> impl<T, const D: usize> Abomonation for Translation<T, D>
where where
T: Scalar,
SVector<T, D>: Abomonation, SVector<T, D>: Abomonation,
{ {
unsafe fn entomb<W: Write>(&self, writer: &mut W) -> IOResult<()> { unsafe fn entomb<W: Write>(&self, writer: &mut W) -> IOResult<()> {
@ -70,7 +69,7 @@ where
} }
#[cfg(feature = "serde-serialize-no-std")] #[cfg(feature = "serde-serialize-no-std")]
impl<T: Scalar, const D: usize> Serialize for Translation<T, D> impl<T, const D: usize> Serialize for Translation<T, D>
where where
Owned<T, Const<D>>: Serialize, Owned<T, Const<D>>: Serialize,
{ {
@ -83,7 +82,7 @@ where
} }
#[cfg(feature = "serde-serialize-no-std")] #[cfg(feature = "serde-serialize-no-std")]
impl<'a, T: Scalar, const D: usize> Deserialize<'a> for Translation<T, D> impl<'a, T, const D: usize> Deserialize<'a> for Translation<T, D>
where where
Owned<T, Const<D>>: Deserialize<'a>, Owned<T, Const<D>>: Deserialize<'a>,
{ {
@ -140,7 +139,7 @@ mod rkyv_impl {
} }
} }
impl<T: Scalar, const D: usize> Translation<T, D> { impl<T, const D: usize> Translation<T, D> {
/// Creates a new translation from the given vector. /// Creates a new translation from the given vector.
#[inline] #[inline]
#[deprecated(note = "Use `::from` instead.")] #[deprecated(note = "Use `::from` instead.")]
@ -166,7 +165,7 @@ impl<T: Scalar, const D: usize> Translation<T, D> {
#[must_use = "Did you mean to use inverse_mut()?"] #[must_use = "Did you mean to use inverse_mut()?"]
pub fn inverse(&self) -> Translation<T, D> pub fn inverse(&self) -> Translation<T, D>
where where
T: ClosedNeg, T: ClosedNeg + Scalar,
{ {
Translation::from(-&self.vector) Translation::from(-&self.vector)
} }
@ -193,7 +192,7 @@ impl<T: Scalar, const D: usize> Translation<T, D> {
#[must_use] #[must_use]
pub fn to_homogeneous(&self) -> OMatrix<T, DimNameSum<Const<D>, U1>, DimNameSum<Const<D>, U1>> pub fn to_homogeneous(&self) -> OMatrix<T, DimNameSum<Const<D>, U1>, DimNameSum<Const<D>, U1>>
where where
T: Zero + One, T: Zero + One + Scalar,
Const<D>: DimNameAdd<U1>, Const<D>: DimNameAdd<U1>,
DefaultAllocator: Allocator<T, DimNameSum<Const<D>, U1>, DimNameSum<Const<D>, U1>>, DefaultAllocator: Allocator<T, DimNameSum<Const<D>, U1>, DimNameSum<Const<D>, U1>>,
{ {
@ -224,7 +223,7 @@ impl<T: Scalar, const D: usize> Translation<T, D> {
#[inline] #[inline]
pub fn inverse_mut(&mut self) pub fn inverse_mut(&mut self)
where where
T: ClosedNeg, T: ClosedNeg + Scalar,
{ {
self.vector.neg_mut() self.vector.neg_mut()
} }
@ -264,16 +263,16 @@ impl<T: Scalar + ClosedSub, const D: usize> Translation<T, D> {
} }
} }
impl<T: Scalar + Eq, const D: usize> Eq for Translation<T, D> {} impl<T: Eq, const D: usize> Eq for Translation<T, D> {}
impl<T: Scalar + PartialEq, const D: usize> PartialEq for Translation<T, D> { impl<T: PartialEq, const D: usize> PartialEq for Translation<T, D> {
#[inline] #[inline]
fn eq(&self, right: &Translation<T, D>) -> bool { fn eq(&self, right: &Translation<T, D>) -> bool {
self.vector == right.vector self.vector == right.vector
} }
} }
impl<T: Scalar + AbsDiffEq, const D: usize> AbsDiffEq for Translation<T, D> impl<T: AbsDiffEq, const D: usize> AbsDiffEq for Translation<T, D>
where where
T::Epsilon: Copy, T::Epsilon: Copy,
{ {
@ -290,7 +289,7 @@ where
} }
} }
impl<T: Scalar + RelativeEq, const D: usize> RelativeEq for Translation<T, D> impl<T: RelativeEq, const D: usize> RelativeEq for Translation<T, D>
where where
T::Epsilon: Copy, T::Epsilon: Copy,
{ {
@ -311,7 +310,7 @@ where
} }
} }
impl<T: Scalar + UlpsEq, const D: usize> UlpsEq for Translation<T, D> impl<T: UlpsEq, const D: usize> UlpsEq for Translation<T, D>
where where
T::Epsilon: Copy, T::Epsilon: Copy,
{ {

View File

@ -27,8 +27,7 @@ use crate::Point;
impl<T1, T2, const D: usize> SubsetOf<Translation<T2, D>> for Translation<T1, D> impl<T1, T2, const D: usize> SubsetOf<Translation<T2, D>> for Translation<T1, D>
where where
T1: Scalar, T2: SupersetOf<T1>,
T2: Scalar + SupersetOf<T1>,
{ {
#[inline] #[inline]
fn to_superset(&self) -> Translation<T2, D> { fn to_superset(&self) -> Translation<T2, D> {
@ -193,14 +192,14 @@ where
} }
} }
impl<T: Scalar, const D: usize> From<OVector<T, Const<D>>> for Translation<T, D> { impl<T, const D: usize> From<OVector<T, Const<D>>> for Translation<T, D> {
#[inline] #[inline]
fn from(vector: OVector<T, Const<D>>) -> Self { fn from(vector: OVector<T, Const<D>>) -> Self {
Translation { vector } Translation { vector }
} }
} }
impl<T: Scalar, const D: usize> From<[T; D]> for Translation<T, D> { impl<T, const D: usize> From<[T; D]> for Translation<T, D> {
#[inline] #[inline]
fn from(coords: [T; D]) -> Self { fn from(coords: [T; D]) -> Self {
Translation { Translation {
@ -209,14 +208,14 @@ impl<T: Scalar, const D: usize> From<[T; D]> for Translation<T, D> {
} }
} }
impl<T: Scalar, const D: usize> From<Point<T, D>> for Translation<T, D> { impl<T, const D: usize> From<Point<T, D>> for Translation<T, D> {
#[inline] #[inline]
fn from(pt: Point<T, D>) -> Self { fn from(pt: Point<T, D>) -> Self {
Translation { vector: pt.coords } Translation { vector: pt.coords }
} }
} }
impl<T: Scalar, const D: usize> From<Translation<T, D>> for [T; D] { impl<T, const D: usize> From<Translation<T, D>> for [T; D] {
#[inline] #[inline]
fn from(t: Translation<T, D>) -> Self { fn from(t: Translation<T, D>) -> Self {
t.vector.into() t.vector.into()

View File

@ -1,10 +1,13 @@
use std::fmt;
#[cfg(feature = "serde-serialize-no-std")] #[cfg(feature = "serde-serialize-no-std")]
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::allocator::Allocator; use crate::allocator::Allocator;
use crate::base::{DefaultAllocator, Matrix, OMatrix, OVector, Unit}; use crate::base::{DefaultAllocator, Matrix, OMatrix, OVector, Unit};
use crate::dimension::{Const, Dim, DimDiff, DimMin, DimMinimum, DimSub, U1}; use crate::dimension::{Const, Dim, DimDiff, DimMin, DimMinimum, DimSub, U1};
use crate::storage::Storage; use crate::storage::{Owned, Storage};
use crate::{Dynamic, };
use simba::scalar::ComplexField; use simba::scalar::ComplexField;
use crate::geometry::Reflection; use crate::geometry::Reflection;
@ -32,7 +35,6 @@ use crate::linalg::householder;
OVector<T, DimMinimum<R, C>>: Deserialize<'de>, OVector<T, DimMinimum<R, C>>: Deserialize<'de>,
OVector<T, DimDiff<DimMinimum<R, C>, U1>>: Deserialize<'de>")) OVector<T, DimDiff<DimMinimum<R, C>, U1>>: Deserialize<'de>"))
)] )]
#[derive(Clone, Debug)]
pub struct Bidiagonal<T: ComplexField, R: DimMin<C>, C: Dim> pub struct Bidiagonal<T: ComplexField, R: DimMin<C>, C: Dim>
where where
DimMinimum<R, C>: DimSub<U1>, DimMinimum<R, C>: DimSub<U1>,
@ -50,18 +52,58 @@ where
upper_diagonal: bool, upper_diagonal: bool,
} }
impl<T: ComplexField, R: DimMin<C>, C: Dim> Clone for Bidiagonal<T, R, C>
where
DimMinimum<R, C>: DimSub<U1>,
DefaultAllocator: Allocator<T, R, C>
+ Allocator<T, DimMinimum<R, C>>
+ Allocator<T, DimDiff<DimMinimum<R, C>, U1>>,
Owned<T, R, C>: Clone,
Owned<T, DimMinimum<R, C>>: Clone,
Owned<T, DimDiff<DimMinimum<R, C>, U1>>: Clone,
{
fn clone(&self) -> Self {
Self {
uv: self.uv.clone(),
diagonal: self.diagonal.clone(),
off_diagonal: self.off_diagonal.clone(),
upper_diagonal: self.upper_diagonal,
}
}
}
impl<T: ComplexField, R: DimMin<C>, C: Dim> Copy for Bidiagonal<T, R, C> impl<T: ComplexField, R: DimMin<C>, C: Dim> Copy for Bidiagonal<T, R, C>
where where
DimMinimum<R, C>: DimSub<U1>, DimMinimum<R, C>: DimSub<U1>,
DefaultAllocator: Allocator<T, R, C> DefaultAllocator: Allocator<T, R, C>
+ Allocator<T, DimMinimum<R, C>> + Allocator<T, DimMinimum<R, C>>
+ Allocator<T, DimDiff<DimMinimum<R, C>, U1>>, + Allocator<T, DimDiff<DimMinimum<R, C>, U1>>,
OMatrix<T, R, C>: Copy, Owned<T, R, C>: Copy,
OVector<T, DimMinimum<R, C>>: Copy, Owned<T, DimMinimum<R, C>>: Copy,
OVector<T, DimDiff<DimMinimum<R, C>, U1>>: Copy, Owned<T, DimDiff<DimMinimum<R, C>, U1>>: Copy,
{ {
} }
impl<T: ComplexField, R: DimMin<C>, C: Dim> fmt::Debug for Bidiagonal<T, R, C>
where
DimMinimum<R, C>: DimSub<U1>,
DefaultAllocator: Allocator<T, R, C>
+ Allocator<T, DimMinimum<R, C>>
+ Allocator<T, DimDiff<DimMinimum<R, C>, U1>>,
Owned<T, R, C>: fmt::Debug,
Owned<T, DimMinimum<R, C>>: fmt::Debug,
Owned<T, DimDiff<DimMinimum<R, C>, U1>>: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("Bidiagonal")
.field("uv", &self.uv)
.field("diagonal", &self.diagonal)
.field("off_diagonal", &self.off_diagonal)
.field("upper_diagonal", &self.upper_diagonal)
.finish()
}
}
impl<T: ComplexField, R: DimMin<C>, C: Dim> Bidiagonal<T, R, C> impl<T: ComplexField, R: DimMin<C>, C: Dim> Bidiagonal<T, R, C>
where where
DimMinimum<R, C>: DimSub<U1>, DimMinimum<R, C>: DimSub<U1>,
@ -81,25 +123,25 @@ where
"Cannot compute the bidiagonalization of an empty matrix." "Cannot compute the bidiagonalization of an empty matrix."
); );
let mut diagonal = let mut diagonal = Matrix::new_uninitialized_generic(min_nrows_ncols, Const::<1>);
unsafe { crate::unimplemented_or_uninitialized_generic!(min_nrows_ncols, Const::<1>) }; let mut off_diagonal =
let mut off_diagonal = unsafe { Matrix::new_uninitialized_generic(min_nrows_ncols.sub(Const::<1>), Const::<1>);
crate::unimplemented_or_uninitialized_generic!( let mut axis_packed = Matrix::new_uninitialized_generic(ncols, Const::<1>);
min_nrows_ncols.sub(Const::<1>), let mut work = Matrix::new_uninitialized_generic(nrows, Const::<1>);
Const::<1>
)
};
let mut axis_packed =
unsafe { crate::unimplemented_or_uninitialized_generic!(ncols, Const::<1>) };
let mut work = unsafe { crate::unimplemented_or_uninitialized_generic!(nrows, Const::<1>) };
let upper_diagonal = nrows.value() >= ncols.value(); let upper_diagonal = nrows.value() >= ncols.value();
if upper_diagonal { if upper_diagonal {
for ite in 0..dim - 1 { for ite in 0..dim - 1 {
householder::clear_column_unchecked(&mut matrix, &mut diagonal[ite], ite, 0, None); householder::clear_column_unchecked(
&mut matrix,
diagonal[ite].as_mut_ptr(),
ite,
0,
None,
);
householder::clear_row_unchecked( householder::clear_row_unchecked(
&mut matrix, &mut matrix,
&mut off_diagonal[ite], off_diagonal[ite].as_mut_ptr(),
&mut axis_packed, &mut axis_packed,
&mut work, &mut work,
ite, ite,
@ -109,7 +151,7 @@ where
householder::clear_column_unchecked( householder::clear_column_unchecked(
&mut matrix, &mut matrix,
&mut diagonal[dim - 1], diagonal[dim - 1].as_mut_ptr(),
dim - 1, dim - 1,
0, 0,
None, None,
@ -118,7 +160,7 @@ where
for ite in 0..dim - 1 { for ite in 0..dim - 1 {
householder::clear_row_unchecked( householder::clear_row_unchecked(
&mut matrix, &mut matrix,
&mut diagonal[ite], diagonal[ite].as_mut_ptr(),
&mut axis_packed, &mut axis_packed,
&mut work, &mut work,
ite, ite,
@ -126,7 +168,7 @@ where
); );
householder::clear_column_unchecked( householder::clear_column_unchecked(
&mut matrix, &mut matrix,
&mut off_diagonal[ite], off_diagonal[ite].as_mut_ptr(),
ite, ite,
1, 1,
None, None,
@ -135,7 +177,7 @@ where
householder::clear_row_unchecked( householder::clear_row_unchecked(
&mut matrix, &mut matrix,
&mut diagonal[dim - 1], diagonal[dim - 1].as_mut_ptr(),
&mut axis_packed, &mut axis_packed,
&mut work, &mut work,
dim - 1, dim - 1,
@ -145,8 +187,8 @@ where
Bidiagonal { Bidiagonal {
uv: matrix, uv: matrix,
diagonal, diagonal: diagonal.assume_init(),
off_diagonal, off_diagonal: off_diagonal.assume_init(),
upper_diagonal, upper_diagonal,
} }
} }
@ -243,23 +285,23 @@ where
#[must_use] #[must_use]
pub fn v_t(&self) -> OMatrix<T, DimMinimum<R, C>, C> pub fn v_t(&self) -> OMatrix<T, DimMinimum<R, C>, C>
where where
DefaultAllocator: Allocator<T, DimMinimum<R, C>, C>, DefaultAllocator: Allocator<T, DimMinimum<R, C>, C> + Allocator<T, Dynamic, U1>,
{ {
let (nrows, ncols) = self.uv.data.shape(); let (nrows, ncols) = self.uv.data.shape();
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 = let mut work = Matrix::new_uninitialized_generic(min_nrows_ncols, Const::<1>);
unsafe { crate::unimplemented_or_uninitialized_generic!(min_nrows_ncols, Const::<1>) }; let mut axis_packed = Matrix::new_uninitialized_generic(ncols, Const::<1>);
let mut axis_packed =
unsafe { crate::unimplemented_or_uninitialized_generic!(ncols, Const::<1>) };
let shift = self.axis_shift().1; let shift = self.axis_shift().1;
for i in (0..min_nrows_ncols.value() - shift).rev() { for i in (0..min_nrows_ncols.value() - shift).rev() {
let axis = self.uv.slice_range(i, i + shift..); let axis = self.uv.slice_range(i, i + shift..);
let mut axis_packed = axis_packed.rows_range_mut(i + shift..); let mut axis_packed = axis_packed.rows_range_mut(i + shift..);
axis_packed.tr_copy_from(&axis); axis_packed.tr_copy_init_from(&axis);
let mut axis_packed = unsafe { axis_packed.slice_assume_init() };
// TODO: sometimes, the axis might have a zero magnitude. // TODO: sometimes, the axis might have a zero magnitude.
let refl = Reflection::new(Unit::new_unchecked(axis_packed), T::zero()); let refl = Reflection::new(Unit::new_unchecked(axis_packed), T::zero());

View File

@ -1,3 +1,6 @@
use std::fmt;
use std::mem::MaybeUninit;
#[cfg(feature = "serde-serialize-no-std")] #[cfg(feature = "serde-serialize-no-std")]
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -9,7 +12,7 @@ use crate::allocator::Allocator;
use crate::base::{Const, DefaultAllocator, Matrix, OMatrix, Vector}; use crate::base::{Const, DefaultAllocator, Matrix, OMatrix, Vector};
use crate::constraint::{SameNumberOfRows, ShapeConstraint}; use crate::constraint::{SameNumberOfRows, ShapeConstraint};
use crate::dimension::{Dim, DimAdd, DimDiff, DimSub, DimSum, U1}; use crate::dimension::{Dim, DimAdd, DimDiff, DimSub, DimSum, U1};
use crate::storage::{Storage, StorageMut}; use crate::storage::{Owned, Storage, StorageMut};
/// The Cholesky decomposition of a symmetric-definite-positive matrix. /// The Cholesky decomposition of a symmetric-definite-positive matrix.
#[cfg_attr(feature = "serde-serialize-no-std", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde-serialize-no-std", derive(Serialize, Deserialize))]
@ -23,7 +26,6 @@ use crate::storage::{Storage, StorageMut};
serde(bound(deserialize = "DefaultAllocator: Allocator<T, D>, serde(bound(deserialize = "DefaultAllocator: Allocator<T, D>,
OMatrix<T, D, D>: Deserialize<'de>")) OMatrix<T, D, D>: Deserialize<'de>"))
)] )]
#[derive(Clone, Debug)]
pub struct Cholesky<T: SimdComplexField, D: Dim> pub struct Cholesky<T: SimdComplexField, D: Dim>
where where
DefaultAllocator: Allocator<T, D, D>, DefaultAllocator: Allocator<T, D, D>,
@ -34,10 +36,34 @@ where
impl<T: SimdComplexField, D: Dim> Copy for Cholesky<T, D> impl<T: SimdComplexField, D: Dim> Copy for Cholesky<T, D>
where where
DefaultAllocator: Allocator<T, D, D>, DefaultAllocator: Allocator<T, D, D>,
OMatrix<T, D, D>: Copy, Owned<T, D, D>: Copy,
{ {
} }
impl<T: SimdComplexField, D: Dim> Clone for Cholesky<T, D>
where
DefaultAllocator: Allocator<T, D, D>,
Owned<T, D, D>: Clone,
{
fn clone(&self) -> Self {
Self {
chol: self.chol.clone(),
}
}
}
impl<T: SimdComplexField, D: Dim> fmt::Debug for Cholesky<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("Cholesky")
.field("chol", &self.chol)
.finish()
}
}
impl<T: SimdComplexField, D: Dim> Cholesky<T, D> impl<T: SimdComplexField, D: Dim> Cholesky<T, D>
where where
DefaultAllocator: Allocator<T, D, D>, DefaultAllocator: Allocator<T, D, D>,
@ -226,6 +252,8 @@ where
DefaultAllocator: Allocator<T, DimSum<D, U1>, DimSum<D, U1>> + Allocator<T, R2>, DefaultAllocator: Allocator<T, DimSum<D, U1>, DimSum<D, U1>> + Allocator<T, R2>,
ShapeConstraint: SameNumberOfRows<R2, DimSum<D, U1>>, ShapeConstraint: SameNumberOfRows<R2, DimSum<D, U1>>,
{ {
// TODO: check that MaybeUninit manipulations are sound!
let mut col = col.into_owned(); let mut col = col.into_owned();
// for an explanation of the formulas, see https://en.wikipedia.org/wiki/Cholesky_decomposition#Updating_the_decomposition // for an explanation of the formulas, see https://en.wikipedia.org/wiki/Cholesky_decomposition#Updating_the_decomposition
let n = col.nrows(); let n = col.nrows();
@ -237,20 +265,20 @@ where
assert!(j < n, "j needs to be within the bound of the new matrix."); assert!(j < n, "j needs to be within the bound of the new matrix.");
// 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 = Matrix::new_uninitialized_generic(
crate::unimplemented_or_uninitialized_generic!(
self.chol.data.shape().0.add(Const::<1>), self.chol.data.shape().0.add(Const::<1>),
self.chol.data.shape().1.add(Const::<1>) self.chol.data.shape().1.add(Const::<1>),
) );
};
// TODO: checked that every entry is initialized EXACTLY once.
chol.slice_range_mut(..j, ..j) chol.slice_range_mut(..j, ..j)
.copy_from(&self.chol.slice_range(..j, ..j)); .copy_init_from(&self.chol.slice_range(..j, ..j));
chol.slice_range_mut(..j, j + 1..) chol.slice_range_mut(..j, j + 1..)
.copy_from(&self.chol.slice_range(..j, j..)); .copy_init_from(&self.chol.slice_range(..j, j..));
chol.slice_range_mut(j + 1.., ..j) chol.slice_range_mut(j + 1.., ..j)
.copy_from(&self.chol.slice_range(j.., ..j)); .copy_init_from(&self.chol.slice_range(j.., ..j));
chol.slice_range_mut(j + 1.., j + 1..) chol.slice_range_mut(j + 1.., j + 1..)
.copy_from(&self.chol.slice_range(j.., j..)); .copy_init_from(&self.chol.slice_range(j.., j..));
// update the jth row // update the jth row
let top_left_corner = self.chol.slice_range(..j, ..j); let top_left_corner = self.chol.slice_range(..j, ..j);
@ -266,7 +294,7 @@ where
// update the center element // update the center element
let center_element = T::sqrt(col_j - T::from_real(new_rowj_adjoint.norm_squared())); let center_element = T::sqrt(col_j - T::from_real(new_rowj_adjoint.norm_squared()));
chol[(j, j)] = center_element; chol[(j, j)] = MaybeUninit::new(center_element);
// update the jth column // update the jth column
let bottom_left_corner = self.chol.slice_range(j.., ..j); let bottom_left_corner = self.chol.slice_range(j.., ..j);
@ -277,7 +305,9 @@ where
&new_rowj_adjoint, &new_rowj_adjoint,
T::one() / center_element, T::one() / center_element,
); );
chol.slice_range_mut(j + 1.., j).copy_from(&new_colj); chol.slice_range_mut(j + 1.., j).copy_init_from(&new_colj);
let chol = unsafe { chol.assume_init() };
// update the bottom right corner // update the bottom right corner
let mut bottom_right_corner = chol.slice_range_mut(j + 1.., j + 1..); let mut bottom_right_corner = chol.slice_range_mut(j + 1.., j + 1..);
@ -298,25 +328,27 @@ where
D: DimSub<U1>, D: DimSub<U1>,
DefaultAllocator: Allocator<T, DimDiff<D, U1>, DimDiff<D, U1>> + Allocator<T, D>, DefaultAllocator: Allocator<T, DimDiff<D, U1>, DimDiff<D, U1>> + Allocator<T, D>,
{ {
// TODO: check that MaybeUninit manipulations are sound!
let n = self.chol.nrows(); let n = self.chol.nrows();
assert!(n > 0, "The matrix needs at least one column."); assert!(n > 0, "The matrix needs at least one column.");
assert!(j < n, "j needs to be within the bound of the matrix."); assert!(j < n, "j needs to be within the bound of the matrix.");
// 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 = Matrix::new_uninitialized_generic(
crate::unimplemented_or_uninitialized_generic!(
self.chol.data.shape().0.sub(Const::<1>), self.chol.data.shape().0.sub(Const::<1>),
self.chol.data.shape().1.sub(Const::<1>) self.chol.data.shape().1.sub(Const::<1>),
) );
};
chol.slice_range_mut(..j, ..j) chol.slice_range_mut(..j, ..j)
.copy_from(&self.chol.slice_range(..j, ..j)); .copy_init_from(&self.chol.slice_range(..j, ..j));
chol.slice_range_mut(..j, j..) chol.slice_range_mut(..j, j..)
.copy_from(&self.chol.slice_range(..j, j + 1..)); .copy_init_from(&self.chol.slice_range(..j, j + 1..));
chol.slice_range_mut(j.., ..j) chol.slice_range_mut(j.., ..j)
.copy_from(&self.chol.slice_range(j + 1.., ..j)); .copy_init_from(&self.chol.slice_range(j + 1.., ..j));
chol.slice_range_mut(j.., j..) chol.slice_range_mut(j.., j..)
.copy_from(&self.chol.slice_range(j + 1.., j + 1..)); .copy_init_from(&self.chol.slice_range(j + 1.., j + 1..));
let chol = unsafe { chol.assume_init() };
// updates the bottom right corner // updates the bottom right corner
let mut bottom_right_corner = chol.slice_range_mut(j.., j..); let mut bottom_right_corner = chol.slice_range_mut(j.., j..);
@ -332,14 +364,12 @@ where
/// ///
/// This helper method is called by `rank_one_update` but also `insert_column` and `remove_column` /// This helper method is called by `rank_one_update` but also `insert_column` and `remove_column`
/// where it is used on a square slice of the decomposition /// where it is used on a square slice of the decomposition
fn xx_rank_one_update<Dm, Sm, Rx, Sx>( fn xx_rank_one_update<Dm: Dim, Sm, Rx: Dim, Sx>(
chol: &mut Matrix<T, Dm, Dm, Sm>, chol: &mut Matrix<T, Dm, Dm, Sm>,
x: &mut Vector<T, Rx, Sx>, x: &mut Vector<T, Rx, Sx>,
sigma: T::RealField, sigma: T::RealField,
) where ) where
//T: ComplexField, //T: ComplexField,
Dm: Dim,
Rx: Dim,
Sm: StorageMut<T, Dm, Dm>, Sm: StorageMut<T, Dm, Dm>,
Sx: StorageMut<T, Rx, U1>, Sx: StorageMut<T, Rx, U1>,
{ {

View File

@ -1,5 +1,7 @@
//! Construction of householder elementary reflections. //! Construction of householder elementary reflections.
use std::mem::MaybeUninit;
use crate::allocator::Allocator; use crate::allocator::Allocator;
use crate::base::{DefaultAllocator, OMatrix, OVector, Unit, Vector}; use crate::base::{DefaultAllocator, OMatrix, OVector, Unit, Vector};
use crate::dimension::Dim; use crate::dimension::Dim;
@ -46,7 +48,7 @@ pub fn reflection_axis_mut<T: ComplexField, D: Dim, S: StorageMut<T, D>>(
#[doc(hidden)] #[doc(hidden)]
pub fn clear_column_unchecked<T: ComplexField, R: Dim, C: Dim>( pub fn clear_column_unchecked<T: ComplexField, R: Dim, C: Dim>(
matrix: &mut OMatrix<T, R, C>, matrix: &mut OMatrix<T, R, C>,
diag_elt: &mut T, diag_elt: *mut T,
icol: usize, icol: usize,
shift: usize, shift: usize,
bilateral: Option<&mut OVector<T, R>>, bilateral: Option<&mut OVector<T, R>>,
@ -57,7 +59,9 @@ pub fn clear_column_unchecked<T: ComplexField, R: Dim, C: Dim>(
let mut axis = left.rows_range_mut(icol + shift..); let mut axis = left.rows_range_mut(icol + shift..);
let (reflection_norm, not_zero) = reflection_axis_mut(&mut axis); let (reflection_norm, not_zero) = reflection_axis_mut(&mut axis);
unsafe {
*diag_elt = reflection_norm; *diag_elt = reflection_norm;
}
if not_zero { if not_zero {
let refl = Reflection::new(Unit::new_unchecked(axis), T::zero()); let refl = Reflection::new(Unit::new_unchecked(axis), T::zero());
@ -74,9 +78,9 @@ pub fn clear_column_unchecked<T: ComplexField, R: Dim, C: Dim>(
#[doc(hidden)] #[doc(hidden)]
pub fn clear_row_unchecked<T: ComplexField, R: Dim, C: Dim>( pub fn clear_row_unchecked<T: ComplexField, R: Dim, C: Dim>(
matrix: &mut OMatrix<T, R, C>, matrix: &mut OMatrix<T, R, C>,
diag_elt: &mut T, diag_elt: *mut T,
axis_packed: &mut OVector<T, C>, axis_packed: &mut OVector<MaybeUninit<T>, C>,
work: &mut OVector<T, R>, work: &mut OVector<MaybeUninit<T>, R>,
irow: usize, irow: usize,
shift: usize, shift: usize,
) where ) where
@ -88,7 +92,7 @@ pub fn clear_row_unchecked<T: ComplexField, R: Dim, C: Dim>(
let (reflection_norm, not_zero) = reflection_axis_mut(&mut axis); let (reflection_norm, not_zero) = reflection_axis_mut(&mut axis);
axis.conjugate_mut(); // So that reflect_rows actually cancels the first row. axis.conjugate_mut(); // So that reflect_rows actually cancels the first row.
*diag_elt = reflection_norm; unsafe{ *diag_elt = reflection_norm;}
if not_zero { if not_zero {
let refl = Reflection::new(Unit::new_unchecked(axis), T::zero()); let refl = Reflection::new(Unit::new_unchecked(axis), T::zero());