mesh_sieve/topology/
orientation.rs1use core::fmt::{Debug, Formatter};
5
6use crate::topology::sieve::oriented::Orientation;
7
8#[derive(Copy, Clone, Eq, PartialEq, Hash, Default)]
11#[repr(transparent)]
12pub struct BitFlip(pub bool);
13impl Debug for BitFlip {
14 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
15 f.debug_tuple("BitFlip").field(&self.0).finish()
16 }
17}
18impl Orientation for BitFlip {
19 #[inline]
20 fn compose(a: Self, b: Self) -> Self {
21 BitFlip(a.0 ^ b.0)
22 }
23 #[inline]
24 fn inverse(a: Self) -> Self {
25 a
26 }
27}
28
29#[derive(Copy, Clone, Eq, PartialEq, Hash)]
31pub struct Rot<const N: u8>(pub u8);
32impl<const N: u8> Default for Rot<N> {
33 fn default() -> Self {
34 Rot(0)
35 }
36}
37impl<const N: u8> Debug for Rot<N> {
38 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
39 f.debug_tuple("Rot").field(&self.0).finish()
40 }
41}
42impl<const N: u8> Orientation for Rot<N> {
43 #[inline]
44 fn compose(a: Self, b: Self) -> Self {
45 Rot::<N>((a.0 + b.0) % N)
46 }
47 #[inline]
48 fn inverse(a: Self) -> Self {
49 Rot::<N>((N - (a.0 % N)) % N)
50 }
51}
52
53#[derive(Copy, Clone, Eq, PartialEq, Hash)]
56pub struct Dihedral<const N: u8> {
57 pub rot: u8,
58 pub flip: bool,
59}
60impl<const N: u8> Default for Dihedral<N> {
61 fn default() -> Self {
62 Self {
63 rot: 0,
64 flip: false,
65 }
66 }
67}
68impl<const N: u8> Debug for Dihedral<N> {
69 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
70 f.debug_struct("Dihedral")
71 .field("rot", &self.rot)
72 .field("flip", &self.flip)
73 .finish()
74 }
75}
76impl<const N: u8> Orientation for Dihedral<N> {
77 #[inline]
78 fn compose(a: Self, b: Self) -> Self {
79 let add = if a.flip {
80 (N - (b.rot % N)) % N
81 } else {
82 b.rot % N
83 };
84 let rot = (a.rot + add) % N;
85 let flip = a.flip ^ b.flip;
86 Self { rot, flip }
87 }
88 #[inline]
89 fn inverse(a: Self) -> Self {
90 if !a.flip {
91 Self {
92 rot: (N - (a.rot % N)) % N,
93 flip: false,
94 }
95 } else {
96 Self {
97 rot: a.rot % N,
98 flip: true,
99 }
100 }
101 }
102}
103
104#[derive(Copy, Clone, Eq, PartialEq, Hash)]
108pub struct Perm<const K: usize>(pub [u8; K]);
109impl<const K: usize> Default for Perm<K> {
110 fn default() -> Self {
111 let mut id = [0u8; K];
112 let mut i = 0;
113 while i < K {
114 id[i] = i as u8;
115 i += 1;
116 }
117 Perm(id)
118 }
119}
120impl<const K: usize> Debug for Perm<K> {
121 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
122 f.debug_tuple("Perm").field(&self.0).finish()
123 }
124}
125impl<const K: usize> Perm<K> {
126 #[inline]
127 pub fn new_unchecked(p: [u8; K]) -> Self {
128 Perm(p)
129 }
130 #[inline]
131 pub fn invert(&self) -> Self {
132 let mut inv = [0u8; K];
133 let mut i = 0;
134 while i < K {
135 inv[self.0[i] as usize] = i as u8;
136 i += 1;
137 }
138 Perm(inv)
139 }
140}
141impl<const K: usize> Orientation for Perm<K> {
142 #[inline]
143 fn compose(a: Self, b: Self) -> Self {
144 let mut out = [0u8; K];
145 let mut i = 0;
146 while i < K {
147 out[i] = a.0[b.0[i] as usize];
148 i += 1;
149 }
150 Perm(out)
151 }
152 #[inline]
153 fn inverse(a: Self) -> Self {
154 a.invert()
155 }
156}
157
158pub use BitFlip as Sign; pub type D3 = Dihedral<3>;
163pub type D4 = Dihedral<4>;
165pub type S3 = Perm<3>;
167pub type S4 = Perm<4>;
169
170#[inline]
174pub fn accumulate_path<O, I>(path: I) -> O
175where
176 O: Orientation,
177 I: IntoIterator<Item = O>,
178{
179 path.into_iter()
180 .fold(O::default(), |acc, step| O::compose(acc, step))
181}
182
183pub trait AccumulatePathExt: Sized {
185 fn accumulate_path<O, I>(path: I) -> O
186 where
187 O: Orientation,
188 I: IntoIterator<Item = O>,
189 {
190 accumulate_path(path)
191 }
192}
193impl<T> AccumulatePathExt for T {}