#[cfg(feature = "serde-serialize")] use serde::{Serialize, Deserialize}; use alga::general::ClosedNeg; use num::One; use allocator::Allocator; use base::{DefaultAllocator, Matrix, Scalar, VectorN}; #[cfg(any(feature = "std", feature = "alloc"))] use dimension::Dynamic; use dimension::{Dim, DimName, U1}; use storage::StorageMut; /// A sequence of row or column permutations. #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] #[cfg_attr( feature = "serde-serialize", serde( bound( serialize = "DefaultAllocator: Allocator<(usize, usize), D>, VectorN<(usize, usize), D>: Serialize" ) ) )] #[cfg_attr( feature = "serde-serialize", serde( bound( deserialize = "DefaultAllocator: Allocator<(usize, usize), D>, VectorN<(usize, usize), D>: Deserialize<'de>" ) ) )] #[derive(Clone, Debug)] pub struct PermutationSequence where DefaultAllocator: Allocator<(usize, usize), D>, { len: usize, ipiv: VectorN<(usize, usize), D>, } impl Copy for PermutationSequence where DefaultAllocator: Allocator<(usize, usize), D>, VectorN<(usize, usize), D>: Copy, { } impl PermutationSequence where DefaultAllocator: Allocator<(usize, usize), D>, { /// Creates a new statically-allocated sequence of `D` identity permutations. #[inline] pub fn identity() -> Self { Self::identity_generic(D::name()) } } #[cfg(any(feature = "std", feature = "alloc"))] impl PermutationSequence where DefaultAllocator: Allocator<(usize, usize), Dynamic>, { /// Creates a new dynamically-allocated sequence of `n` identity permutations. #[inline] pub fn identity(n: usize) -> Self { Self::identity_generic(Dynamic::new(n)) } } impl PermutationSequence where DefaultAllocator: Allocator<(usize, usize), D>, { /// Creates a new sequence of D identity permutations. #[inline] pub fn identity_generic(dim: D) -> Self { unsafe { PermutationSequence { len: 0, ipiv: VectorN::new_uninitialized_generic(dim, U1), } } } /// Adds the interchange of the row (or column) `i` with the row (or column) `i2` to this /// sequence of permutations. #[inline] pub fn append_permutation(&mut self, i: usize, i2: usize) { if i != i2 { assert!( self.len < self.ipiv.len(), "Maximum number of permutations exceeded." ); self.ipiv[self.len] = (i, i2); self.len += 1; } } /// Applies this sequence of permutations to the rows of `rhs`. #[inline] pub fn permute_rows(&self, rhs: &mut Matrix) where S2: StorageMut, { for i in self.ipiv.rows_range(..self.len).iter() { rhs.swap_rows(i.0, i.1) } } /// Applies this sequence of permutations in reverse to the rows of `rhs`. #[inline] pub fn inv_permute_rows(&self, rhs: &mut Matrix) where S2: StorageMut, { for i in 0..self.len { let (i1, i2) = self.ipiv[self.len - i - 1]; rhs.swap_rows(i1, i2) } } /// Applies this sequence of permutations to the columns of `rhs`. #[inline] pub fn permute_columns(&self, rhs: &mut Matrix) where S2: StorageMut, { for i in self.ipiv.rows_range(..self.len).iter() { rhs.swap_columns(i.0, i.1) } } /// Applies this sequence of permutations in reverse to the columns of `rhs`. #[inline] pub fn inv_permute_columns( &self, rhs: &mut Matrix, ) where S2: StorageMut, { for i in 0..self.len { let (i1, i2) = self.ipiv[self.len - i - 1]; rhs.swap_columns(i1, i2) } } /// The number of non-identity permutations applied by this sequence. pub fn len(&self) -> usize { self.len } /// The determinant of the matrix corresponding to this permutation. #[inline] pub fn determinant(&self) -> N { if self.len % 2 == 0 { N::one() } else { -N::one() } } }