1
//! A fibonacci heap is a type of data structure optimized for use as a priority queue.
2
//! It is commonly useful in pathfinding algorithms like Dijkstra's and A*.
3
//! 
4
//! Below is a very in depth comparison and analysis of various types of heaps,
5
//! skip to [`FibHeap`] if you only want to know how to use this library.
6
//! Reading the tests is also a great way to find examples.  Building code as tests will
7
//! help debug fibheap code in particular because additional checks are performed under `cfg(test)`
8
//! that will `abort` if the heap breaks (ie because a duplicate node was added, a node was removed
9
//! that wasn't in the heap, or there is a bug in the library).
10
//! 
11
//! Depending on your needs, [`crate::mmheap::MmHeap`] may be more useful to you, or
12
//! Rust's builtin [`std::collections::BinaryHeap`].  Both of these are binary heaps,
13
//! but the former offers fast access to both the minimum and the maximum.
14
//! 
15
//! # Comparison of Heaps
16
//! ## Asymptotic Time
17
//!|            | Binary | Pairing | Fibonacci | Bucket |
18
//!|------------|--------|---------|-----------|--------|
19
//!|find-min    | O(1)   | O(1)    | O(1)      | O(1)   |
20
//!|extract-min | O(logn)| O(logn) | O(logn)   | O(1)   |
21
//!|insert      | O(logn)| O(1)    | O(1)      | O(1)   |
22
//!|decrease-key| O(logn)| O(logn) | O(1)      | O(1)   |
23
//!|increase-key| O(logn)| O(logn) | O(logn)   | O(1)   |
24
//!|meld        | O(n)   | O(1)    | O(1)      | O(n)   |
25
//! Not all of these operations are directly supported.  In Fibonacci heaps, `increase-key`
26
//! must be implemented by removing and re-inserting an element.  In binary heaps,
27
//! decrease/increase key can be difficult to implement because the elements exist in the heap's
28
//! internal buffer and there isn't a direct way to get a reference/index to them.
29
//! Also in binary heaps, meld is not directly supported and must be implemented by extending
30
//! the internal buffer of one heap by that of another and re-heapifying.
31
//! Bucket queues are extremely good when relevant, but they only support a fixed number of
32
//! priorities, literally having a bucket for each priority, so they are not always suitable.
33
//! 
34
//! ## Linked vs Unlinked Data Structures
35
//! Asymptotic time complexity is not the whole story.  Fibonacci heaps and pairing heaps are linked data
36
//! structures, so links to adjacent nodes are stored as pointers, whereas binary heaps
37
//! have such a simple, rigid structure that they can be stored directly in an array
38
//! (eg the children of a node at index i will be at indices 2i + 1 and 2i + 2).
39
//! Linked data structures can still be stored in an array, but the offsets between nodes
40
//! are not consistent and so generally pointers are used, which can introduce overhead in several
41
//! ways.  Linked data structures often underperform relative to "rigid" data structures
42
//! even though their asymptotic complexity is better.  And even among linked data structures,
43
//! Fibonacci heaps are considered complex and may perform worse than pairing heaps.
44
//! 
45
//! ## Amortized Running Time
46
//! The runtimes of Fibonacci heaps are amortized using potential, which means if the
47
//! number of other calls is much much greater than the number of extract-min calls,
48
//! the extract-min calls may take much longer because they are picking up more work.
49
//! This doesn't happen in most use cases since generally a large part of the heap will be
50
//! drained in algorithms like heapsort, A*, etc.  When it's not the case that a large part
51
//! of the heap will be drained, a minmax heap can often be a good choice since it allows
52
//! dropping entries that will never be used efficiently.  In particular, if the number of
53
//! entries that will be extracted from the heap is constant and small, a minmax heap will
54
//! probably be best.  If the number of entries that will be extracted is proportional to
55
//! the number inserted and/or large, a fibonacci heap may be the best.
56
//! 
57
//! ## Explanation of Algorithms
58
//! There are two operations (extract-min and decrease-key) that are central to Fibonacci heaps,
59
//! and all other operations are trivial.
60
//! A Fibonacci heap consists of a collection of subheaps, each of which is a tree where
61
//! nodes can have any number of children.  This is implemented by giving each node 4 pointers:
62
//! its parent, its first child, its next sibling, and its previous sibling.  For the subheap roots,
63
//! their parent is null and their next/previous siblings are instead other roots.
64
//! Each node also stores its degree (number of chilren) and whether or not it has had a child removed.
65
//! 
66
//! The heap itself stores a pointer to the minimal root, and the number of elements in the heap.
67
//! 
68
//! This structure is restricted by a few invariants.  First, each node is less than or equal to
69
//! all of its children according to the heap comparison function.  Second, the total size of a
70
//! subheap whose root has k children is at least F_(k+2), where F_k is the kth Fibonacci number,
71
//! with F_1 = F_2 = 1, F_3 = 2, F_4 = 3, etc.
72
//! 
73
//! When extract-min is called, first we remove the minimal root.
74
//! Then we iterate over the roots of all other subheaps, plus the children of the removed root,
75
//! placing them into an array with O(logn) elements.
76
//! Each such node goes into the index in the array corresponding to its degree.  If there is already a subheap there,
77
//! we instead remove that subheap, merge it with the current one, and keep going.  When we merge the subheaps,
78
//! the one with the larger root is added as a child of the one with the smaller root, so the degree of the latter goes
79
//! up and then we try to put it in the next corresponding index in the array, repeating until we reach a degree that
80
//! isn't in the array yet.
81
//! 
82
//! At the end, this gives us an array of subheaps with distinct degrees.
83
//! We re-link these into a double circularly linked list, and update the minimal root pointer to point to the minimal one.
84
//! 
85
//! If all subheaps obey the `size >= F_(degree + 2)` invariant before `extract-min`, they will also obey it after.
86
//! 
87
//! If there are two or fewer nodes in the heap before we extract-min, we can optimize by not merging subheaps and just
88
//! setting the new minimal root to either the one remaining node or null.
89
//! 
90
//! When decrease-key is called, if the key is still greater than or equal to the parent's key, or the node is
91
//! a root node and the key is still greater than or equal to the minimal root, or the root node is the minimal root,
92
//! there is nothing to be done.  If the node is a root node but not the minimal root and the key becomes
93
//! less than the minimal heap, update the minimal heap.
94
//! 
95
//! Finally, if the key is now less than the parent's key, remove the node from its sibling list and as a child of its parent.
96
//! Add it as a new subeap.  If the parent was not marked as already having a child removed, mark it as such
97
//! and then remove it as well, repeating for any remaining parents.  However, root nodes need not be marked as such.
98
//! 
99
//! This marking is needed to ensure that the `size >= F_(degree + 2)` invariant does not break
100
//! 
101
//! Insert and meld just require adding a new subheap with one element, and stitching together the subheap root linked lists,
102
//! respectively.
103
//! 
104
//! Find-min just requires inspecting the min_root pointer.
105
//! 
106
//! ## Further Reading
107
//! [Wikipedia](https://en.wikipedia.org/wiki/Fibonacci_heap)
108
//! [3b1b style video by SithDev](https://youtu.be/6JxvKfSV9Ns)
109
//! 
110
//! A very popular priority queue crate.  This crate implements priority queues using a hash table to allow key-indexed node
111
//! access, and builds the priority queue on top of its internal hash table.  It has a good api and is a good choice most of
112
//! the time.  Crater has some advantages over this crate: our fib heap allows building priority queues with any backing
113
//! store, eg KD trees, vectors, just putting each node in `Box`, etc; and references to nodes have generous lifetimes,
114
//! so storing references instead of keys is possible and makes lookup as fast as possible.  However, unless you need these
115
//! features, this crate is a better choice than Crater.
116
//! [priority-queue](https://crates.io/crates/priority-queue)
117

            
118
use std::{cell::UnsafeCell, cmp::Ordering, marker::PhantomData, ptr};
119

            
120
/// The intrusive struct itself that should be embedded in any types that
121
/// implement [`Node`].  See [`FibHeap`] for more information.
122
#[derive(Debug)]
123
pub struct RawNode<'a, T: Node<'a> + ?Sized> {
124
	prev: UnsafeCell<Option<&'a T>>,
125
	next: UnsafeCell<Option<&'a T>>,
126
	first_child: UnsafeCell<Option<&'a T>>,
127
	parent: UnsafeCell<Option<&'a T>>,
128
	has_split: UnsafeCell<bool>,
129
	degree: UnsafeCell<u8>
130
}
131

            
132
/// Any struct can be used as the fib heap element simply by embedding a [`RawNode`]
133
/// in it (or wrapping it in a struct containing a raw node) and implementing this trait.
134
pub trait Node<'a> {
135
	/// Comparison function for nodes, can just wrap Ord impl if present
136
	fn cmp(&'a self, other: &'a Self) -> Ordering;
137
	/// Get a reference to the embedded raw node.  This is used internally to traverse and bookkeep the heap.
138
	/// Accessing this is not thread safe as-is.  Implementors can place the raw node under a lock,
139
	/// but it's better to lock the entire [`FibHeap`] to avoid race conditions.
140
	fn get_raw(&'a self) -> &RawNode<'a, Self>;
141
}
142

            
143
struct SiblingIter<'a, T: Node<'a> + ?Sized> {
144
	start: Option<&'a T>,
145
	iter: &'a T
146
}
147

            
148
impl<'a, T: Node<'a> + ?Sized> Iterator for SiblingIter<'a, T> {
149
	type Item = &'a T;
150
3994968
	fn next(&mut self) -> Option<Self::Item> {
151
3994968
		self.start?;
152
2656436
		let res = self.iter;
153
2656436
		self.iter = (*unsafe { res.get_raw().next.get().as_ref() }.unwrap()).unwrap();
154
2656436
		if ptr::eq(self.iter, self.start.unwrap()) { self.start = None }
155
2656436
		Some(res)
156
3994968
	}
157
}
158

            
159
struct UnlinkingSiblingIter<'a, T: Node<'a> + ?Sized> {
160
	start: Option<&'a T>,
161
	iter: &'a T
162
}
163

            
164
impl<'a, T: Node<'a> + ?Sized> Iterator for UnlinkingSiblingIter<'a, T> {
165
	type Item = &'a T;
166
145658
	fn next(&mut self) -> Option<Self::Item> {
167
145658
		self.start?;
168
119764
		let res = self.iter;
169
119764
		let links = res.get_raw();
170
119764
		self.iter = (*unsafe { links.next.get().as_ref() }.unwrap()).unwrap();
171
119764
		if ptr::eq(self.iter, self.start.unwrap()) { self.start = None }
172
119764
		unsafe {
173
119764
			*links.next.get() = None;
174
119764
			*links.prev.get() = None;
175
119764
			*links.parent.get() = None;
176
119764
		}
177
119764
		Some(res)
178
145658
	}
179
}
180

            
181
#[cfg(test)]
182
enum FibHeapError<'a, T: Node<'a> + ?Sized> {
183
	BrokenPrevLink(&'a T),
184
	LessThanParent(&'a T),
185
	BrokenParentLink(&'a T),
186
	WrongDegree(&'a T),
187
	TooSmall(&'a T),
188
	WrongCount
189
}
190

            
191
#[cfg(test)]
192
impl<'a, T: Node<'a> + ?Sized> PartialEq for FibHeapError<'a, T> {
193
	fn eq(&self, other: &Self) -> bool {
194
		use FibHeapError::*;
195
		match (self, other) {
196
			(BrokenPrevLink(a), BrokenPrevLink(b))
197
			| (LessThanParent(a), LessThanParent(b))
198
			| (BrokenParentLink(a), BrokenParentLink(b))
199
			| (WrongDegree(a), WrongDegree(b))
200
			| (TooSmall(a), TooSmall(b)) => ptr::eq(a, b),
201
			(WrongCount, WrongCount) => true,
202
			_ => false
203
		}
204
	}
205
}
206

            
207
#[cfg(test)]
208
impl<'a, T: Node<'a> + ?Sized> std::fmt::Debug for FibHeapError<'a, T> {
209
	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
210
		use FibHeapError::*;
211
		match self {
212
			BrokenPrevLink(a) => write!(f, "BrokenPrevLink({})", a as *const _ as usize),
213
			LessThanParent(a) => write!(f, "LessThanParent({})", a as *const _ as usize),
214
			BrokenParentLink(a) => write!(f, "BrokenParentLink({})", a as *const _ as usize),
215
			WrongDegree(a) => write!(f, "WrongDegree({})", a as *const _ as usize),
216
			TooSmall(a) => write!(f, "TooSmall({})", a as *const _ as usize),
217
			WrongCount => write!(f, "WrongCount")
218
		}
219
	}
220
}
221

            
222
impl<'a, T: Node<'a> + ?Sized> Default for RawNode<'a, T> {
223
12808
	fn default() -> Self {
224
12808
		Self{prev: None.into(), next: None.into(), first_child: None.into(), parent: None.into(), has_split: false.into(), degree: 0.into()}
225
12808
	}
226
}
227

            
228
#[cfg(test)]
229
1338532
fn iter_siblings<'a, T>(node: &'a T) -> SiblingIter<'a, T>
230
1338532
where T: Node<'a> + ?Sized {
231
1338532
	SiblingIter{start: Some(node), iter: node}
232
1338532
}
233

            
234
25666
fn unlinking_siblings<'a, T>(node: &'a T) -> UnlinkingSiblingIter<'a, T>
235
25666
where T: Node<'a> + ?Sized {
236
25666
	UnlinkingSiblingIter{start: Some(node), iter: node}
237
25666
}
238

            
239
12998
fn unlinking_children<'a, T>(node: &'a T) -> UnlinkingSiblingIter<'a, T>
240
12998
where T: Node<'a> + ?Sized {
241
12998
	let links = node.get_raw();
242
12998
	(*unsafe { links.first_child.get().as_ref() }.unwrap()).inspect(|_| unsafe {
243
12770
		*links.first_child.get() = None;
244
12770
		*links.degree.get() = 0
245
12998
	}).map_or(UnlinkingSiblingIter{start: None, iter: node}, unlinking_siblings)
246
12998
}
247

            
248
12998
unsafe fn remove_root<'a, T>(node: &'a T) -> Option<&'a T>
249
12998
where T: Node<'a> + ?Sized {
250
12998
	let links = node.get_raw();
251
12998
	let next = (*unsafe { links.next.get().as_ref() }.unwrap()).unwrap();
252
12998
	let prev = (*unsafe { links.prev.get().as_ref() }.unwrap()).unwrap();
253
12998
	if ptr::eq(next, prev) {
254
734
		if ptr::eq(next, node) {
255
102
			None
256
		} else {
257
632
			let next_links = next.get_raw();
258
632
			unsafe {
259
632
				*next_links.next.get() = Some(next);
260
632
				*next_links.prev.get() = Some(next);
261
632
				*links.next.get() = Some(node);
262
632
				*links.prev.get() = Some(node);
263
632
			}
264
632
			Some(next)
265
		}
266
	} else {
267
12264
		let next_links = next.get_raw();
268
12264
		let prev_links = prev.get_raw();
269
12264
		unsafe {
270
12264
			*next_links.prev.get() = Some(prev);
271
12264
			*prev_links.next.get() = Some(next);
272
12264
			*links.next.get() = Some(node);
273
12264
			*links.prev.get() = Some(node);
274
12264
		}
275
12264
		Some(next)
276
	}
277
12998
}
278

            
279
70662
unsafe fn merge_same_deg<'a, T>(node: &'a T, other: &'a T) -> &'a T
280
70662
where T: Node<'a> + ?Sized {
281
	// first, find which of node / other has the minimal key, breaking ties with node
282
70662
	let (res_ptr, other_ptr) = if node.cmp(other).is_le() {
283
37434
		(node, other)
284
33228
	} else { (other, node) };
285
70662
	let res_links = res_ptr.get_raw();
286
70662
	let other_links = other_ptr.get_raw();
287
70662
	match *res_links.degree.get() {
288
12770
		0 => unsafe { // the roots both have degree zero, so there are no children to fix up
289
12770
			*other_links.next.get() = Some(other_ptr);
290
12770
			*other_links.prev.get() = Some(other_ptr);
291
12770
			*other_links.parent.get() = Some(res_ptr);
292
12770
			*res_links.first_child.get() = Some(other_ptr);
293
12770
		},
294
12442
		1 => unsafe { // the roots both have degree one, so res has one existing child
295
12442
			let first_child = (*res_links.first_child.get()).unwrap();
296
12442
			*other_links.next.get() = Some(first_child);
297
12442
			*other_links.prev.get() = Some(first_child);
298
12442
			let first_child_links = first_child.get_raw();
299
12442
			*first_child_links.next.get() = Some(other_ptr);
300
12442
			*first_child_links.prev.get() = Some(other_ptr);
301
12442
			*other_links.parent.get() = Some(res_ptr);
302
12442
		},
303
45450
		_ => unsafe { // the roots both have degree greater than one, so res has a distinct existing first and last child
304
45450
			let first_child = (*res_links.first_child.get()).unwrap();
305
45450
			*other_links.next.get() = Some(first_child);
306
45450
			let first_child_links = first_child.get_raw();
307
45450
			let last_child = (*first_child_links.prev.get()).unwrap();
308
45450
			*other_links.prev.get() = Some(last_child);
309
45450
			*last_child.get_raw().next.get() = Some(other_ptr);
310
45450
			*first_child_links.prev.get() = Some(other_ptr);
311
45450
			*other_links.parent.get() = Some(res_ptr);
312
45450
		}
313
	}
314
70662
	*res_links.degree.get() += 1;
315
70662
	res_ptr
316
70662
}
317
#[cfg(test)]
318
2656436
fn check<'a, T>(node: &'a T) -> Result<usize, FibHeapError<'a, T>>
319
2656436
where T: Node<'a> + ?Sized {
320
2656436
	use FibHeapError::*;
321
2656436
	let mut degree = 0;
322
2656436
	let mut first = None;
323
2656436
	let mut prev = None;
324
2656436
	let mut count = 1;
325
2656436
	let (mut fib_d1, mut fib_d2) = (1, 1);
326
2656436
	for child in (*unsafe { node.get_raw().first_child.get().as_ref().unwrap() }).into_iter().flat_map(iter_siblings) {
327
2540292
		degree += 1;
328
2540292
		(fib_d1, fib_d2) = (fib_d2, fib_d1 + fib_d2);
329
2540292
		let child_links = child.get_raw();
330
2540292
		if child.cmp(node) == Ordering::Less {
331
			return Err(LessThanParent(child))
332
2540292
		}
333
2540292
		if prev.is_none() {
334
1312530
			first = Some(child);
335
1312530
		} else if !unsafe { *child_links.prev.get() }.is_some_and(|p|ptr::eq(p, prev.unwrap())) {
336
			Err(BrokenPrevLink(child))?
337
1227762
		} else if !unsafe { *child_links.parent.get() }.is_some_and(|p|ptr::eq(p, node)) {
338
			return Err(BrokenParentLink(child))
339
1227762
		}
340
2540292
		prev = Some(child);
341
2540292
		count += check(child)?;
342
	}
343
2656436
	if let Some(first_node) = first {
344
1312530
		let child_links = first_node.get_raw();
345
1312530
		if !unsafe { *child_links.prev.get() }.is_some_and(|p|ptr::eq(p, prev.unwrap())) {
346
			return Err(BrokenPrevLink(first_node))
347
1312530
		}
348
		// we don't need to check "prev".next because that's the termination condition of `iter_siblings`
349
1343906
	}
350
2656436
	if degree != unsafe { *node.get_raw().degree.get() } {
351
		Err(WrongDegree(node))
352
2656436
	} else if count < fib_d2 {
353
		Err(TooSmall(node))
354
2656436
	} else { Ok(count) }
355
2656436
}
356

            
357
/// A fibonacci heap is a type of data structure optimized for use as a priority queue.
358
/// It is commonly useful in pathfinding algorithms like Dijkstra's and A*.
359
/// Fib heaps have the following amortized time complexities:
360
/// - find-min: O(1)
361
/// - extract-min: O(logn)
362
/// - insert: O(1), compare to O(logn) in a binary heap
363
/// - decrease-key: O(1), compare to O(logn) in a binary heap / pairing heap
364
/// - meld: O(1), compare to O(n) in a binary heap
365
/// Extracting (or deleting) an arbitrary element is also O(logn).
366
/// Increase-key is not directly supported, but can be done by removing and reinserting.
367
/// Fib heaps will generally be a better choice than other heaps when:
368
/// - The number of elements extracted from the heap is proportional to the number inserted and/or large, not fixed and small
369
/// - The keys/priorities of elements need to be decreased frequently
370
/// - The keys/priorities of elements don't need to be increased frequently (also the comparison function doesn't need to be changed)
371
pub struct FibHeap<'a, T: Node<'a> + ?Sized, U> {
372
	min_root: Option<&'a T>,
373
	count: usize,
374
	container: PhantomData<&'a mut U>
375
}
376

            
377
impl<'a, T: Node<'a> + ?Sized + 'a, U> FibHeap<'a, T, U> {
378
	/// Create a new fibonacci heap whose backing storage will live at least as long as `_container`.
379
	/// Typically, if the nodes are stored in a `Vec` or a [`crate::kdtree::KdTree`] or so on,
380
	/// this backing container will have to remain effectively pinned for as long as the fibonacci
381
	/// heap exists, so that references to nodes remain valid.
382
	/// 
383
	/// Conceptually, only the lifespan of `_container` matters: by passing it in here and holding a `PhantomData`
384
	/// reference with the same lifespan, we force the shared reference to the container to outlive the
385
	/// fibonacci heap and prevent any mutable references to it from existing for that time.
386
	/// 
387
	/// Internally, [`RawNode`] uses [`UnsafeCell`] so that nodes can be mutated through shared reference.
388
	/// Otherwise, correctly mutating nodes is excessively complicated (requires using raw pointers throughout,
389
	/// and requires the backing storage to have some way to get a mutable subreference that doesn't overlap with
390
	/// any node so we can assume it is effectively pinned, most of the time this would be a mutable reference to
391
	/// an empty slice).
392
4
	pub fn new(_container: &'a U) -> Self {
393
4
		Self{min_root: None, count: 0, container: PhantomData}
394
4
	}
395
	/// Get the minimal element if it exists, returning a reference to it without removing it.
396
	/// It is safe to decrease the key of the result, but not to increase it
397
	/// if doing so could cause it to no longer be minimal (the key probably lives behind an [`UnsafeCell`])
398
594
	pub fn peek_min(&self) -> Option<&'a T> {
399
594
		self.min_root
400
594
	}
401
	/// Get and remove the minimal element if it exists, returning a reference to it.
402
	/// The key of the result may be freely modified
403
13002
	pub fn pop_min(&mut self) -> Option<&'a T> {
404
13002
		if self.count <= 1 {
405
4
			let res = self.min_root?;
406
4
			self.count = 0;
407
4
			self.min_root = None;
408
4
			#[cfg(test)]{
409
4
				assert!(self.check().is_ok())
410
			}
411
4
			return Some(res)
412
12998
		}
413
12998
		// Calculate the ceiling of the base 2 log of self.count, then multiply by the reciprocal of the base 2 log of the golden ratio
414
12998
		let max_degree = ((((self.count - 1).ilog2() + 1) as f64)*1.4404200904125567).ceil() as usize;
415
12998
		let mut roots = vec![None; max_degree + 1];
416
12998
		let min_root = self.min_root.unwrap();
417
12998
		let other_roots = unsafe { remove_root(min_root) };
418
12998
		// iterate over all roots besides min_root (other_roots.flat_map(RawNode::unlinking_siblings)),
419
12998
		// followed by all children of min_root.
420
12998
		// unlinking_siblings/children are "destructive" and will automatically remove all sibling links.
421
12998
		let iter = other_roots.into_iter().flat_map(unlinking_siblings)
422
12998
			.chain(unlinking_children(min_root));
423
132762
		for mut root_ptr in iter {
424
190426
			loop { // repeatedly try to insert the root into the array of roots, merging it with the root with the same degree until it has unique degree
425
190426
				let degree = unsafe { *root_ptr.get_raw().degree.get() } as usize;
426
190426
				match roots[degree].take() {
427
					None => {
428
119764
						roots[degree] = Some(root_ptr);
429
119764
						break
430
					},
431
70662
					Some(other_ptr) => root_ptr = unsafe { merge_same_deg(root_ptr, other_ptr) }
432
				}
433
			}
434
		}
435
12998
		let mut iter = roots.into_iter().flatten();
436
12998
		let [first_ptr, mut min_ptr, mut last_ptr] = [iter.next().unwrap(); 3];
437
49102
		for root_ptr in iter {
438
36104
			let last_links = last_ptr.get_raw();
439
36104
			let curr_links = root_ptr.get_raw();
440
36104
			unsafe {
441
36104
				*last_links.next.get() = Some(root_ptr);
442
36104
				*curr_links.prev.get() = Some(last_ptr);
443
36104
			}
444
36104
			if root_ptr.cmp(min_ptr).is_le() {
445
25148
				min_ptr = root_ptr;
446
25148
			}
447
36104
			last_ptr = root_ptr;
448
		}
449
12998
		if ptr::eq(first_ptr, last_ptr) {
450
258
			let first_links = first_ptr.get_raw();
451
258
			unsafe {
452
258
				*first_links.prev.get() = Some(first_ptr);
453
258
				*first_links.next.get() = Some(first_ptr);
454
258
			}
455
12740
		} else { unsafe {
456
12740
			*first_ptr.get_raw().prev.get() = Some(last_ptr);
457
12740
			*last_ptr.get_raw().next.get() = Some(first_ptr);
458
12740
		}}
459
12998
		self.count -= 1;
460
12998
		self.min_root = Some(min_ptr);
461
12998
		#[cfg(test)]{
462
12998
			assert_eq!(self.check(), Ok(()));
463
		}
464
12998
		Some(min_root)
465
13002
	}
466
	/// Add a node to the heap.  This is unsafe because the node must not already be in
467
	/// the heap, nor in a different heap.  It is not strictly required for all nodes
468
	/// to have the same backing store as long as the borrow checker confirms they outlive
469
	/// the heap, but most of the time all references will be to elements of the backing store.
470
13004
	pub unsafe fn push(&mut self, ent: &'a T) {
471
13004
		unsafe { self.reattach(ent) }
472
13004
		self.count += 1;
473
13004
		#[cfg(test)]{
474
13004
			assert_eq!(self.check(), Ok(()))
475
		}
476
13004
	}
477
	/// Called immediately AFTER a node's key is decreased, to ensure that the heap invariants
478
	/// are maintained.  This is unsafe because the node must be an element of the heap.
479
	pub unsafe fn decrease_key(&mut self, ent: &'a T) {
480
		if unsafe { *ent.get_raw().parent.get()}.is_some_and(|p|ent.cmp(p) == Ordering::Less) {
481
			self.separate_node(ent)
482
		}
483
	}
484
	/// Remove a node from the heap by reference.  Since the heap is intrusive and does not own its
485
	/// nodes, nothing is returned because the caller already has a reference to the removed node.
486
	/// This is unsafe because the node must be an element of the heap.
487
	pub unsafe fn remove(&mut self, node: &'a T) {
488
		self.separate_node(node);
489
		self.min_root = Some(node);
490
		self.pop_min();
491
	}
492
13004
	unsafe fn reattach(&mut self, node: &'a T) {
493
13004
		match self.count {
494
6
			0 => {
495
6
				self.min_root = Some(node);
496
6
				let links = node.get_raw();
497
6
				*links.next.get() = Some(node);
498
6
				*links.prev.get() = Some(node);
499
6
			},
500
			1 => {
501
8
				let root_links = self.min_root.unwrap().get_raw();
502
8
				*root_links.next.get() = Some(node);
503
8
				*root_links.prev.get() = Some(node);
504
8
				let node_links = node.get_raw();
505
8
				*node_links.next.get() = self.min_root;
506
8
				*node_links.prev.get() = self.min_root;
507
8
				if node.cmp(self.min_root.unwrap()).is_le() {
508
2
					self.min_root = Some(node)
509
6
				}
510
			},
511
			_ => {
512
12990
				let root_links = self.min_root.unwrap().get_raw();
513
12990
				let next_root = (*root_links.next.get()).unwrap();
514
12990
				let next_links = next_root.get_raw();
515
12990
				let node_links = node.get_raw();
516
12990
				*node_links.prev.get() = self.min_root;
517
12990
				*next_links.prev.get() = Some(node);
518
12990
				*node_links.next.get() = Some(next_root);
519
12990
				*root_links.next.get() = Some(node);
520
12990
				if node.cmp(self.min_root.unwrap()).is_le() {
521
118
					self.min_root = Some(node)
522
12872
				}
523
			}
524
		}
525
13004
	}
526
	unsafe fn separate_node(&mut self, mut node: &'a T) {
527
		loop {
528
			let Some(parent) = *node.get_raw().parent.get() else { return };
529
			let next = remove_root(node);
530
			let parent_links = parent.get_raw();
531
			if (*parent_links.first_child.get()).is_some_and(|f|ptr::eq(node, f)) {
532
				*parent_links.first_child.get() = next;
533
			}
534
			*node.get_raw().parent.get() = None;
535
			self.reattach(node);
536
			*parent_links.degree.get() -= 1;
537
			if !*parent_links.has_split.get() {
538
				if (*parent_links.parent.get()).is_none() {
539
					*parent_links.has_split.get() = true;
540
				}
541
				break
542
			}
543
			*parent_links.has_split.get() = false;
544
			node = parent;
545
		}
546
		#[cfg(test)]{
547
			assert!(self.check().is_ok())
548
		}
549
	}
550
	#[cfg(test)]
551
26006
	fn check(&self) -> Result<(), FibHeapError<'a, T>> {
552
26006
		use FibHeapError::*;
553
26006
		if (self.count == 0) != self.min_root.is_none() {
554
			return Err(WrongCount)
555
26006
		} if self.count == 0 {
556
4
			return Ok(())
557
26002
		}
558
26002
		#[cfg(feature = "stress_tests")]{
559
26002
			return Ok(())
560
26002
		}
561
26002
		let root = self.min_root.unwrap();
562
26002
		let mut first = None;
563
26002
		let mut prev: Option<&T> = None;
564
26002
		let mut count = 0;
565
116144
		for child in iter_siblings(root) {
566
116144
			if child.cmp(root) == Ordering::Less {
567
				return Err(LessThanParent(child))
568
116144
			}
569
116144
			let child_links = child.get_raw();
570
116144
			if prev.is_none() {
571
26002
				first = Some(child);
572
90142
			} else if !unsafe { *child_links.prev.get() }.is_some_and(|p|ptr::eq(p, prev.unwrap())) {
573
				Err(BrokenPrevLink(child))?
574
90142
			} else if unsafe { *child_links.parent.get() }.is_some() {
575
				return Err(FibHeapError::BrokenParentLink(child))
576
90142
			}
577
116144
			prev = Some(child);
578
116144
			count += check(child)?;
579
		}
580
26002
		if let Some(child) = first {
581
26002
			let child_links = child.get_raw();
582
26002
			if !unsafe { *child_links.prev.get() }.is_some_and(|p|ptr::eq(p, prev.unwrap())) {
583
				return Err(FibHeapError::BrokenPrevLink(child))
584
26002
			}
585
			// we don't need to check "prev".next because that's the termination condition of `iter_siblings`
586
		}
587
26002
		if count != self.count {
588
			Err(FibHeapError::WrongCount)
589
26002
		} else { Ok(()) }
590
26006
	} 
591
}
592

            
593
#[cfg(test)]
594
mod tests {
595
    use std::{cell::UnsafeCell, cmp::Ordering, fs, ops::Deref};
596

            
597
    use num_traits::Euclid;
598

            
599
    use super::{FibHeap, Node, RawNode};
600

            
601
	struct GenNode<'a> {
602
		multiple: UnsafeCell<u64>,
603
		prime: UnsafeCell<u64>,
604
		_node: RawNode<'a, Self>
605
	}
606

            
607
	impl<'a> Node<'a> for GenNode<'a> {
608
1926
		fn cmp(&'a self, other: &'a Self) -> Ordering {
609
1926
			unsafe { (*self.multiple.get()).cmp(other.multiple.get().as_ref().unwrap()) }
610
1926
		}
611
10042
		fn get_raw(&'a self) -> &RawNode<Self> {
612
10042
			&self._node
613
10042
		}
614
	}
615

            
616
	#[test]
617
2
	fn prime_fheap() {
618
2
		let mut prime_sum = 0;
619
2
		let scapegoat = Box::new(());
620
2
		let mut ref_holder = Vec::new();
621
2
		let mut my_heap = FibHeap::new(&scapegoat);
622
2
		let ub = 100;
623
196
		for n in 2..ub {
624
398
			loop {
625
596
				if !my_heap.peek_min().is_some_and(|g: &GenNode|unsafe { *g.multiple.get() } < n ) {
626
196
					break
627
202
				}
628
202
				let node = my_heap.pop_min().unwrap();
629
202
				unsafe {
630
202
					*node.multiple.get() += *node.prime.get();
631
202
					if *node.multiple.get() < ub {
632
196
						my_heap.push(node)
633
6
					}
634
				}
635
			}
636
293
			if !my_heap.peek_min().is_some_and(|g|unsafe { *g.multiple.get() } == n) {
637
50
				prime_sum += n;
638
50
				if n*n < ub {
639
8
					let node = Box::new(GenNode{multiple: (n*n).into(), prime: n.into(), _node: Default::default()});
640
8
					ref_holder.push(node);
641
8
					unsafe {
642
8
						let last_ref = (ref_holder.last().unwrap().deref() as *const GenNode).as_ref().unwrap();
643
8
						my_heap.push(last_ref)
644
					}
645
42
				}
646
146
			}
647
		}
648
2
		eprintln!("Sum of primes < {} = {}", ub, prime_sum);
649
2
		assert_eq!(prime_sum, 1060);
650
2
	}
651

            
652
	struct GridNode<'a> {
653
		cost: u64,
654
		h: u64,
655
		min_dist: UnsafeCell<u64>,
656
		visited: UnsafeCell<bool>,
657
		_node: RawNode<'a, Self>
658
	}
659

            
660
	impl<'a> Node<'a> for GridNode<'a> {
661
2774274
		fn cmp(&'a self, other: &'a Self) -> Ordering {
662
2774274
			unsafe { *self.min_dist.get() + self.h }.cmp(&unsafe { *other.min_dist.get() + other.h })
663
2774274
			//unsafe { *self.min_dist.get() }.cmp(&unsafe { *other.min_dist.get() })
664
2774274
		}
665
12697184
		fn get_raw(&'a self) -> &RawNode<'a, Self> {
666
12697184
			&&self._node
667
12697184
		}
668
	}
669

            
670
	#[test]
671
2
	fn shortest_path() {
672
2
		let f = fs::read_to_string("resources/0083_matrix.txt").unwrap();
673
2
		let mut cols = None;
674
2
		let mut grid = Vec::new();
675
160
		for l in f.lines() {
676
160
			let a = grid.len();
677
12880
			grid.extend(l.split(',').map(|t|GridNode{cost: t.parse().unwrap(), h: 0, min_dist: 0.into(), visited: false.into(), _node: Default::default()}));
678
160
			let c = grid.len() - a;
679
160
			cols.get_or_insert(c);
680
160
			assert_eq!(cols.unwrap(), c, "All rows must be the same length");
681
		}
682
2
		let cols = cols.unwrap_or_default();
683
2
		let rows = grid.len().checked_div(cols).unwrap_or_default();
684
12801
		let min_cost = grid.iter().map(|n|n.cost).min();
685
12800
		for (i, n) in grid.iter_mut().enumerate() {
686
12800
			let (row, col) = i.div_rem_euclid(&cols);
687
12800
			n.h = min_cost.unwrap()*(rows - row + cols - col - 1) as u64;
688
12800
		}
689
2
		let mut frontier = FibHeap::new(&grid);
690
2
		let node = grid.first().unwrap();
691
2
		unsafe {
692
2
			*node.min_dist.get() = node.cost;
693
2
			frontier.push(node);
694
2
		}
695
12800
		loop {
696
12800
			let node = frontier.pop_min().unwrap();
697
12800
			let i = unsafe { (node as *const GridNode<'_>).offset_from(grid.as_ptr()) } as usize;
698
12800
			if i == grid.len() - 1 {
699
2
				break
700
12798
			}
701
12798
			let (row, col) = i.div_rem_euclid(&cols);
702
12798
			unsafe { *node.visited.get() = true };
703
51192
			for (dr, dc) in [(1, 0), (-1, 0), (0, 1), (0, -1)] {
704
51192
				let r1 = (row as isize + dr).clamp(0, rows as isize - 1) as _;
705
51192
				let c1 = (col as isize + dc).clamp(0, cols as isize - 1) as _;
706
51192
				if (r1, c1) == (row, col) {
707
636
					continue
708
50556
				}
709
50556
				let n1 = &grid[r1*cols + c1];
710
50556
				unsafe {
711
50556
					if *n1.visited.get() {
712
25276
						continue
713
25280
					}
714
25280
					let curr_dist = *n1.min_dist.get();
715
25280
					let new_dist = *node.min_dist.get() + n1.cost;
716
25280
					if curr_dist == 0 {
717
12798
						*n1.min_dist.get() = new_dist;
718
12798
						frontier.push(n1);
719
12798
					} else if curr_dist > new_dist {
720
						*n1.min_dist.get() = new_dist;
721
						frontier.decrease_key(n1);
722
12482
					}
723
				}
724
			}
725
		}
726
2
		let res = unsafe { *grid.last().unwrap().min_dist.get() };
727
2
		eprintln!("Min path sum: {res}");
728
2
		assert_eq!(res, 425185);
729
2
	}
730
}