haar_lib/algebra/
transform.rs

1//! 配列の並び替えの合成
2pub use crate::algebra::traits::*;
3use crate::impl_algebra;
4
5/// 変換操作
6#[derive(Clone, Debug, Default)]
7pub struct Transformation {
8    value: Option<Vec<usize>>,
9}
10
11impl Transformation {
12    /// `i`番目の要素を返す。
13    pub fn get(&self, i: usize) -> usize {
14        self.value.as_ref().map_or_else(|| i, |a| a[i])
15    }
16
17    /// $b_i = a_{T_i}$を満たすbを返す。
18    pub fn apply<T: Clone>(&self, a: Vec<T>) -> Vec<T> {
19        self.value
20            .as_ref()
21            .map(|t| t.iter().map(|&i| a[i].clone()).collect())
22            .unwrap_or(a)
23    }
24
25    /// 単位元であるとき、`true`を返す。
26    pub fn is_identity(&self) -> bool {
27        self.value
28            .as_ref()
29            .is_none_or(|a| a.iter().enumerate().all(|(i, &x)| i == x))
30    }
31
32    /// 操作を合成する。
33    pub fn compose(self, other: Self) -> Self {
34        Self {
35            value: match (self.value, other.value) {
36                (Some(a), Some(b)) => {
37                    let n = a.len();
38                    assert_eq!(a.len(), b.len());
39                    Some((0..n).map(|i| a[b[i]]).collect())
40                }
41                (a, None) => a,
42                (None, b) => b,
43            },
44        }
45    }
46}
47
48impl TryFrom<Vec<usize>> for Transformation {
49    type Error = &'static str;
50
51    fn try_from(value: Vec<usize>) -> Result<Self, Self::Error> {
52        let n = value.len();
53        value
54            .iter()
55            .all(|&i| i < n)
56            .then_some(Self { value: Some(value) })
57            .ok_or("すべての値は`.len()`未満でなければならない。")
58    }
59}
60
61impl PartialEq for Transformation {
62    fn eq(&self, other: &Self) -> bool {
63        match (&self.value, &other.value) {
64            (Some(a), Some(b)) => a == b,
65            _ => self.is_identity() && other.is_identity(),
66        }
67    }
68}
69
70impl_algebra!(
71    Transformation;
72    op: |a: Self, b: Self| a.compose(b);
73    id: Self { value: None };
74    assoc;
75);