1use std::ops::{Mul, MulAssign};
8use auto_impl_ops::auto_ops;
9use either::Either;
10
11#[derive(Clone, Debug, PartialEq, Eq)]
17pub struct Perm {
18 data: Either<usize, Vec<usize>>,
19}
20
21impl Perm {
22 pub(crate) fn new(data: Vec<usize>) -> Self {
26 assert!(is_valid_perm(&data), "not a valid permutation: {:?}", data);
27 Self::new_unchecked(data)
28 }
29
30 fn new_unchecked(data: Vec<usize>) -> Self {
32 Self { data: Either::Right(data) }
33 }
34
35 pub fn from_indices<I>(images: I) -> Self
38 where I: IntoIterator<Item = usize> {
39 Self::new(images.into_iter().collect())
40 }
41
42 pub fn id(n: usize) -> Self {
44 Self { data: Either::Left(n) }
45 }
46
47 pub fn len(&self) -> usize {
48 match &self.data {
49 Either::Left(n) => *n,
50 Either::Right(v) => v.len(),
51 }
52 }
53
54 pub fn at(&self, i: usize) -> usize {
56 match &self.data {
57 Either::Left(_) => i,
58 Either::Right(v) => v[i],
59 }
60 }
61
62 pub fn is_id(&self) -> bool {
64 match &self.data {
65 Either::Left(_) => true,
66 Either::Right(v) => v.iter().enumerate().all(|(i, &x)| i == x),
67 }
68 }
69
70 pub fn inv(&self) -> Self {
72 match &self.data {
73 Either::Left(n) => Self::id(*n),
74 Either::Right(v) => {
75 let mut inv = vec![0; v.len()];
76 for (i, &j) in v.iter().enumerate() {
77 inv[j] = i;
78 }
79 Self { data: Either::Right(inv) }
80 }
81 }
82 }
83
84 pub fn apply_to<R>(&self, y: Vec<R>) -> Vec<R> {
87 assert_eq!(y.len(), self.len());
88 match &self.data {
89 Either::Left(_) => y,
90 Either::Right(v) => {
91 let n = v.len();
92 let mut result: Vec<R> = Vec::with_capacity(n);
93 let dst = result.as_mut_ptr();
94 for (i, x) in y.into_iter().enumerate() {
95 unsafe { dst.add(v[i]).write(x); }
98 }
99 unsafe { result.set_len(n); }
101 result
102 }
103 }
104 }
105
106 pub fn apply_inv_to<R>(&self, y: Vec<R>) -> Vec<R> {
110 assert_eq!(y.len(), self.len());
111 match &self.data {
112 Either::Left(_) => y,
113 Either::Right(v) => {
114 let mut y = std::mem::ManuallyDrop::new(y);
115 let src = y.as_mut_ptr();
116 let cap = y.capacity();
117 let result: Vec<R> = v.iter().map(|&k| unsafe { src.add(k).read() }).collect();
119 unsafe { drop(Vec::from_raw_parts(src, 0, cap)); }
122 result
123 }
124 }
125 }
126
127 pub fn shift(self, r: usize) -> Self {
131 match self.data {
132 Either::Left(n) => Self::id(n + r),
133 Either::Right(v) => {
134 let mut data: Vec<usize> = (0..r).collect();
135 data.extend(v.into_iter().map(|x| x + r));
136 Self::new(data)
137 }
138 }
139 }
140
141 pub fn extend(self, r: usize) -> Self {
145 match self.data {
146 Either::Left(n) => Self::id(n + r),
147 Either::Right(mut v) => {
148 let m = v.len();
149 v.extend(m..m + r);
150 Self::new(v)
151 }
152 }
153 }
154
155 pub fn forward_indices<I>(n: usize, prefix: I) -> Self
160 where I: IntoIterator<Item = usize> {
161 let mut data = vec![0usize; n];
162 let mut taken = vec![false; n];
163 let mut k = 0;
164 for i in prefix {
165 assert!(i < n, "index {i} out of range 0..{n}");
166 assert!(!taken[i], "duplicate index {i} in prefix");
167 data[i] = k;
168 taken[i] = true;
169 k += 1;
170 }
171 if k == 0 {
172 return Self::id(n);
173 }
174 let mut pos = k;
175 for j in 0..n {
176 if !taken[j] {
177 data[j] = pos;
178 pos += 1;
179 }
180 }
181 Self::new_unchecked(data)
182 }
183}
184
185#[auto_ops]
187impl Mul<&Perm> for &Perm {
188 type Output = Perm;
189 fn mul(self, rhs: &Perm) -> Perm {
190 assert_eq!(self.len(), rhs.len(), "permutations must have the same length");
191 match (&self.data, &rhs.data) {
192 (Either::Left(_), _) => rhs.clone(),
193 (_, Either::Left(_)) => self.clone(),
194 (Either::Right(_), Either::Right(qv)) => {
195 Perm::new(qv.iter().map(|&i| self.at(i)).collect())
196 }
197 }
198 }
199}
200
201fn is_valid_perm(v: &[usize]) -> bool {
202 let n = v.len();
203 let mut seen = vec![false; n];
204 for &x in v {
205 if x >= n || seen[x] {
206 return false;
207 }
208 seen[x] = true;
209 }
210 true
211}
212
213#[cfg(test)]
214mod tests {
215 use super::*;
216
217 #[test]
220 fn id() {
221 let p = Perm::id(4);
222 assert!(p.is_id());
223 assert_eq!(p.len(), 4);
224 for i in 0..4 {
225 assert_eq!(p.at(i), i);
226 }
227 }
228
229 #[test]
230 fn new_accepts_valid() {
231 let p = Perm::new(vec![2, 0, 1]);
232 assert_eq!(p.at(0), 2);
233 assert_eq!(p.at(1), 0);
234 assert_eq!(p.at(2), 1);
235 }
236
237 #[test]
238 #[should_panic]
239 fn new_rejects_duplicate() {
240 let _ = Perm::new(vec![0, 0, 1]);
241 }
242
243 #[test]
244 #[should_panic]
245 fn new_rejects_out_of_range() {
246 let _ = Perm::new(vec![0, 1, 5]);
247 }
248
249 #[test]
252 fn is_id_true_false() {
253 assert!(Perm::id(3).is_id());
254 assert!(Perm::new(vec![0, 1, 2]).is_id());
256 assert!(!Perm::new(vec![1, 0]).is_id());
257 }
258
259 #[test]
260 fn accessors() {
261 let v = vec![2, 0, 1, 3];
262 let p = Perm::new(v.clone());
263 assert_eq!(p.len(), 4);
264 for (i, &expected) in v.iter().enumerate() {
265 assert_eq!(p.at(i), expected);
266 }
267 }
268
269 #[test]
272 fn inv_of_id() {
273 let id = Perm::id(5);
274 assert_eq!(id.inv(), id);
275 }
276
277 #[test]
278 fn inv_of_inv() {
279 let p = Perm::new(vec![2, 0, 3, 1]);
280 assert_eq!(p.inv().inv(), p);
281 }
282
283 #[test]
284 fn inv_roundtrip() {
285 let p = Perm::new(vec![2, 0, 3, 1]);
286 let pi = p.inv();
287 for i in 0..p.len() {
288 assert_eq!(pi.at(p.at(i)), i);
289 assert_eq!(p.at(pi.at(i)), i);
290 }
291 }
292
293 #[test]
296 fn mul_formula() {
297 let p = Perm::new(vec![2, 0, 3, 1]);
299 let q = Perm::new(vec![1, 2, 0, 3]);
300 let pq = &p * &q;
301 for i in 0..4 {
302 assert_eq!(pq.at(i), p.at(q.at(i)));
303 }
304 }
305
306 #[test]
307 fn mul_with_id() {
308 let p = Perm::new(vec![2, 0, 3, 1]);
309 let id = Perm::id(4);
310 assert_eq!(&p * &id, p);
311 assert_eq!(&id * &p, p);
312 }
313
314 #[test]
315 fn mul_id_with_id() {
316 let id = Perm::id(4);
317 assert_eq!(&id * &id, id);
318 }
319
320 #[test]
321 fn mul_by_inverse_is_id() {
322 let p = Perm::new(vec![2, 0, 3, 1]);
323 assert!((&p * &p.inv()).is_id());
324 assert!((&p.inv() * &p).is_id());
325 }
326
327 #[test]
328 fn mul_associative() {
329 let p = Perm::new(vec![2, 0, 3, 1]);
330 let q = Perm::new(vec![1, 3, 0, 2]);
331 let r = Perm::new(vec![3, 1, 2, 0]);
332 assert_eq!(&(&p * &q) * &r, &p * &(&q * &r));
333 }
334
335 #[test]
336 #[should_panic]
337 fn mul_panics_on_dim_mismatch() {
338 let p = Perm::id(3);
339 let q = Perm::id(4);
340 let _ = &p * &q;
341 }
342
343 #[test]
346 fn apply_to_consumes() {
347 let p = Perm::from_indices([1, 2, 0]);
350 assert_eq!(p.apply_to(vec![10, 20, 30]), vec![30, 10, 20]);
351 }
352
353 #[test]
354 fn apply_to_by_id() {
355 let id = Perm::id(4);
356 assert_eq!(id.apply_to(vec![1, 2, 3, 4]), vec![1, 2, 3, 4]);
357 }
358
359 #[test]
360 fn apply_inv_to_consumes() {
361 let p = Perm::from_indices([1, 2, 0]);
363 assert_eq!(p.apply_inv_to(vec![10, 20, 30]), vec![20, 30, 10]);
364 }
365
366 #[test]
367 fn apply_inv_to_inverts_apply_to() {
368 let p = Perm::from_indices([2, 0, 3, 1]);
370 let y = vec![10, 20, 30, 40];
371 let permuted = p.apply_to(y.clone());
372 assert_eq!(p.apply_inv_to(permuted), y);
373 }
374
375 #[test]
376 #[should_panic]
377 fn apply_to_panics_on_len_mismatch() {
378 let p = Perm::id(3);
379 let _ = p.apply_to(vec![1, 2]);
380 }
381
382 #[test]
385 fn shift_basic() {
386 let p = Perm::from_indices([1, 2, 0]);
388 let s = p.shift(2);
389 assert_eq!(s.len(), 5);
390 for (i, &x) in [0, 1, 3, 4, 2].iter().enumerate() {
391 assert_eq!(s.at(i), x);
392 }
393 }
394
395 #[test]
396 fn shift_zero() {
397 let p = Perm::from_indices([2, 0, 1]);
398 let s = p.clone().shift(0);
399 assert_eq!(s, p);
400 }
401
402 #[test]
403 fn shift_of_id() {
404 let s = Perm::id(3).shift(2);
406 assert!(s.is_id());
407 assert_eq!(s.len(), 5);
408 }
409
410 #[test]
413 fn extend_basic() {
414 let p = Perm::from_indices([1, 2, 0]);
416 let s = p.extend(2);
417 assert_eq!(s.len(), 5);
418 for (i, &x) in [1, 2, 0, 3, 4].iter().enumerate() {
419 assert_eq!(s.at(i), x);
420 }
421 }
422
423 #[test]
424 fn extend_zero() {
425 let p = Perm::from_indices([2, 0, 1]);
426 let s = p.clone().extend(0);
427 assert_eq!(s, p);
428 }
429
430 #[test]
431 fn extend_of_id() {
432 let s = Perm::id(3).extend(2);
434 assert!(s.is_id());
435 assert_eq!(s.len(), 5);
436 }
437
438 #[test]
441 fn forward_indices_basic() {
442 let p = Perm::forward_indices(5, [3, 1]);
444 let expected = [2, 1, 3, 0, 4];
445 for (i, &x) in expected.iter().enumerate() {
446 assert_eq!(p.at(i), x);
447 }
448 }
449
450 #[test]
451 fn forward_indices_empty_prefix() {
452 let p = Perm::forward_indices(4, std::iter::empty());
453 assert!(p.is_id());
454 }
455
456 #[test]
457 fn forward_indices_full_prefix() {
458 let p = Perm::forward_indices(4, [2, 0, 3, 1]);
460 assert_eq!(p.at(2), 0);
461 assert_eq!(p.at(0), 1);
462 assert_eq!(p.at(3), 2);
463 assert_eq!(p.at(1), 3);
464 }
465
466 #[test]
469 fn mul_all_ref_variants() {
470 let p = Perm::new(vec![2, 0, 3, 1]);
471 let q = Perm::new(vec![1, 2, 0, 3]);
472 let expected = &p * &q;
473
474 assert_eq!(p.clone() * q.clone(), expected);
475 assert_eq!(p.clone() * &q, expected);
476 assert_eq!(&p * q.clone(), expected);
477 assert_eq!(&p * &q, expected);
478 }
479}