1use std::{mem::ManuallyDrop, sync::atomic::Ordering};
2
3use rayon::prelude::*;
4
5use crate::prelude::*;
6
7pub struct Afforest<NI: Idx>(Box<[Atomic<NI>]>);
16
17unsafe impl<NI: Idx> Send for Afforest<NI> {}
18unsafe impl<NI: Idx> Sync for Afforest<NI> {}
19
20impl<NI: Idx> UnionFind<NI> for Afforest<NI> {
21 fn union(&self, u: NI, v: NI) {
23 let mut p1 = self.find(u);
24 let mut p2 = self.find(v);
25
26 while p1 != p2 {
27 let high = NI::max(p1, p2);
28 let low = p1 + p2 - high;
29 let p_high = self.find(high);
30
31 if p_high == low
32 || (p_high == high && self.update_parent(self.find(high), high, low).is_ok())
33 {
34 break;
35 }
36 p1 = self.parent(self.parent(high));
37 p2 = self.parent(low);
38 }
39 }
40
41 fn find(&self, u: NI) -> NI {
42 self.parent(u)
43 }
44
45 fn len(&self) -> usize {
46 self.0.len()
47 }
48
49 fn compress(&self) {
51 (0..self.len()).into_par_iter().map(NI::new).for_each(|n| {
52 while self.parent(n) != self.parent(self.parent(n)) {
53 self.0[n.index()].store(self.parent(self.parent(n)), Ordering::SeqCst)
54 }
55 });
56 }
57}
58
59impl<NI: Idx> Afforest<NI> {
60 pub fn new(size: usize) -> Self {
76 let mut v = Vec::with_capacity(size);
77
78 (0..size)
79 .into_par_iter()
80 .map(|i| Atomic::new(NI::new(i)))
81 .collect_into_vec(&mut v);
82
83 Self(v.into_boxed_slice())
84 }
85
86 fn parent(&self, i: NI) -> NI {
87 self.0[i.index()].load(Ordering::SeqCst)
88 }
89
90 fn update_parent(&self, id: NI, current: NI, new: NI) -> Result<NI, NI> {
91 self.0[id.index()].compare_exchange_weak(current, new, Ordering::SeqCst, Ordering::Relaxed)
92 }
93}
94
95impl<NI: Idx> Components<NI> for Afforest<NI> {
96 fn component(&self, node: NI) -> NI {
97 self.find(node)
98 }
99
100 fn to_vec(self) -> Vec<NI> {
101 let mut components = ManuallyDrop::new(self.0.into_vec());
102 let (ptr, len, cap) = (
103 components.as_mut_ptr(),
104 components.len(),
105 components.capacity(),
106 );
107
108 unsafe {
110 let ptr = ptr as *mut Vec<NI>;
111 let ptr = ptr as *mut _;
112 Vec::from_raw_parts(ptr, len, cap)
113 }
114 }
115}
116
117#[cfg(test)]
118mod test {
119 use crate::prelude::*;
120
121 #[test]
122 fn test_union() {
123 let af = Afforest::new(10);
124
125 af.union(9, 7);
126 af.union(7, 4);
127 af.union(4, 2);
128 af.union(2, 0);
129
130 af.compress();
131
132 assert_eq!(af.find(9), 0);
133 }
134}