1use std::fmt::Display;
2
3use yui_core::bitseq::Bit;
4use yui_core::CloneAnd;
5
6use crate::Path;
7use super::Edge;
8
9use NodeType::{X, Xm, V, H};
10
11#[derive(Clone, Copy, PartialEq, Eq, Hash, derive_more::Display, Debug)]
12pub enum NodeType {
13 X, Xm, V, H
14}
15
16impl NodeType {
17 pub fn cc(&mut self) {
18 match self {
19 Xm => *self = X,
20 X => *self = Xm,
21 _ => ()
22 }
23 }
24}
25
26#[derive(Debug, Clone, PartialEq, Eq, Hash)]
27pub struct Node {
28 ntype: NodeType,
29 edges: [Edge; 4]
30}
31
32impl Node {
33 pub fn new(ntype: NodeType, edges: [Edge; 4]) -> Self {
34 Node { ntype, edges }
35 }
36
37 pub fn from_pd_code(edges: [Edge; 4]) -> Self {
38 Node::new(NodeType::X, edges)
39 }
40
41 pub fn ntype(&self) -> NodeType {
42 self.ntype
43 }
44
45 pub fn edge(&self, i: usize) -> Edge {
46 assert!(i < 4);
47 self.edges[i]
48 }
49
50 pub fn edges(&self) -> &[Edge; 4] {
51 &self.edges
52 }
53
54 pub fn min_edge(&self) -> Edge {
55 self.edges.iter().min().unwrap().clone()
56 }
57
58 pub fn is_crossing(&self) -> bool {
59 matches!(self.ntype, X | Xm)
60 }
61
62 pub fn is_resolved(&self) -> bool {
63 matches!(self.ntype, V | H)
64 }
65
66 pub fn resolve(&mut self, r: Bit) {
67 use Bit::{Bit0, Bit1};
68
69 match (self.ntype, r) {
70 (X, Bit0) | (Xm, Bit1) => self.ntype = H,
71 (X, Bit1) | (Xm, Bit0) => self.ntype = V,
72 _ => panic!()
73 }
74 }
75
76 pub fn resolved(&self, r: Bit) -> Self {
77 self.clone_and(|x|
78 x.resolve(r)
79 )
80 }
81
82 pub fn cc(&mut self) {
83 self.ntype.cc()
84 }
85
86 pub fn is_adj_to(&self, x: &Node) -> bool {
87 self.edges.iter().any(|e| x.edges.contains(e))
88 }
89
90 pub fn arcs(&self) -> (Path, Path) {
91 let comp = |i: usize, j: usize| {
92 let (ei, ej) = (self.edges[i], self.edges[j]);
93 if ei == ej {
94 Path::new(vec![ei], true)
95 } else {
96 Path::new(vec![ei, ej], false)
97 }
98 };
99 match self.ntype {
100 X |
101 Xm => (comp(0, 2), comp(1, 3)),
102 V => (comp(0, 3), comp(1, 2)),
103 H => (comp(0, 1), comp(2, 3))
104 }
105 }
106
107 pub fn convert_edges<F>(&self, f: F) -> Self
108 where F: Fn(Edge) -> Edge {
109 Self {
110 ntype: self.ntype,
111 edges: self.edges.map(|e| f(e))
112 }
113 }
114
115 pub(crate) fn traverse_inner(&self, index:usize) -> usize {
116 debug_assert!((0..4).contains(&index));
117
118 match self.ntype {
119 X | Xm => (index + 2) % 4,
120 V => 3 - index,
121 H => (5 - index) % 4
122 }
123 }
124}
125
126impl From<[Edge; 4]> for Node {
127 fn from(edges: [Edge; 4]) -> Self {
128 Self::new(NodeType::X, edges)
129 }
130}
131
132impl Display for Node {
133 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
134 write!(f, "{}{:?}", self.ntype, self.edges)
135 }
136}
137
138#[cfg(test)]
139mod tests {
140 use super::*;
141
142 fn a_crossing(ntype:NodeType) -> Node {
143 Node{
144 ntype,
145 edges: [0,1,2,3]
146 }
147 }
148
149 #[test]
150 fn crossing_is_resolved() {
151 let c = a_crossing(X);
152 assert!(c.is_crossing());
153
154 let c = a_crossing(Xm);
155 assert!(c.is_crossing());
156
157 let c = a_crossing(H);
158 assert!(c.is_resolved());
159
160 let c = a_crossing(V);
161 assert!(c.is_resolved());
162 }
163
164 #[test]
165 fn crossing_resolve() {
166 use Bit::{Bit0, Bit1};
167
168 let mut c = a_crossing(X);
169
170 c.resolve(Bit0);
171 assert!(c.is_resolved());
172 assert_eq!(c.ntype(), H);
173
174 let mut c = a_crossing(X);
175
176 c.resolve(Bit1);
177 assert!(c.is_resolved());
178 assert_eq!(c.ntype(), V);
179
180 let mut c = a_crossing(Xm);
181
182 c.resolve(Bit0);
183 assert!(c.is_resolved());
184 assert_eq!(c.ntype(), V);
185
186 let mut c = a_crossing(Xm);
187
188 c.resolve(Bit1);
189 assert!(c.is_resolved());
190 assert_eq!(c.ntype(), H);
191 }
192
193 #[test]
194 fn crossing_mirror() {
195 let c = a_crossing(X).clone_and(|c| c.cc());
196 assert_eq!(c.ntype(), Xm);
197
198 let c = a_crossing(Xm).clone_and(|c| c.cc());
199 assert_eq!(c.ntype(), X);
200
201 let c = a_crossing(H).clone_and(|c| c.cc());
202 assert_eq!(c.ntype(), H);
203
204 let c = a_crossing(V).clone_and(|c| c.cc());
205 assert_eq!(c.ntype(), V);
206 }
207
208 #[test]
209 fn crossing_pass() {
210 let c = a_crossing(X);
211 assert_eq!(c.traverse_inner(0), 2);
212 assert_eq!(c.traverse_inner(1), 3);
213 assert_eq!(c.traverse_inner(2), 0);
214 assert_eq!(c.traverse_inner(3), 1);
215
216 let c = a_crossing(Xm);
217 assert_eq!(c.traverse_inner(0), 2);
218 assert_eq!(c.traverse_inner(1), 3);
219 assert_eq!(c.traverse_inner(2), 0);
220 assert_eq!(c.traverse_inner(3), 1);
221
222 let c = a_crossing(V);
223 assert_eq!(c.traverse_inner(0), 3);
224 assert_eq!(c.traverse_inner(1), 2);
225 assert_eq!(c.traverse_inner(2), 1);
226 assert_eq!(c.traverse_inner(3), 0);
227
228 let c = a_crossing(H);
229 assert_eq!(c.traverse_inner(0), 1);
230 assert_eq!(c.traverse_inner(1), 0);
231 assert_eq!(c.traverse_inner(2), 3);
232 assert_eq!(c.traverse_inner(3), 2);
233 }
234}