nalgebra/src/linalg/permutation_sequence.rs

216 lines
5.9 KiB
Rust
Raw Normal View History

2021-07-17 15:52:57 +08:00
use std::fmt;
2021-07-16 12:56:58 +08:00
use std::mem::MaybeUninit;
#[cfg(feature = "serde-serialize-no-std")]
2018-10-22 13:00:10 +08:00
use serde::{Deserialize, Serialize};
use num::One;
2020-03-21 19:16:46 +08:00
use simba::scalar::ClosedNeg;
2019-03-23 21:29:07 +08:00
use crate::allocator::Allocator;
2021-04-11 17:00:38 +08:00
use crate::base::{DefaultAllocator, Matrix, OVector, Scalar};
2018-05-27 03:02:24 +08:00
#[cfg(any(feature = "std", feature = "alloc"))]
2019-03-23 21:29:07 +08:00
use crate::dimension::Dynamic;
2021-07-17 15:52:57 +08:00
use crate::dimension::{Dim, DimName};
use crate::iter::MatrixIter;
2021-07-20 07:00:40 +08:00
use crate::storage::{InnerOwned, StorageMut};
2021-07-17 15:52:57 +08:00
use crate::{Const, U1};
/// A sequence of row or column permutations.
#[cfg_attr(feature = "serde-serialize-no-std", derive(Serialize, Deserialize))]
#[cfg_attr(
feature = "serde-serialize-no-std",
2020-03-21 19:16:46 +08:00
serde(bound(serialize = "DefaultAllocator: Allocator<(usize, usize), D>,
2021-04-11 17:00:38 +08:00
OVector<(usize, usize), D>: Serialize"))
)]
#[cfg_attr(
feature = "serde-serialize-no-std",
2020-03-21 19:16:46 +08:00
serde(bound(deserialize = "DefaultAllocator: Allocator<(usize, usize), D>,
2021-04-11 17:00:38 +08:00
OVector<(usize, usize), D>: Deserialize<'de>"))
)]
pub struct PermutationSequence<D: Dim>
2020-04-06 00:49:48 +08:00
where
DefaultAllocator: Allocator<(usize, usize), D>,
2018-02-02 19:26:35 +08:00
{
len: usize,
2021-07-16 12:56:58 +08:00
ipiv: OVector<MaybeUninit<(usize, usize)>, D>,
}
impl<D: Dim> Copy for PermutationSequence<D>
2018-02-02 19:26:35 +08:00
where
DefaultAllocator: Allocator<(usize, usize), D>,
2021-07-16 12:56:58 +08:00
OVector<MaybeUninit<(usize, usize)>, D>: Copy,
2020-03-21 19:16:46 +08:00
{
}
2021-07-17 15:52:57 +08:00
impl<D: Dim> Clone for PermutationSequence<D>
where
DefaultAllocator: Allocator<(usize, usize), D>,
OVector<MaybeUninit<(usize, usize)>, D>: Clone,
{
fn clone(&self) -> Self {
Self {
len: self.len,
ipiv: self.ipiv.clone(),
}
}
}
impl<D: Dim> fmt::Debug for PermutationSequence<D>
where
DefaultAllocator: Allocator<(usize, usize), D>,
OVector<MaybeUninit<(usize, usize)>, D>: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("PermutationSequence")
.field("len", &self.len)
.field("ipiv", &self.ipiv)
.finish()
}
}
impl<D: DimName> PermutationSequence<D>
2020-04-06 00:49:48 +08:00
where
DefaultAllocator: Allocator<(usize, usize), D>,
2018-02-02 19:26:35 +08:00
{
/// 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<Dynamic>
2020-04-06 00:49:48 +08:00
where
DefaultAllocator: Allocator<(usize, usize), Dynamic>,
2018-02-02 19:26:35 +08:00
{
/// Creates a new dynamically-allocated sequence of `n` identity permutations.
#[inline]
pub fn identity(n: usize) -> Self {
Self::identity_generic(Dynamic::new(n))
}
}
impl<D: Dim> PermutationSequence<D>
2020-04-06 00:49:48 +08:00
where
DefaultAllocator: Allocator<(usize, usize), D>,
2018-02-02 19:26:35 +08:00
{
/// Creates a new sequence of D identity permutations.
#[inline]
pub fn identity_generic(dim: D) -> Self {
2021-07-18 02:01:03 +08:00
Self {
len: 0,
ipiv: OVector::new_uninitialized_generic(dim, Const::<1>),
}
}
/// 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 {
2018-02-02 19:26:35 +08:00
assert!(
self.len < self.ipiv.len(),
"Maximum number of permutations exceeded."
);
2021-07-17 15:52:57 +08:00
self.ipiv[self.len] = MaybeUninit::new((i, i2));
self.len += 1;
}
}
/// Applies this sequence of permutations to the rows of `rhs`.
#[inline]
2021-04-11 17:00:38 +08:00
pub fn permute_rows<T: Scalar, R2: Dim, C2: Dim, S2>(&self, rhs: &mut Matrix<T, R2, C2, S2>)
2020-04-06 00:49:48 +08:00
where
2021-04-11 17:00:38 +08:00
S2: StorageMut<T, R2, C2>,
2020-04-06 00:49:48 +08:00
{
2021-07-17 15:52:57 +08:00
for perm in self.iter() {
rhs.swap_rows(perm.0, perm.1)
}
}
/// Applies this sequence of permutations in reverse to the rows of `rhs`.
#[inline]
2021-04-11 17:00:38 +08:00
pub fn inv_permute_rows<T: Scalar, R2: Dim, C2: Dim, S2>(&self, rhs: &mut Matrix<T, R2, C2, S2>)
2020-04-06 00:49:48 +08:00
where
2021-04-11 17:00:38 +08:00
S2: StorageMut<T, R2, C2>,
2018-02-02 19:26:35 +08:00
{
2021-07-17 15:52:57 +08:00
for perm in self.iter().rev() {
let (i1, i2) = perm;
rhs.swap_rows(i1, i2)
}
}
/// Applies this sequence of permutations to the columns of `rhs`.
#[inline]
2021-04-11 17:00:38 +08:00
pub fn permute_columns<T: Scalar, R2: Dim, C2: Dim, S2>(&self, rhs: &mut Matrix<T, R2, C2, S2>)
2020-04-06 00:49:48 +08:00
where
2021-04-11 17:00:38 +08:00
S2: StorageMut<T, R2, C2>,
2018-02-02 19:26:35 +08:00
{
2021-07-17 15:52:57 +08:00
for perm in self.iter() {
rhs.swap_columns(perm.0, perm.1)
}
}
/// Applies this sequence of permutations in reverse to the columns of `rhs`.
#[inline]
2021-04-11 17:00:38 +08:00
pub fn inv_permute_columns<T: Scalar, R2: Dim, C2: Dim, S2>(
2018-02-02 19:26:35 +08:00
&self,
2021-04-11 17:00:38 +08:00
rhs: &mut Matrix<T, R2, C2, S2>,
2018-02-02 19:26:35 +08:00
) where
2021-04-11 17:00:38 +08:00
S2: StorageMut<T, R2, C2>,
2018-02-02 19:26:35 +08:00
{
2021-07-17 15:52:57 +08:00
for perm in self.iter().rev() {
let (i1, i2) = perm;
rhs.swap_columns(i1, i2)
}
}
/// The number of non-identity permutations applied by this sequence.
#[must_use]
pub fn len(&self) -> usize {
self.len
}
/// Returns true if the permutation sequence contains no elements.
#[must_use]
pub fn is_empty(&self) -> bool {
self.len() == 0
}
/// The determinant of the matrix corresponding to this permutation.
#[inline]
#[must_use]
2021-04-11 17:00:38 +08:00
pub fn determinant<T: One + ClosedNeg>(&self) -> T {
if self.len % 2 == 0 {
2021-04-11 17:00:38 +08:00
T::one()
2018-02-02 19:26:35 +08:00
} else {
2021-04-11 17:00:38 +08:00
-T::one()
}
}
2021-07-17 15:52:57 +08:00
/// Iterates over the permutations that have been initialized.
pub fn iter(
&self,
) -> std::iter::Map<
std::iter::Copied<
std::iter::Take<
MatrixIter<
MaybeUninit<(usize, usize)>,
D,
U1,
2021-07-20 07:00:40 +08:00
InnerOwned<MaybeUninit<(usize, usize)>, D, U1>,
2021-07-17 15:52:57 +08:00
>,
>,
>,
impl FnMut(MaybeUninit<(usize, usize)>) -> (usize, usize),
> {
self.ipiv
.iter()
.take(self.len)
.copied()
.map(|e| unsafe { e.assume_init() })
}
}