1#[cfg(feature = "serde-serialize-no-std")]
2use serde::{Deserialize, Serialize};
3
4use num::One;
5use simba::scalar::ClosedNeg;
6
7use crate::allocator::Allocator;
8use crate::base::{DefaultAllocator, Matrix, OVector, Scalar};
9#[cfg(any(feature = "std", feature = "alloc"))]
10use crate::dimension::Dyn;
11use crate::dimension::{Const, Dim, DimName};
12use crate::storage::StorageMut;
13
14#[cfg_attr(feature = "serde-serialize-no-std", derive(Serialize, Deserialize))]
16#[cfg_attr(
17 feature = "serde-serialize-no-std",
18 serde(bound(serialize = "DefaultAllocator: Allocator<D>,
19 OVector<(usize, usize), D>: Serialize"))
20)]
21#[cfg_attr(
22 feature = "serde-serialize-no-std",
23 serde(bound(deserialize = "DefaultAllocator: Allocator<D>,
24 OVector<(usize, usize), D>: Deserialize<'de>"))
25)]
26#[derive(Clone, Debug)]
27pub struct PermutationSequence<D: Dim>
28where
29 DefaultAllocator: Allocator<D>,
30{
31 len: usize,
32 ipiv: OVector<(usize, usize), D>,
33}
34
35impl<D: Dim> Copy for PermutationSequence<D>
36where
37 DefaultAllocator: Allocator<D>,
38 OVector<(usize, usize), D>: Copy,
39{
40}
41
42impl<D: DimName> PermutationSequence<D>
43where
44 DefaultAllocator: Allocator<D>,
45{
46 #[inline]
48 pub fn identity() -> Self {
49 Self::identity_generic(D::name())
50 }
51}
52
53#[cfg(any(feature = "std", feature = "alloc"))]
54impl PermutationSequence<Dyn>
55where
56 DefaultAllocator: Allocator<Dyn>,
57{
58 #[inline]
60 pub fn identity(n: usize) -> Self {
61 Self::identity_generic(Dyn(n))
62 }
63}
64
65impl<D: Dim> PermutationSequence<D>
66where
67 DefaultAllocator: Allocator<D>,
68{
69 #[inline]
71 pub fn identity_generic(dim: D) -> Self {
72 Self {
73 len: 0,
74 ipiv: Matrix::repeat_generic(dim, Const::<1>, (0, 0)),
77 }
78 }
79
80 #[inline]
83 pub fn append_permutation(&mut self, i: usize, i2: usize) {
84 if i != i2 {
85 assert!(
86 self.len < self.ipiv.len(),
87 "Maximum number of permutations exceeded."
88 );
89 self.ipiv[self.len] = (i, i2);
90 self.len += 1;
91 }
92 }
93
94 #[inline]
96 pub fn permute_rows<T: Scalar, R2: Dim, C2: Dim, S2>(&self, rhs: &mut Matrix<T, R2, C2, S2>)
97 where
98 S2: StorageMut<T, R2, C2>,
99 {
100 for i in self.ipiv.rows_range(..self.len).iter() {
101 rhs.swap_rows(i.0, i.1)
102 }
103 }
104
105 #[inline]
107 pub fn inv_permute_rows<T: Scalar, R2: Dim, C2: Dim, S2>(&self, rhs: &mut Matrix<T, R2, C2, S2>)
108 where
109 S2: StorageMut<T, R2, C2>,
110 {
111 for i in 0..self.len {
112 let (i1, i2) = self.ipiv[self.len - i - 1];
113 rhs.swap_rows(i1, i2)
114 }
115 }
116
117 #[inline]
119 pub fn permute_columns<T: Scalar, R2: Dim, C2: Dim, S2>(&self, rhs: &mut Matrix<T, R2, C2, S2>)
120 where
121 S2: StorageMut<T, R2, C2>,
122 {
123 for i in self.ipiv.rows_range(..self.len).iter() {
124 rhs.swap_columns(i.0, i.1)
125 }
126 }
127
128 #[inline]
130 pub fn inv_permute_columns<T: Scalar, R2: Dim, C2: Dim, S2>(
131 &self,
132 rhs: &mut Matrix<T, R2, C2, S2>,
133 ) where
134 S2: StorageMut<T, R2, C2>,
135 {
136 for i in 0..self.len {
137 let (i1, i2) = self.ipiv[self.len - i - 1];
138 rhs.swap_columns(i1, i2)
139 }
140 }
141
142 #[must_use]
144 pub fn len(&self) -> usize {
145 self.len
146 }
147
148 #[must_use]
150 pub fn is_empty(&self) -> bool {
151 self.len() == 0
152 }
153
154 #[inline]
156 #[must_use]
157 pub fn determinant<T: One + ClosedNeg>(&self) -> T {
158 if self.len % 2 == 0 {
159 T::one()
160 } else {
161 -T::one()
162 }
163 }
164}