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 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
SparsityPatternFormatError::InvalidOffsetArrayLength => {
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>
where
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
/// a scalar.

View File

@ -146,7 +146,7 @@ macro_rules! component_binop_impl(
);
/// # 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_mul, component_mul_mut, component_mul_assign, cmpy, ClosedMul.mul.mul_assign,
r"

View File

@ -683,7 +683,7 @@ where
{
/// Creates a new uninitialized matrix or vector.
#[inline]
pub fn new_uninitialized(nrows: usize) -> OMatrix<MaybeUninit<T>, Dynamic, C> {
pub fn new_uninitialized(nrows: usize) -> OMatrix<MaybeUninit<T>, Dynamic, C> {
Self::new_uninitialized_generic(Dynamic::new(nrows), C::name())
}
}
@ -705,7 +705,10 @@ where
{
/// Creates a new uninitialized matrix or vector.
#[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))
}
}
@ -899,13 +902,11 @@ where
}
#[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
R: Dim,
C: Dim,
T: Arbitrary + Send,
DefaultAllocator: Allocator<T, R, C>,
Owned<T, R, C>: Clone + Send,
Owned<T, R, C>: Clone+Send,
{
#[inline]
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 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
for &'a mut Matrix<T, R, C, S>
{
impl<'a, T, R: Dim, C: Dim, S: StorageMut<T, R, C>> IntoIterator for &'a mut Matrix<T, R, C, S> {
type Item = &'a mut T;
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]
fn from(vec: SVector<T, D>) -> Self {
// 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]
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::storage::{ContiguousStorage, ContiguousStorageMut};
use crate::base::{Matrix, Scalar};
use crate::base::Matrix;
/*
*
@ -23,7 +23,7 @@ macro_rules! coords_impl(
#[repr(C)]
#[derive(Eq, PartialEq, Clone, Hash, Debug, Copy)]
#[cfg_attr(feature = "serde-serialize-no-std", derive(Serialize, Deserialize))]
pub struct $T<T: Scalar> {
pub struct $T<T> {
$(pub $comps: T),*
}
}
@ -31,7 +31,7 @@ macro_rules! coords_impl(
macro_rules! deref_impl(
($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> {
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> {
#[inline]
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() {
unsafe {
*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
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.
#[inline]
pub fn set_diagonal<R2: Dim, S2>(&mut self, diag: &Vector<T, R2, S2>)
where
T: Clone,
R: DimMin<C>,
S2: Storage<T, 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.");
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]
pub fn set_row<C2: Dim, S2>(&mut self, i: usize, row: &RowVector<T, C2, S2>)
where
T: Clone,
S2: Storage<T, U1, 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]
pub fn set_column<R2: Dim, S2>(&mut self, i: usize, column: &Vector<T, R2, S2>)
where
T: Clone,
S2: Storage<T, R2, U1>,
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.
///
/// 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 i in j + 1..dim {
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 i in 0..j {
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
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.
#[inline]
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
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.
@ -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
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.
@ -738,7 +741,7 @@ impl<T: Scalar, R: Dim, C: Dim, S: Storage<T, R, C>> Matrix<T, R, C, S> {
}
/// # 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.
///
/// 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 {
res.columns_range_mut(ncols..).fill(val.inlined_clone());
res.columns_range_mut(ncols..).fill(val.clone());
}
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
#[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.
///
/// 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"))]
impl<T: Scalar, C: Dim> OMatrix<T, Dynamic, C>
impl<T: Clone, C: Dim> OMatrix<T, Dynamic, C>
where
DefaultAllocator: Allocator<T, Dynamic, C>,
{
@ -971,7 +974,7 @@ where
}
#[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
DefaultAllocator: Allocator<T, R, Dynamic>,
{
@ -993,13 +996,7 @@ where
}
}
unsafe fn compress_rows<T: Scalar>(
data: &mut [T],
nrows: usize,
ncols: usize,
i: usize,
nremove: usize,
) {
unsafe fn compress_rows<T>(data: &mut [T], nrows: usize, ncols: usize, i: usize, nremove: usize) {
let new_nrows = nrows - nremove;
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.
// The `data` buffer is assumed to contained at least `(nrows + ninsert) * ncols` elements.
unsafe fn extend_rows<T: Scalar>(
data: &mut [T],
nrows: usize,
ncols: usize,
i: usize,
ninsert: usize,
) {
unsafe fn extend_rows<T>(data: &mut [T], nrows: usize, ncols: usize, i: usize, ninsert: usize) {
let new_nrows = nrows + ninsert;
if new_nrows == 0 || ncols == 0 {
@ -1070,7 +1061,6 @@ unsafe fn extend_rows<T: Scalar>(
#[cfg(any(feature = "std", feature = "alloc"))]
impl<T, R, S> Extend<T> for Matrix<T, R, Dynamic, S>
where
T: Scalar,
R: Dim,
S: Extend<T>,
{
@ -1118,7 +1108,6 @@ where
#[cfg(any(feature = "std", feature = "alloc"))]
impl<T, S> Extend<T> for Matrix<T, Dynamic, U1, S>
where
T: Scalar,
S: Extend<T>,
{
/// Extend the number of rows of a `Vector` with elements
@ -1137,12 +1126,9 @@ where
}
#[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
T: Scalar,
R: Dim,
S: Extend<Vector<T, RV, SV>>,
RV: Dim,
SV: Storage<T, RV>,
ShapeConstraint: SameNumberOfRows<R, RV>,
{

View File

@ -716,7 +716,34 @@ impl<T, R: Dim, C: Dim, S: Storage<T, R, C>> Matrix<T, R, C, S> {
self.transpose_to(&mut res);
unsafe {
// Safety: res is now fully initialized due to the guarantees of transpose_to.
// Safety: res is now fully initialized due to the guarantees of transpose_to.
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()
}
}
@ -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.
#[inline]
#[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
T: Clone,
DefaultAllocator: Allocator<T2, R, C>,
{
let (nrows, ncols) = self.data.shape();
let mut res = OMatrix::new_uninitialized_generic(nrows, ncols);
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.
@ -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`?
@ -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> {
/// Gets a reference to the i-th element of this column vector without bound checking.
#[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
T: Scalar + AbsDiffEq,
S: Storage<T, R, C>,
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
T: Scalar + RelativeEq,
S: Storage<T, R, C>,
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
T: Scalar + UlpsEq,
S: Storage<T, R, C>,
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
T: Hash,
S: Storage<T, R, C>,
{
fn hash<H: Hasher>(&self, state: &mut H) {

View File

@ -9,11 +9,9 @@ use crate::base::{DefaultAllocator, OMatrix, Scalar};
* 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
T: Scalar + SimdValue,
R: Dim,
C: Dim,
T::Element: Scalar,
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
T: Scalar + Zero + One + ClosedAdd + ClosedMul,
SB: Storage<T, R2, C1>,
SA: ContiguousStorageMut<T, R1, C1> + Clone,
SA: ContiguousStorageMut<T, R1, C1> ,
ShapeConstraint: AreMultipliable<R1, C1, R2, C1>,
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
T: Scalar + Zero + One + ClosedAdd + ClosedMul,
SB: Storage<T, R2, C1>,
SA: ContiguousStorageMut<T, R1, C1> + Clone,
SA: ContiguousStorageMut<T, R1, C1> ,
ShapeConstraint: AreMultipliable<R1, C1, R2, C1>,
// TODO: this is too restrictive. See comments for the non-ref version.
DefaultAllocator: Allocator<T, R1, C1> + InnerAllocator<T, R1, C1, Buffer = SA>,
@ -796,7 +796,6 @@ where
ShapeConstraint: SameNumberOfRows<R3, R1>
+ SameNumberOfColumns<C3, C2>
+ AreMultipliable<R1, C1, R2, C2>,
DefaultAllocator: Allocator<T, R3, C3>,
{
out.gemm_z(T::one(), self, rhs);
}

View File

@ -26,6 +26,8 @@ pub trait Scalar: 'static + Clone + Debug {
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 {
#[inline(always)]
fn inlined_clone(&self) -> T {

View File

@ -7,7 +7,7 @@ use num::Zero;
use simba::scalar::{ClosedAdd, Field, SupersetOf};
/// # 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
/// corresponding column of the original matrix.
#[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 typenum::{self, Cmp, Greater};
@ -11,7 +11,7 @@ macro_rules! impl_swizzle {
#[must_use]
pub fn $name(&self) -> $Result<T>
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
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
D: DimName + ToTypenum,
{

View File

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

View File

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

View File

@ -24,8 +24,7 @@ use crate::geometry::{
impl<T1, T2> SubsetOf<DualQuaternion<T2>> for DualQuaternion<T1>
where
T1: SimdRealField,
T2: SimdRealField + SupersetOf<T1>,
T2: SupersetOf<T1>,
{
#[inline]
fn to_superset(&self) -> DualQuaternion<T2> {
@ -49,8 +48,7 @@ where
impl<T1, T2> SubsetOf<UnitDualQuaternion<T2>> for UnitDualQuaternion<T1>
where
T1: SimdRealField,
T2: SimdRealField + SupersetOf<T1>,
T2: SupersetOf<T1>,
{
#[inline]
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,
};
impl<T: SimdRealField> AsRef<[T; 8]> for DualQuaternion<T> {
impl<T> AsRef<[T; 8]> for DualQuaternion<T> {
#[inline]
fn as_ref(&self) -> &[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]
fn as_mut(&mut self) -> &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;
#[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]
fn index_mut(&mut self, i: usize) -> &mut T {
&mut self.as_mut()[i]

View File

@ -80,7 +80,6 @@ pub struct Isometry<T, R, const D: usize> {
#[cfg(feature = "abomonation-serialize")]
impl<T, R, const D: usize> Abomonation for Isometry<T, R, D>
where
T: SimdRealField,
R: Abomonation,
Translation<T, D>: Abomonation,
{
@ -106,10 +105,7 @@ mod rkyv_impl {
use crate::{base::Scalar, geometry::Translation};
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>
where
T::Archived: Scalar,
{
impl<T: Archive, R: Archive, const D: usize> Archive for Isometry<T, R, D> {
type Archived = Isometry<T::Archived, R::Archived, D>;
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>
Serialize<S> for Isometry<T, R, D>
impl<T: Serialize<S>, R: Serialize<S>, S: Fallible + ?Sized, const D: usize> Serialize<S>
for Isometry<T, R, D>
where
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>
where
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
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
Owned<T, Const<D>>: Copy
{
}
impl<T: Copy, R: Copy, const D: usize> Copy for Isometry<T, R, D> where 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]
fn clone(&self) -> Self {
Self {
@ -638,7 +631,7 @@ where
* 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
R: fmt::Display,
{

View File

@ -5,6 +5,7 @@ use std::fmt;
use std::hash;
#[cfg(feature = "abomonation-serialize")]
use std::io::{Result as IOResult, Write};
use std::mem::MaybeUninit;
#[cfg(feature = "serde-serialize-no-std")]
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::{Const, DefaultAllocator, OVector};
use crate::storage::Owned;
use crate::Scalar;
/// 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
/// of said transformations for details.
#[repr(C)]
#[derive(Debug, Clone)]
// TODO: figure out why #[derive(Clone, Debug)] doesn't work!
pub struct OPoint<T, D: DimName>
where
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")]
unsafe impl<T, D: DimName> bytemuck::Zeroable for OPoint<T, D>
where
@ -151,7 +163,8 @@ where
#[inline]
#[must_use]
pub fn map<T2, F: FnMut(T) -> T2>(&self, f: F) -> OPoint<T2, D>
where T:Clone,
where
T: Clone,
DefaultAllocator: Allocator<T2, D>,
{
self.coords.map(f).into()
@ -194,22 +207,44 @@ where
#[inline]
#[must_use]
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
T: One,
D: DimNameAdd<U1>,
DefaultAllocator: Allocator<T, DimNameSum<D, U1>>,
{
let mut res = unsafe {
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();
let mut res = OVector::<_, DimNameSum<D, U1>>::new_uninitialized();
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.
@ -415,7 +450,7 @@ where
/*
* inf/sup
*/
impl<T: SimdPartialOrd, D: DimName> OPoint<T, D>
impl<T: Scalar + SimdPartialOrd, D: DimName> OPoint<T, D>
where
DefaultAllocator: Allocator<T, D>,
{

View File

@ -50,9 +50,9 @@ where
#[inline]
pub fn origin() -> Self
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.
@ -70,8 +70,11 @@ where
/// assert_eq!(pt, Point3::new(1.0, 2.0, 3.0));
/// ```
#[inline]
pub fn from_slice(components: &[T]) -> Self {
Self::from(OVector::from_row_slice(components))
pub fn from_slice(components: &[T]) -> Self
where
T: Clone,
{
Self::from(OVector::<_, D>::from_row_slice(components))
}
/// 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>
where
DefaultAllocator: Allocator<T, D>,
crate::base::storage::Owned<T, D>: Send,
crate::base::storage::Owned<T, D>: Clone + Send,
{
#[inline]
fn arbitrary(g: &mut Gen) -> Self {

View File

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

View File

@ -1,7 +1,7 @@
use std::ops::{Deref, DerefMut};
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;
@ -13,7 +13,7 @@ use crate::geometry::OPoint;
macro_rules! deref_impl(
($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>;
@ -23,7 +23,7 @@ macro_rules! deref_impl(
}
}
impl<T: Scalar> DerefMut for OPoint<T, $D>
impl<T> DerefMut for OPoint<T, $D>
{
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {

View File

@ -1,10 +1,13 @@
use simba::simd::SimdValue;
use crate::base::OVector;
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 SimdBool = T::SimdBool;

View File

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

View File

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

View File

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

View File

@ -1,3 +1,5 @@
use std::mem::MaybeUninit;
use crate::base::constraint::{AreMultipliable, DimEq, SameNumberOfRows, ShapeConstraint};
use crate::base::{Const, Matrix, Unit, Vector};
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>(
&self,
lhs: &mut Matrix<T, R2, C2, S2>,
work: &mut Vector<T, R2, S3>,
work: &mut Vector<MaybeUninit<T>, R2, S3>,
) where
S2: StorageMut<T, R2, C2>,
S3: StorageMut<T, R2>,
S3: StorageMut<MaybeUninit<T>, R2>,
ShapeConstraint: DimEq<C2, D> + AreMultipliable<R2, C2, D, U1>,
{
lhs.mul_to(&self.axis, work);
let mut work = unsafe { work.assume_init_mut() };
if !self.bias.is_zero() {
work.add_scalar_mut(-self.bias);
}
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`.
pub fn reflect_rows_with_sign<R2: Dim, C2: Dim, S2, S3>(
&self,
lhs: &mut Matrix<T, R2, C2, S2>,
work: &mut Vector<T, R2, S3>,
work: &mut Vector<MaybeUninit<T>, R2, S3>,
sign: T,
) where
S2: StorageMut<T, R2, C2>,
S3: StorageMut<T, R2>,
S3: StorageMut<MaybeUninit<T>, R2>,
ShapeConstraint: DimEq<C2, D> + AreMultipliable<R2, C2, D, U1>,
{
lhs.mul_to(&self.axis, work);
let mut work = unsafe { work.assume_init_mut() };
if !self.bias.is_zero() {
work.add_scalar_mut(-self.bias);
}
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, const D: usize> Clone for Rotation<T, D>
impl<T: Clone, const D: usize> Clone for Rotation<T, D>
where
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.
///
/// 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
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.
///
/// # Example
@ -263,7 +263,7 @@ impl<T: Scalar, const D: usize> Rotation<T, D> {
#[must_use]
pub fn to_homogeneous(&self) -> OMatrix<T, DimNameSum<Const<D>, U1>, DimNameSum<Const<D>, U1>>
where
T: Zero + One,
T: Zero + One + Scalar,
Const<D>: DimNameAdd<U1>,
DefaultAllocator: Allocator<T, DimNameSum<Const<D>, U1>, DimNameSum<Const<D>, U1>>,
{

View File

@ -1,5 +1,6 @@
use approx::{AbsDiffEq, RelativeEq, UlpsEq};
use std::any::Any;
use std::fmt;
use std::fmt::Debug;
use std::hash;
use std::marker::PhantomData;
@ -7,7 +8,7 @@ use std::marker::PhantomData;
#[cfg(feature = "serde-serialize-no-std")]
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use simba::scalar::RealField;
use simba::scalar::{ComplexField, RealField};
use crate::base::allocator::Allocator;
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 {
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
/// 3D transformation.
#[repr(C)]
#[derive(Debug)]
pub struct Transform<T: RealField, C: TCategory, const D: usize>
pub struct Transform<T, C: TCategory, const D: usize>
where
Const<D>: DimNameAdd<U1>,
DefaultAllocator: Allocator<T, DimNameSum<Const<D>, U1>, DimNameSum<Const<D>, U1>>,
@ -167,7 +167,7 @@ where
_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
Const<D>: DimNameAdd<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
Const<D>: DimNameAdd<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
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>>: Clone,
{
#[inline]
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")]
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
Const<D>: DimNameAdd<U1>,
DefaultAllocator: Allocator<T, DimNameSum<Const<D>, U1>, DimNameSum<Const<D>, U1>>,
@ -213,7 +227,7 @@ where
}
#[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
Const<D>: DimNameAdd<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
Const<D>: DimNameAdd<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
Const<D>: DimNameAdd<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
Const<D>: DimNameAdd<U1>,
DefaultAllocator: Allocator<T, DimNameSum<Const<D>, U1>, DimNameSum<Const<D>, U1>>,
@ -354,7 +368,10 @@ where
#[deprecated(
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())
}
@ -372,7 +389,10 @@ where
/// ```
#[inline]
#[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()
}
@ -401,7 +421,10 @@ where
/// ```
#[inline]
#[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
.try_inverse()
.map(Transform::from_matrix_unchecked)
@ -427,6 +450,7 @@ where
#[must_use = "Did you mean to use inverse_mut()?"]
pub fn inverse(self) -> Transform<T, C, D>
where
T: ComplexField,
C: SubTCategoryOf<TProjective>,
{
// TODO: specialize for TAffine?
@ -458,7 +482,10 @@ where
/// assert!(!t.try_inverse_mut());
/// ```
#[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()
}
@ -482,6 +509,7 @@ where
#[inline]
pub fn inverse_mut(&mut self)
where
T: ComplexField,
C: SubTCategoryOf<TProjective>,
{
let _ = self.matrix.try_inverse_mut();

View File

@ -29,7 +29,7 @@ pub struct Translation<T, const D: usize> {
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
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
Owned<T, Const<D>>: Clone,
{
@ -53,7 +53,6 @@ where
#[cfg(feature = "abomonation-serialize")]
impl<T, const D: usize> Abomonation for Translation<T, D>
where
T: Scalar,
SVector<T, D>: Abomonation,
{
unsafe fn entomb<W: Write>(&self, writer: &mut W) -> IOResult<()> {
@ -70,7 +69,7 @@ where
}
#[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
Owned<T, Const<D>>: Serialize,
{
@ -83,7 +82,7 @@ where
}
#[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
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.
#[inline]
#[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()?"]
pub fn inverse(&self) -> Translation<T, D>
where
T: ClosedNeg,
T: ClosedNeg + Scalar,
{
Translation::from(-&self.vector)
}
@ -193,7 +192,7 @@ impl<T: Scalar, const D: usize> Translation<T, D> {
#[must_use]
pub fn to_homogeneous(&self) -> OMatrix<T, DimNameSum<Const<D>, U1>, DimNameSum<Const<D>, U1>>
where
T: Zero + One,
T: Zero + One + Scalar,
Const<D>: DimNameAdd<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]
pub fn inverse_mut(&mut self)
where
T: ClosedNeg,
T: ClosedNeg + Scalar,
{
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]
fn eq(&self, right: &Translation<T, D>) -> bool {
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
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
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
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>
where
T1: Scalar,
T2: Scalar + SupersetOf<T1>,
T2: SupersetOf<T1>,
{
#[inline]
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]
fn from(vector: OVector<T, Const<D>>) -> Self {
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]
fn from(coords: [T; D]) -> Self {
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]
fn from(pt: Point<T, D>) -> Self {
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]
fn from(t: Translation<T, D>) -> Self {
t.vector.into()

View File

@ -1,10 +1,13 @@
use std::fmt;
#[cfg(feature = "serde-serialize-no-std")]
use serde::{Deserialize, Serialize};
use crate::allocator::Allocator;
use crate::base::{DefaultAllocator, Matrix, OMatrix, OVector, Unit};
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 crate::geometry::Reflection;
@ -32,7 +35,6 @@ use crate::linalg::householder;
OVector<T, DimMinimum<R, C>>: Deserialize<'de>,
OVector<T, DimDiff<DimMinimum<R, C>, U1>>: Deserialize<'de>"))
)]
#[derive(Clone, Debug)]
pub struct Bidiagonal<T: ComplexField, R: DimMin<C>, C: Dim>
where
DimMinimum<R, C>: DimSub<U1>,
@ -50,18 +52,58 @@ where
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>
where
DimMinimum<R, C>: DimSub<U1>,
DefaultAllocator: Allocator<T, R, C>
+ Allocator<T, DimMinimum<R, C>>
+ Allocator<T, DimDiff<DimMinimum<R, C>, U1>>,
OMatrix<T, R, C>: Copy,
OVector<T, DimMinimum<R, C>>: Copy,
OVector<T, DimDiff<DimMinimum<R, C>, U1>>: Copy,
Owned<T, R, C>: Copy,
Owned<T, DimMinimum<R, C>>: 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>
where
DimMinimum<R, C>: DimSub<U1>,
@ -81,25 +123,25 @@ where
"Cannot compute the bidiagonalization of an empty matrix."
);
let mut diagonal =
unsafe { crate::unimplemented_or_uninitialized_generic!(min_nrows_ncols, Const::<1>) };
let mut off_diagonal = unsafe {
crate::unimplemented_or_uninitialized_generic!(
min_nrows_ncols.sub(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 mut diagonal = Matrix::new_uninitialized_generic(min_nrows_ncols, Const::<1>);
let mut off_diagonal =
Matrix::new_uninitialized_generic(min_nrows_ncols.sub(Const::<1>), Const::<1>);
let mut axis_packed = Matrix::new_uninitialized_generic(ncols, Const::<1>);
let mut work = Matrix::new_uninitialized_generic(nrows, Const::<1>);
let upper_diagonal = nrows.value() >= ncols.value();
if upper_diagonal {
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(
&mut matrix,
&mut off_diagonal[ite],
off_diagonal[ite].as_mut_ptr(),
&mut axis_packed,
&mut work,
ite,
@ -109,7 +151,7 @@ where
householder::clear_column_unchecked(
&mut matrix,
&mut diagonal[dim - 1],
diagonal[dim - 1].as_mut_ptr(),
dim - 1,
0,
None,
@ -118,7 +160,7 @@ where
for ite in 0..dim - 1 {
householder::clear_row_unchecked(
&mut matrix,
&mut diagonal[ite],
diagonal[ite].as_mut_ptr(),
&mut axis_packed,
&mut work,
ite,
@ -126,7 +168,7 @@ where
);
householder::clear_column_unchecked(
&mut matrix,
&mut off_diagonal[ite],
off_diagonal[ite].as_mut_ptr(),
ite,
1,
None,
@ -135,7 +177,7 @@ where
householder::clear_row_unchecked(
&mut matrix,
&mut diagonal[dim - 1],
diagonal[dim - 1].as_mut_ptr(),
&mut axis_packed,
&mut work,
dim - 1,
@ -145,8 +187,8 @@ where
Bidiagonal {
uv: matrix,
diagonal,
off_diagonal,
diagonal: diagonal.assume_init(),
off_diagonal: off_diagonal.assume_init(),
upper_diagonal,
}
}
@ -243,23 +285,23 @@ where
#[must_use]
pub fn v_t(&self) -> OMatrix<T, DimMinimum<R, C>, C>
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 min_nrows_ncols = nrows.min(ncols);
let mut res = Matrix::identity_generic(min_nrows_ncols, ncols);
let mut work =
unsafe { crate::unimplemented_or_uninitialized_generic!(min_nrows_ncols, Const::<1>) };
let mut axis_packed =
unsafe { crate::unimplemented_or_uninitialized_generic!(ncols, Const::<1>) };
let mut work = Matrix::new_uninitialized_generic(min_nrows_ncols, Const::<1>);
let mut axis_packed = Matrix::new_uninitialized_generic(ncols, Const::<1>);
let shift = self.axis_shift().1;
for i in (0..min_nrows_ncols.value() - shift).rev() {
let axis = self.uv.slice_range(i, 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.
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")]
use serde::{Deserialize, Serialize};
@ -9,7 +12,7 @@ use crate::allocator::Allocator;
use crate::base::{Const, DefaultAllocator, Matrix, OMatrix, Vector};
use crate::constraint::{SameNumberOfRows, ShapeConstraint};
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.
#[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>,
OMatrix<T, D, D>: Deserialize<'de>"))
)]
#[derive(Clone, Debug)]
pub struct Cholesky<T: SimdComplexField, D: Dim>
where
DefaultAllocator: Allocator<T, D, D>,
@ -34,10 +36,34 @@ where
impl<T: SimdComplexField, D: Dim> Copy for Cholesky<T, D>
where
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>
where
DefaultAllocator: Allocator<T, D, D>,
@ -226,6 +252,8 @@ where
DefaultAllocator: Allocator<T, DimSum<D, U1>, DimSum<D, U1>> + Allocator<T, R2>,
ShapeConstraint: SameNumberOfRows<R2, DimSum<D, U1>>,
{
// TODO: check that MaybeUninit manipulations are sound!
let mut col = col.into_owned();
// for an explanation of the formulas, see https://en.wikipedia.org/wiki/Cholesky_decomposition#Updating_the_decomposition
let n = col.nrows();
@ -237,20 +265,20 @@ where
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
let mut chol = unsafe {
crate::unimplemented_or_uninitialized_generic!(
self.chol.data.shape().0.add(Const::<1>),
self.chol.data.shape().1.add(Const::<1>)
)
};
let mut chol = Matrix::new_uninitialized_generic(
self.chol.data.shape().0.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)
.copy_from(&self.chol.slice_range(..j, ..j));
.copy_init_from(&self.chol.slice_range(..j, ..j));
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)
.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..)
.copy_from(&self.chol.slice_range(j.., j..));
.copy_init_from(&self.chol.slice_range(j.., j..));
// update the jth row
let top_left_corner = self.chol.slice_range(..j, ..j);
@ -266,7 +294,7 @@ where
// update the center element
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
let bottom_left_corner = self.chol.slice_range(j.., ..j);
@ -277,7 +305,9 @@ where
&new_rowj_adjoint,
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
let mut bottom_right_corner = chol.slice_range_mut(j + 1.., j + 1..);
@ -298,25 +328,27 @@ where
D: DimSub<U1>,
DefaultAllocator: Allocator<T, DimDiff<D, U1>, DimDiff<D, U1>> + Allocator<T, D>,
{
// TODO: check that MaybeUninit manipulations are sound!
let n = self.chol.nrows();
assert!(n > 0, "The matrix needs at least one column.");
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
let mut chol = unsafe {
crate::unimplemented_or_uninitialized_generic!(
self.chol.data.shape().0.sub(Const::<1>),
self.chol.data.shape().1.sub(Const::<1>)
)
};
let mut chol = Matrix::new_uninitialized_generic(
self.chol.data.shape().0.sub(Const::<1>),
self.chol.data.shape().1.sub(Const::<1>),
);
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..)
.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)
.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..)
.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
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`
/// 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>,
x: &mut Vector<T, Rx, Sx>,
sigma: T::RealField,
) where
//T: ComplexField,
Dm: Dim,
Rx: Dim,
Sm: StorageMut<T, Dm, Dm>,
Sx: StorageMut<T, Rx, U1>,
{

View File

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