steel_core/java_block_pos_set/
tree.rs1use std::cmp::Ordering;
2use steel_utils::BlockPos;
3
4use super::{EMPTY, EqualHashOrder, JavaBlockPosSet, UNTREEIFY_THRESHOLD, spread};
5
6pub(super) struct Links {
7 pub(super) parent: u32,
8 pub(super) left: u32,
9 pub(super) right: u32,
10 pub(super) prev: u32,
11 pub(super) red: bool,
12}
13
14impl Links {
15 const EMPTY: Self = Self {
16 parent: EMPTY,
17 left: EMPTY,
18 right: EMPTY,
19 prev: EMPTY,
20 red: false,
21 };
22}
23
24impl JavaBlockPosSet {
25 pub(super) fn tree_root(&self, mut node: u32) -> u32 {
26 while self.links(node).parent != EMPTY {
27 node = self.links(node).parent;
28 }
29 node
30 }
31
32 pub(super) fn links(&self, node: u32) -> &Links {
33 &self.trees[&node]
34 }
35
36 pub(super) fn links_mut(&mut self, node: u32) -> &mut Links {
37 match self.trees.get_mut(&node) {
38 Some(links) => links,
39 None => panic!("tree bin entry has no tree links"),
40 }
41 }
42
43 fn reset_links(&mut self, node: u32) {
44 self.trees.insert(node, Links::EMPTY);
45 }
46
47 pub(super) fn find_in_tree(&self, mut node: u32, hash: i32, pos: BlockPos) -> bool {
48 while node != EMPTY {
49 let entry = &self.entries[node as usize];
50 let links = self.links(node);
51 let node_hash = spread(entry.pos);
52 match hash.cmp(&node_hash) {
53 Ordering::Less => node = links.left,
54 Ordering::Greater => node = links.right,
55 Ordering::Equal => {
56 if entry.pos == pos || self.find_in_tree(links.right, hash, pos) {
57 return true;
58 }
59 node = links.left;
60 }
61 }
62 }
63 false
64 }
65
66 fn goes_left(&self, node: u32, parent: u32) -> bool {
67 let hash = spread(self.entries[node as usize].pos);
68 let parent_hash = spread(self.entries[parent as usize].pos);
69 if hash != parent_hash {
70 return hash < parent_hash;
71 }
72 match self.equal_hash_order {
73 EqualHashOrder::Insertion => node < parent,
74 EqualHashOrder::Coordinates => {
75 let pos = self.entries[node as usize].pos;
76 let parent_pos = self.entries[parent as usize].pos;
77 (pos.y(), pos.z(), pos.x()) < (parent_pos.y(), parent_pos.z(), parent_pos.x())
78 }
79 }
80 }
81
82 fn attach(&mut self, root: u32, node: u32) -> u32 {
83 let mut parent = root;
84 loop {
85 let left = self.goes_left(node, parent);
86 let child = if left {
87 self.links(parent).left
88 } else {
89 self.links(parent).right
90 };
91 if child != EMPTY {
92 parent = child;
93 continue;
94 }
95 self.links_mut(node).parent = parent;
96 if left {
97 self.links_mut(parent).left = node;
98 } else {
99 self.links_mut(parent).right = node;
100 }
101 return parent;
102 }
103 }
104
105 pub(super) fn split_tree(&mut self, index: usize, head: u32, bit: usize) {
106 let mut counts = [0; 2];
107 let mut current = head;
108 while current != EMPTY {
109 let next = self.entries[current as usize].next;
110 let side =
111 usize::from(spread(self.entries[current as usize].pos) as u32 as usize & bit != 0);
112 let target = index + side * bit;
113 let bucket = self.buckets[target];
114 self.links_mut(current).prev = if bucket.head == EMPTY {
115 EMPTY
116 } else {
117 bucket.tail
118 };
119 self.append(target, current);
120 counts[side] += 1;
121 current = next;
122 }
123 for side in 0..2 {
124 if counts[side] <= UNTREEIFY_THRESHOLD {
125 continue;
127 }
128 let target = index + side * bit;
129 self.buckets[target].tail = EMPTY;
130 if counts[1 - side] != 0 {
132 self.treeify(target);
133 }
134 }
135 }
136
137 pub(super) fn treeify(&mut self, bucket: usize) {
138 let mut node = self.buckets[bucket].head;
139 let mut root = EMPTY;
140 let mut prev = EMPTY;
141 while node != EMPTY {
142 self.reset_links(node);
143 self.links_mut(node).prev = prev;
144 if root == EMPTY {
145 root = node;
146 } else {
147 self.attach(root, node);
148 root = self.balance_insertion(root, node);
149 }
150 prev = node;
151 node = self.entries[node as usize].next;
152 }
153 self.buckets[bucket].tail = EMPTY;
154 self.move_root_to_front(bucket, root);
155 }
156
157 pub(super) fn insert_tree(&mut self, bucket: usize, node: u32) {
158 self.reset_links(node);
159 let root = self.tree_root(self.buckets[bucket].head);
160 let parent = self.attach(root, node);
161 let next = self.entries[parent as usize].next;
162 self.entries[parent as usize].next = node;
163 self.entries[node as usize].next = next;
164 self.links_mut(node).prev = parent;
165 if next != EMPTY {
166 self.links_mut(next).prev = node;
167 }
168 let root = self.balance_insertion(root, node);
169 self.move_root_to_front(bucket, root);
170 }
171
172 fn move_root_to_front(&mut self, bucket: usize, root: u32) {
173 debug_assert_eq!(self.links(root).parent, EMPTY);
174 let first = self.buckets[bucket].head;
175 if root == first {
176 return;
177 }
178 let next = self.entries[root as usize].next;
179 let prev = self.links(root).prev;
180 if next != EMPTY {
181 self.links_mut(next).prev = prev;
182 }
183 if prev != EMPTY {
184 self.entries[prev as usize].next = next;
185 }
186 self.links_mut(first).prev = root;
187 self.entries[root as usize].next = first;
188 self.links_mut(root).prev = EMPTY;
189 self.buckets[bucket].head = root;
190 }
191
192 pub(super) fn rotate(&mut self, mut root: u32, node: u32, left: bool) -> u32 {
194 let pivot = if left {
195 self.links(node).right
196 } else {
197 self.links(node).left
198 };
199 let inner = if left {
200 self.links(pivot).left
201 } else {
202 self.links(pivot).right
203 };
204 if left {
205 self.links_mut(node).right = inner;
206 } else {
207 self.links_mut(node).left = inner;
208 }
209 if inner != EMPTY {
210 self.links_mut(inner).parent = node;
211 }
212 let parent = self.links(node).parent;
213 self.links_mut(pivot).parent = parent;
214 if parent == EMPTY {
215 root = pivot;
216 self.links_mut(pivot).red = false;
217 } else if self.links(parent).left == node {
218 self.links_mut(parent).left = pivot;
219 } else {
220 self.links_mut(parent).right = pivot;
221 }
222 if left {
223 self.links_mut(pivot).left = node;
224 } else {
225 self.links_mut(pivot).right = node;
226 }
227 self.links_mut(node).parent = pivot;
228 root
229 }
230
231 fn balance_insertion(&mut self, mut root: u32, mut node: u32) -> u32 {
232 self.links_mut(node).red = true;
233 loop {
234 let mut parent = self.links(node).parent;
235 if parent == EMPTY {
236 self.links_mut(node).red = false;
237 return node;
238 }
239 let mut grandparent = self.links(parent).parent;
240 if !self.links(parent).red || grandparent == EMPTY {
241 return root;
242 }
243 let left = parent == self.links(grandparent).left;
244 let uncle = if left {
245 self.links(grandparent).right
246 } else {
247 self.links(grandparent).left
248 };
249 if uncle != EMPTY && self.links(uncle).red {
250 self.links_mut(uncle).red = false;
251 self.links_mut(parent).red = false;
252 self.links_mut(grandparent).red = true;
253 node = grandparent;
254 continue;
255 }
256 let inner = if left {
257 self.links(parent).right
258 } else {
259 self.links(parent).left
260 };
261 if node == inner {
262 node = parent;
263 root = self.rotate(root, node, left);
264 parent = self.links(node).parent;
265 grandparent = self.links(parent).parent;
266 }
267 self.links_mut(parent).red = false;
268 if grandparent != EMPTY {
269 self.links_mut(grandparent).red = true;
270 root = self.rotate(root, grandparent, !left);
271 }
272 }
273 }
274}