Checkpoint #9
This commit is contained in:
parent
c3f869e017
commit
87fe2b30df
|
@ -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).")
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -683,7 +683,7 @@ where
|
||||||
{
|
{
|
||||||
/// Creates a new uninitialized matrix or vector.
|
/// Creates a new uninitialized matrix or vector.
|
||||||
#[inline]
|
#[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())
|
Self::new_uninitialized_generic(Dynamic::new(nrows), C::name())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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 {
|
||||||
|
|
|
@ -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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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>,
|
||||||
{
|
{
|
||||||
|
|
|
@ -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);
|
self.transpose_to(&mut res);
|
||||||
|
|
||||||
unsafe {
|
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()
|
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.
|
/// 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) {
|
||||||
|
|
|
@ -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>,
|
||||||
{
|
{
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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]
|
||||||
|
|
|
@ -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,
|
||||||
{
|
{
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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>,
|
||||||
{
|
{
|
||||||
|
|
|
@ -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> {
|
||||||
|
|
|
@ -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]
|
||||||
|
|
|
@ -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,
|
||||||
{
|
{
|
||||||
|
|
|
@ -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>,
|
||||||
{
|
{
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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(),
|
||||||
]))
|
]))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
/// ```
|
/// ```
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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>;
|
||||||
{
|
{
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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>>,
|
||||||
{
|
{
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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,
|
||||||
{
|
{
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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());
|
||||||
|
|
||||||
|
|
|
@ -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>,
|
||||||
{
|
{
|
||||||
|
|
|
@ -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);
|
||||||
*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());
|
||||||
|
@ -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());
|
||||||
|
|
Loading…
Reference in New Issue