1pub trait Permutation {
3 fn len(&self) -> usize;
5
6 fn inverse(&self) -> Self;
8
9 fn indices(&self) -> &[usize];
11
12 fn pow(&self, exp: u32) -> Self;
13}
14
15mod without_std {
16 use super::*;
17 use crate::perm_type::PermS;
18
19 impl<const SIZE: usize> Permutation for PermS<SIZE> {
20 fn indices(&self) -> &[usize] {
21 self.indices.as_ref()
22 }
23
24 fn len(&self) -> usize {
25 SIZE
26 }
27
28 fn inverse(&self) -> Self {
29 let mut inversed = [0; SIZE];
30 inverse_indices(self.indices.as_ref(), &mut inversed);
31 Self { indices: inversed }
32 }
33
34 fn pow(&self, exp: u32) -> Self {
35 let mut mask = u32_leading_bit(exp);
36 let mut pow = Self::identity();
37
38 loop {
40 if exp & mask != 0 {
41 pow = &pow * self;
42 }
43
44 mask >>= 1;
45
46 if mask == 0 {
47 break;
48 } else {
49 pow = &pow * &pow;
50 }
51 }
52
53 pow
54 }
55 }
56
57 #[cfg(test)]
58 mod tests {
59 use super::*;
60 use crate::apply::PermApply;
61 use rand::prelude::*;
62
63 #[test]
64 fn static_inverse() {
65 const SIZE: usize = 1024;
66 {
67 let mut rng = rand::thread_rng();
68
69 let mut perm = PermS::<SIZE>::identity();
70 perm.indices.shuffle(&mut rng);
71 let inverse = perm.inverse();
72
73 let mut orig = [0usize; SIZE];
74 rng.fill(&mut orig);
75
76 let mut new = orig.clone();
77 perm.apply(&mut new);
78 inverse.apply(&mut new);
79
80 assert_eq!(orig, new);
81 }
82
83 {
84 assert_eq!(
85 PermS::<SIZE>::cycle().inverse(),
86 PermS::<SIZE>::reverse_cycle()
87 );
88 }
89 }
90 }
91}
92
93#[cfg(feature = "std")]
94mod with_std {
95 use super::*;
96 use crate::perm_type::PermD;
97
98 impl Permutation for PermD {
99 fn indices(&self) -> &[usize] {
100 self.indices.as_ref()
101 }
102
103 fn len(&self) -> usize {
104 self.indices.len()
105 }
106
107 fn inverse(&self) -> Self {
108 let mut inversed = vec![0; self.indices.len()];
109 inverse_indices(self.indices.as_slice(), &mut inversed);
110 Self { indices: inversed }
111 }
112
113 fn pow(&self, exp: u32) -> Self {
114 let mut mask = u32_leading_bit(exp);
115 let mut pow = Self::identity(self.indices.len());
116
117 loop {
119 if exp & mask != 0 {
120 pow = &pow * self;
121 }
122
123 mask >>= 1;
124
125 if mask == 0 {
126 break;
127 } else {
128 pow = &pow * &pow;
129 }
130 }
131
132 pow
133 }
134 }
135
136 #[cfg(test)]
137 mod tests {
138 use super::*;
139 use crate::{apply::PermApply, perm_type::PermS};
140 use rand::prelude::*;
141 use std::collections::HashSet;
142
143 #[test]
144 fn dynamic_inverse() {
145 const SIZE: usize = 1024;
146 {
147 let mut rng = rand::thread_rng();
148
149 let mut perm = PermD::identity(SIZE);
150 perm.indices.shuffle(&mut rng);
151 let inverse = perm.inverse();
152
153 let mut orig = [0usize; SIZE];
154 rng.fill(&mut orig);
155
156 let mut new = orig.clone();
157 perm.apply(&mut new).unwrap();
158 inverse.apply(&mut new).unwrap();
159
160 assert_eq!(orig, new);
161 }
162
163 {
164 assert_eq!(PermD::cycle(SIZE).inverse(), PermD::reverse_cycle(SIZE));
165 }
166 }
167
168 #[test]
169 fn dynamic_pow() {
170 let cycle = PermD::cycle(6);
171 assert_eq!(cycle.pow(5), PermD::reverse_cycle(6));
172 assert_eq!(cycle.pow(6), PermD::identity(6));
173
174 let set: HashSet<_> = (0..6).map(|exp| cycle.pow(exp)).collect();
175 assert_eq!(set.len(), 6);
176 }
177
178 #[test]
179 fn static_pow() {
180 let cycle = PermS::<6>::cycle();
181 assert_eq!(cycle.pow(5), PermS::<6>::reverse_cycle());
182 assert_eq!(cycle.pow(6), PermS::<6>::identity());
183
184 let set: HashSet<_> = (0..6).map(|exp| cycle.pow(exp)).collect();
185 assert_eq!(set.len(), 6);
186 }
187 }
188}
189
190fn inverse_indices(indices: &[usize], inverse_indices: &mut [usize]) {
191 indices.iter().enumerate().for_each(|(dst, &src)| {
192 inverse_indices[src] = dst;
193 });
194}
195
196fn u32_leading_bit(n: u32) -> u32 {
197 let n = n as u64;
198 let n = n | (n >> 1);
199 let n = n | (n >> 2);
200 let n = n | (n >> 4);
201 let n = n | (n >> 8);
202 let n = n | (n >> 16);
203 ((n + 1) >> 1) as u32
204}
205
206#[cfg(test)]
207mod tests {
208 use super::*;
209
210 #[test]
211 fn u32_leading_bit_test() {
212 assert_eq!(u32_leading_bit(0b1), 0b1);
213 assert_eq!(u32_leading_bit(0b10), 0b10);
214 assert_eq!(u32_leading_bit(0b11), 0b10);
215 assert_eq!(u32_leading_bit(0b100111), 0b100000);
216 assert_eq!(
217 u32_leading_bit(0b_11111111_11111111_11111111_11111111),
218 0b_10000000_00000000_00000000_00000000
219 );
220 }
221}