1#![no_std]
2
3#[cfg(test)]
4#[macro_use]
5extern crate std;
6
7extern crate alloc;
8
9#[cfg(test)]
10mod test;
11
12use alloc::collections::btree_map::BTreeMap;
13use alloc::rc::Rc;
14use alloc::vec::Vec;
15use core::cell::RefCell;
16use core::cmp::Ordering;
17
18pub use bromberg_sl2::{BrombergHashable, HashMatrix, I};
19
20#[derive(Clone)]
21pub enum PrefixDiff<T> {
22 LessThan,
23 PrefixOf(T),
24 Equal,
25 PrefixedBy(T),
26 GreaterThan,
27}
28
29#[derive(Clone)]
30pub struct MergleNode<T> {
31 pub elem: T,
32 elem_hash: HashMatrix,
33 height: usize,
34 hash: HashMatrix,
35 pub left: Option<Rc<MergleNode<T>>>,
36 pub right: Option<Rc<MergleNode<T>>>,
37}
38
39type MergleDiff<T> = PrefixDiff<Rc<MergleNode<T>>>;
40
41type MemoizedDiffTable<T> = BTreeMap<(HashMatrix, HashMatrix), MergleDiff<T>>;
42
43#[derive(Default)]
44pub struct MemTableRef<T>(Rc<RefCell<MemoizedDiffTable<T>>>);
45
46impl<T> Clone for MemTableRef<T> {
47 fn clone(&self) -> Self {
48 MemTableRef(Rc::clone(&self.0))
49 }
50}
51
52impl<T: Clone> MemTableRef<T> {
53 pub fn new() -> Self {
54 MemTableRef(Rc::new(RefCell::new(BTreeMap::new())))
55 }
56
57 fn insert(&self, a: HashMatrix, b: HashMatrix, r: PrefixDiff<Rc<MergleNode<T>>>) {
58 let mut table = self.0.borrow_mut();
59 if a > b {
60 table.insert((b, a), r.reverse());
61 } else {
62 table.insert((a, b), r.clone());
63 }
64 }
65
66 fn lookup(&self, a: HashMatrix, b: HashMatrix) -> Option<PrefixDiff<Rc<MergleNode<T>>>> {
67 if a == b {
68 Some(PrefixDiff::Equal)
69 } else {
70 let table = self.0.borrow();
71 if a > b {
72 table.get(&(b, a)).map(|r| r.reverse())
73 } else {
74 table.get(&(a, b)).cloned()
75 }
76 }
77 }
78}
79
80impl<T: Clone> PrefixDiff<T> {
81 fn reverse(&self) -> Self {
82 match self {
83 PrefixDiff::LessThan => PrefixDiff::GreaterThan,
84 PrefixDiff::PrefixOf(t) => PrefixDiff::PrefixedBy(t.clone()),
85 PrefixDiff::Equal => PrefixDiff::Equal,
86 PrefixDiff::PrefixedBy(t) => PrefixDiff::PrefixOf(t.clone()),
87 PrefixDiff::GreaterThan => PrefixDiff::LessThan,
88 }
89 }
90
91 fn from_ord(o: Ordering) -> Self {
92 match o {
93 Ordering::Less => PrefixDiff::LessThan,
94 Ordering::Equal => PrefixDiff::Equal,
95 Ordering::Greater => PrefixDiff::GreaterThan,
96 }
97 }
98}
99
100impl<T: BrombergHashable + Ord + Clone> MergleNode<T> {
101 fn new(
102 elem: T,
103 elem_hash: HashMatrix,
104 left: Option<Rc<Self>>,
105 right: Option<Rc<Self>>,
106 ) -> Self {
107 MergleNode {
108 elem,
109 elem_hash,
110 height: usize::max(Self::height(&left), Self::height(&right)) + 1,
111 hash: Self::hash(&left) * elem_hash * Self::hash(&right),
112 left,
113 right,
114 }
115 }
116
117 fn create_node_map(self: &Rc<Self>, map: &mut BTreeMap<HashMatrix, Rc<Self>>) {
118 if let alloc::collections::btree_map::Entry::Vacant(e) = map.entry(self.hash) {
119 e.insert(Rc::clone(self));
120 } else {
121 return;
122 }
123
124 if let Some(ln) = &self.left {
125 MergleNode::create_node_map(ln, map)
126 }
127
128 if let Some(rn) = &self.right {
129 MergleNode::create_node_map(rn, map)
130 }
131 }
132
133 fn singleton(e: T, h: HashMatrix) -> Self {
134 Self::new(e, h, None, None)
135 }
136
137 fn replace_left(&self, subtree: Option<Rc<Self>>) -> Self {
138 Self::new(
139 self.elem.clone(),
140 self.elem_hash,
141 subtree,
142 self.right.clone(),
143 )
144 }
145
146 fn replace_right(&self, subtree: Option<Rc<Self>>) -> Self {
147 Self::new(
148 self.elem.clone(),
149 self.elem_hash,
150 self.left.clone(),
151 subtree,
152 )
153 }
154
155 fn height(t: &Option<Rc<Self>>) -> usize {
156 match t {
157 None => 0,
158 Some(p) => p.height,
159 }
160 }
161
162 fn balance(&self) -> isize {
163 (Self::height(&self.left) as isize) - (Self::height(&self.right) as isize)
164 }
165
166 fn hash(t: &Option<Rc<Self>>) -> HashMatrix {
167 match t {
168 None => I,
169 Some(p) => p.hash,
170 }
171 }
172
173 fn rotate_left(&self) -> Self {
174 let right = self.right.as_ref().unwrap();
175 right.replace_left(Some(Rc::new(self.replace_right(right.left.clone()))))
176 }
177
178 fn rotate_right(&self) -> Self {
179 let left = self.left.as_ref().unwrap();
180 left.replace_right(Some(Rc::new(self.replace_left(left.right.clone()))))
181 }
182
183 fn rebalance(self) -> Self {
184 let b = self.balance();
185 let res = if b > 1 {
186 let left = self.left.as_ref().unwrap();
188 if left.balance() < 0 {
189 self.replace_left(Some(Rc::new(left.rotate_left())))
190 .rotate_right()
191 } else {
192 self.rotate_right()
193 }
194 } else if b < -1 {
195 let right = self.right.as_ref().unwrap();
196 if right.balance() > 0 {
198 self.replace_right(Some(Rc::new(right.rotate_right())))
199 .rotate_left()
200 } else {
201 self.rotate_left()
202 }
203 } else {
204 self.clone()
205 };
206 debug_assert!(isize::abs(Self::balance(&res)) < 2);
207 res
208 }
209
210 fn pop_right(&self) -> (T, HashMatrix, Option<Rc<Self>>) {
211 match &self.right {
212 None => (self.elem.clone(), self.elem_hash, self.left.clone()),
213 Some(t) => {
214 let (v, h, r_res) = t.pop_right();
215 let candidate_res = self.replace_right(r_res);
216 (v, h, Some(Rc::new(candidate_res.rebalance())))
217 }
218 }
219 }
220
221 fn push_left(&self, insertion: T, hash: HashMatrix) -> Self {
222 let left = match &self.left {
223 None => Self::singleton(insertion, hash),
224 Some(t) => t.push_left(insertion, hash),
225 };
226 self.replace_left(Some(Rc::new(left))).rebalance()
227 }
228
229 fn join_left_with_insert(left: &Rc<Self>, t: T, h: HashMatrix, right: &Rc<Self>) -> Self {
230 let t_prime = if Self::height(&right.left) > left.height + 1 {
231 Self::join_left_with_insert(left, t, h, right.left.as_ref().unwrap())
232 } else {
233 Self::new(t, h, Some(left.clone()), right.left.clone())
234 };
235 right.replace_left(Some(Rc::new(t_prime))).rebalance()
236 }
237
238 fn join_right_with_insert(left: &Rc<Self>, t: T, h: HashMatrix, right: &Rc<Self>) -> Self {
239 let t_prime = if Self::height(&left.right) > right.height + 1 {
240 Self::join_right_with_insert(left.right.as_ref().unwrap(), t, h, right)
241 } else {
242 Self::new(t, h, left.right.clone(), Some(right.clone()))
243 };
244
245 left.replace_right(Some(Rc::new(t_prime))).rebalance()
246 }
247
248 fn join_with_insert(
249 left: &Rc<Self>,
250 insertion: T,
251 elem_hash: HashMatrix,
252 right: &Rc<Self>,
253 ) -> Self {
254 let balance = (left.height as isize) - (right.height as isize);
255 if balance > 1 {
256 Self::join_right_with_insert(left, insertion, elem_hash, right)
258 } else if balance < -1 {
259 Self::join_left_with_insert(left, insertion, elem_hash, right)
261 } else {
262 Self::new(
263 insertion,
264 elem_hash,
265 Some(left.clone()),
266 Some(right.clone()),
267 )
268 }
269 }
270
271 fn join(left: &Rc<Self>, right: &Rc<Self>) -> Self {
272 match left.pop_right() {
273 (v, h, None) => right.push_left(v, h),
274 (v, h, Some(new_left)) => Self::join_with_insert(&new_left, v, h, right),
275 }
276 }
277
278 fn elem_plus_right(&self) -> Self {
279 match &self.right {
280 None => MergleNode::singleton(self.elem.clone(), self.elem_hash),
281 Some(r) => r.push_left(self.elem.clone(), self.elem_hash),
282 }
283 }
284
285 fn prefix_diff(&self, other: &Self, table: &MemTableRef<T>) -> PrefixDiff<Rc<Self>> {
286 if let Some(res) = table.lookup(self.hash, other.hash) {
287 return res;
288 }
289 if self.hash == other.hash {
290 return PrefixDiff::Equal;
291 }
292
293 let res = match (self.height, other.height) {
294 (1, 1) => PrefixDiff::from_ord(self.elem.cmp(&other.elem)),
295 (a, b) if a >= b => {
296 let left_subtree = self.left.as_ref().unwrap();
297 match left_subtree.prefix_diff(other, table) {
298 PrefixDiff::LessThan => PrefixDiff::LessThan,
299 PrefixDiff::PrefixOf(b_suffix) => {
300 MergleNode::prefix_diff(&self.elem_plus_right(), &b_suffix, table)
301 }
302 PrefixDiff::Equal => PrefixDiff::PrefixedBy(Rc::new(self.elem_plus_right())),
303 PrefixDiff::PrefixedBy(a_suffix) => PrefixDiff::PrefixedBy(Rc::new(
304 MergleNode::join(&a_suffix, &Rc::new(self.elem_plus_right())),
305 )),
306 PrefixDiff::GreaterThan => PrefixDiff::GreaterThan,
307 }
308 }
309 (_, _) => MergleNode::prefix_diff(other, self, table).reverse(),
310 };
311
312 table.insert(self.hash, other.hash, res.clone());
313 res
314 }
315}
316
317impl<T: BrombergHashable> BrombergHashable for MergleNode<T> {
318 fn bromberg_hash(&self) -> HashMatrix {
319 self.hash
320 }
321}
322
323#[derive(Clone)]
324pub struct Mergle<T> {
325 root: Rc<MergleNode<T>>,
326 table: MemTableRef<T>,
327}
328
329impl<T: BrombergHashable + Clone + Ord> Mergle<T> {
330 pub fn singleton(t: T, table: &MemTableRef<T>) -> Mergle<T> {
331 let hash = t.bromberg_hash();
332 Mergle {
333 root: Rc::new(MergleNode::singleton(t, hash)),
334 table: table.clone(),
335 }
336 }
337
338 #[must_use]
339 pub fn merge(&self, other: &Self) -> Self {
340 Mergle {
341 root: Rc::new(MergleNode::join(&self.root, &other.root)),
342 table: self.table.clone(),
343 }
344 }
345
346 pub fn iter(&self) -> impl Iterator<Item = T> + '_ {
347 use alloc::vec;
348 let stack = vec![StackElem::Node(self.root.clone())];
349 Iter { stack }
350 }
351
352 #[must_use]
353 pub fn pop(&self) -> (T, Option<Mergle<T>>) {
354 let (v, _, n) = self.root.pop_right();
355 (
356 v,
357 n.map(|r| Mergle {
358 root: r,
359 table: self.table.clone(),
360 }),
361 )
362 }
363
364 pub fn node_map(&self) -> BTreeMap<HashMatrix, Rc<MergleNode<T>>> {
365 let mut map = BTreeMap::new();
366 MergleNode::create_node_map(&self.root, &mut map);
367 map
368 }
369}
370
371impl<T: BrombergHashable + Clone + Ord> Mergle<T> {
372 #[must_use]
373 pub fn prefix_cmp(&self, other: &Self) -> PrefixDiff<Mergle<T>> {
374 match self.root.prefix_diff(&*other.root, &self.table) {
375 PrefixDiff::LessThan => PrefixDiff::LessThan,
376 PrefixDiff::PrefixOf(node) => PrefixDiff::PrefixOf(Mergle {
377 root: node.clone(),
378 table: self.table.clone(),
379 }),
380 PrefixDiff::Equal => PrefixDiff::Equal,
381 PrefixDiff::PrefixedBy(node) => PrefixDiff::PrefixedBy(Mergle {
382 root: node.clone(),
383 table: self.table.clone(),
384 }),
385 PrefixDiff::GreaterThan => PrefixDiff::GreaterThan,
386 }
387 }
388}
389
390impl<T: BrombergHashable + Clone + Ord> Ord for Mergle<T> {
391 fn cmp(&self, other: &Self) -> Ordering {
392 match self.prefix_cmp(other) {
393 PrefixDiff::LessThan | PrefixDiff::PrefixOf(_) => Ordering::Less,
394 PrefixDiff::Equal => Ordering::Equal,
395 PrefixDiff::PrefixedBy(_) | PrefixDiff::GreaterThan => Ordering::Greater,
396 }
397 }
398}
399
400impl<T: BrombergHashable + Clone + Ord> PartialOrd for Mergle<T> {
401 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
402 Some(self.cmp(other))
403 }
404}
405
406impl<T: BrombergHashable + Clone + Ord> PartialEq for Mergle<T> {
407 fn eq(&self, other: &Self) -> bool {
408 self.cmp(other) == Ordering::Equal
409 }
410}
411
412impl<T: BrombergHashable + Clone + Ord> Eq for Mergle<T> {}
413
414impl<T: BrombergHashable> BrombergHashable for Mergle<T> {
415 fn bromberg_hash(&self) -> HashMatrix {
416 self.root.bromberg_hash()
417 }
418}
419
420pub struct Iter<T> {
421 stack: Vec<StackElem<T>>,
422}
423
424enum StackElem<T> {
425 Elem(T),
427 Node(Rc<MergleNode<T>>),
428}
429
430impl<T: BrombergHashable + Clone + Ord> Iterator for Iter<T> {
431 type Item = T;
432 fn next(&mut self) -> Option<Self::Item> {
433 let mut result = None;
434 while let Some(stack_elem) = self.stack.pop() {
435 match stack_elem {
436 StackElem::Elem(elem) => {
437 result = Some(elem.clone());
439 break;
440 }
441 StackElem::Node(node) => {
442 if let Some(right_tree) = &node.right {
445 self.stack.push(StackElem::Node(right_tree.clone()));
446 };
447
448 if let Some(left_tree) = &node.left {
449 self.stack.push(StackElem::Elem(node.elem.clone()));
450 self.stack.push(StackElem::Node(left_tree.clone()));
451 } else {
452 result = Some(node.elem.clone());
454 break;
455 }
456 }
457 }
458 }
459 result
460 }
461}