rusty_perm/
from_indices.rs

1use crate::common::*;
2
3/// An operator that builds a permutation from a list indexes.
4pub trait PermFromIndices<T>
5where
6    Self: Sized,
7{
8    fn from_indices(indices: T) -> Option<Self>;
9}
10
11mod without_std {
12    use super::*;
13    use crate::perm_type::PermS;
14
15    impl<const SIZE: usize> PermFromIndices<[usize; SIZE]> for PermS<SIZE> {
16        /// Builds a static permutation from an owned array of indices.
17        fn from_indices(indices: [usize; SIZE]) -> Option<Self> {
18            if !check_indices(indices.as_ref(), &mut [false; SIZE]) {
19                return None;
20            }
21            Some(Self { indices })
22        }
23    }
24
25    impl<const SIZE: usize> PermFromIndices<&[usize; SIZE]> for PermS<SIZE> {
26        /// Builds a static permutation from a borrowed array of indices.
27        fn from_indices(indices: &[usize; SIZE]) -> Option<Self> {
28            Self::from_indices(indices.as_ref())
29        }
30    }
31
32    impl<const SIZE: usize> PermFromIndices<&[usize]> for PermS<SIZE> {
33        /// Builds a static permutation from a slice of indices.
34        fn from_indices(indices: &[usize]) -> Option<Self> {
35            if indices.len() != SIZE {
36                return None;
37            }
38            if !check_indices(indices, &mut [false; SIZE]) {
39                return None;
40            }
41            Some(Self {
42                indices: indices.try_into().unwrap(),
43            })
44        }
45    }
46}
47
48#[cfg(feature = "std")]
49mod with_std {
50    use super::*;
51    use crate::perm_type::{PermD, PermS};
52
53    impl PermFromIndices<Cow<'_, [usize]>> for PermD {
54        /// Builds a dynamic permutation from a copy-on-write slice of indices.
55        fn from_indices(indices: Cow<'_, [usize]>) -> Option<Self> {
56            if !check_indices(indices.as_ref(), &mut vec![false; indices.len()]) {
57                return None;
58            }
59            Some(Self {
60                indices: indices.into_owned(),
61            })
62        }
63    }
64
65    impl PermFromIndices<Vec<usize>> for PermD {
66        /// Builds a dynamic permutation from a vector of indices.
67        fn from_indices(indices: Vec<usize>) -> Option<Self> {
68            if !check_indices(indices.as_slice(), &mut vec![false; indices.len()]) {
69                return None;
70            }
71            Some(Self { indices })
72        }
73    }
74
75    impl PermFromIndices<&'_ [usize]> for PermD {
76        /// Builds a dynamic permutation from a slice of indices.
77        fn from_indices(indices: &[usize]) -> Option<Self> {
78            Self::from_indices(Cow::<'_, [usize]>::from(indices))
79        }
80    }
81
82    impl<const SIZE: usize> PermFromIndices<[usize; SIZE]> for PermD {
83        /// Builds a dynamic permutation from an array of indices.
84        fn from_indices(indices: [usize; SIZE]) -> Option<Self> {
85            Self::from_indices(indices.as_ref())
86        }
87    }
88
89    impl<const SIZE: usize> PermFromIndices<Vec<usize>> for PermS<SIZE> {
90        /// Builds a static permutation from a vector indices.
91        fn from_indices(indices: Vec<usize>) -> Option<Self> {
92            let indices: &[usize] = indices.as_ref();
93            Self::from_indices(indices)
94        }
95    }
96
97    impl<const SIZE: usize> PermFromIndices<Cow<'_, [usize]>> for PermS<SIZE> {
98        /// Builds a static permutation from a copy-on-write slice of indices.
99        fn from_indices(indices: Cow<'_, [usize]>) -> Option<Self> {
100            Self::from_indices(indices.as_ref())
101        }
102    }
103}
104
105fn check_indices(indices: &[usize], visited: &mut [bool]) -> bool {
106    let len = indices.len();
107    indices.iter().all(|&index| {
108        if index >= len || visited[index] {
109            false
110        } else {
111            visited[index] = true;
112            true
113        }
114    })
115}