rusty_perm/
product.rs

1use crate::common::*;
2
3/// The permutation composition operator.
4pub trait PermProduct<Rhs> {
5    type Output;
6
7    fn perm_product(&self, other: &Rhs) -> Self::Output;
8}
9
10mod without_std {
11    use super::*;
12    use crate::perm_type::PermS;
13
14    impl<const SIZE: usize> PermProduct<PermS<SIZE>> for PermS<SIZE> {
15        type Output = PermS<SIZE>;
16
17        fn perm_product(&self, other: &PermS<SIZE>) -> Self::Output {
18            let mut indices = [0; SIZE];
19            product(&self.indices, &other.indices, &mut indices);
20            Self { indices }
21        }
22    }
23
24    impl<const SIZE: usize> Mul<&PermS<SIZE>> for &PermS<SIZE> {
25        type Output = PermS<SIZE>;
26
27        fn mul(self, other: &PermS<SIZE>) -> Self::Output {
28            self.perm_product(other)
29        }
30    }
31
32    impl<'a, const SIZE: usize> Product<&'a PermS<SIZE>> for PermS<SIZE> {
33        fn product<I>(iter: I) -> Self
34        where
35            I: Iterator<Item = &'a PermS<SIZE>>,
36        {
37            iter.fold(Self::identity(), |product, item| product.mul(item))
38        }
39    }
40
41    impl<const SIZE: usize> Product<PermS<SIZE>> for PermS<SIZE> {
42        fn product<I>(iter: I) -> Self
43        where
44            I: Iterator<Item = PermS<SIZE>>,
45        {
46            iter.fold(Self::identity(), |product, item| product.mul(&item))
47        }
48    }
49}
50
51#[cfg(feature = "std")]
52mod with_std {
53    use super::*;
54    use crate::{
55        perm_trait::Permutation,
56        perm_type::{PermD, PermS},
57    };
58
59    impl<const SIZE: usize> PermProduct<PermD> for PermS<SIZE> {
60        type Output = Option<PermS<SIZE>>;
61
62        fn perm_product(&self, other: &PermD) -> Self::Output {
63            if other.len() != SIZE {
64                return None;
65            }
66            let mut indices = [0; SIZE];
67            product(&self.indices, &other.indices, &mut indices);
68            Some(Self { indices })
69        }
70    }
71
72    impl<const SIZE: usize> PermProduct<PermS<SIZE>> for PermD {
73        type Output = Option<PermS<SIZE>>;
74
75        fn perm_product(&self, other: &PermS<SIZE>) -> Self::Output {
76            if self.len() != SIZE {
77                return None;
78            }
79            let mut indices = [0; SIZE];
80            product(&self.indices, &other.indices, &mut indices);
81            Some(PermS { indices })
82        }
83    }
84
85    impl PermProduct<PermD> for PermD {
86        type Output = Option<PermD>;
87
88        fn perm_product(&self, other: &PermD) -> Self::Output {
89            if self.len() != other.len() {
90                return None;
91            }
92            let mut indices = vec![0; self.len()];
93            product(&self.indices, &other.indices, &mut indices);
94            Some(Self { indices })
95        }
96    }
97
98    impl<const SIZE: usize> Mul<&PermD> for &PermS<SIZE> {
99        type Output = PermS<SIZE>;
100
101        fn mul(self, other: &PermD) -> Self::Output {
102            self.perm_product(other).unwrap()
103        }
104    }
105
106    impl<const SIZE: usize> Mul<&PermS<SIZE>> for &PermD {
107        type Output = PermS<SIZE>;
108
109        fn mul(self, other: &PermS<SIZE>) -> Self::Output {
110            self.perm_product(other).unwrap()
111        }
112    }
113
114    impl Mul<&PermD> for &PermD {
115        type Output = PermD;
116
117        fn mul(self, other: &PermD) -> Self::Output {
118            self.perm_product(other).unwrap()
119        }
120    }
121
122    impl<'a, const SIZE: usize> Product<&'a PermD> for Option<PermS<SIZE>> {
123        fn product<I>(mut iter: I) -> Self
124        where
125            I: Iterator<Item = &'a PermD>,
126        {
127            iter.try_fold(PermS::<SIZE>::identity(), |product, item| -> Option<_> {
128                product.perm_product(item)
129            })
130        }
131    }
132
133    impl<const SIZE: usize> Product<PermD> for Option<PermS<SIZE>> {
134        fn product<I>(mut iter: I) -> Self
135        where
136            I: Iterator<Item = PermD>,
137        {
138            iter.try_fold(PermS::<SIZE>::identity(), |product, item| -> Option<_> {
139                product.perm_product(&item)
140            })
141        }
142    }
143
144    impl<'a, const SIZE: usize> Product<&'a PermS<SIZE>> for PermD {
145        fn product<I>(iter: I) -> Self
146        where
147            I: Iterator<Item = &'a PermS<SIZE>>,
148        {
149            iter.fold(PermS::<SIZE>::identity(), |product, item| product.mul(item))
150                .into_dynamic()
151        }
152    }
153
154    impl<const SIZE: usize> Product<PermS<SIZE>> for PermD {
155        fn product<I>(iter: I) -> Self
156        where
157            I: Iterator<Item = PermS<SIZE>>,
158        {
159            iter.fold(PermS::<SIZE>::identity(), |product, item| {
160                product.mul(&item)
161            })
162            .into_dynamic()
163        }
164    }
165
166    impl<'a> Product<&'a PermD> for Option<PermD> {
167        fn product<I>(mut iter: I) -> Self
168        where
169            I: Iterator<Item = &'a PermD>,
170        {
171            let first = iter.next()?.to_owned();
172            iter.try_fold(first, |product, item| -> Option<_> {
173                product.perm_product(item)
174            })
175        }
176    }
177
178    impl Product<PermD> for Option<PermD> {
179        fn product<I>(mut iter: I) -> Self
180        where
181            I: Iterator<Item = PermD>,
182        {
183            let first = iter.next()?;
184            iter.try_fold(first, |product, item| -> Option<_> {
185                product.perm_product(&item)
186            })
187        }
188    }
189}
190
191fn product(lhs: &[usize], rhs: &[usize], output: &mut [usize]) {
192    let len = output.len();
193    (0..len).for_each(|src| {
194        let dst = lhs[rhs[src]];
195        output[src] = dst;
196    });
197}