partitions/lib.rs
1//! A [disjoint-sets/union-find] implementation of a vector partitioned in sets that allows
2//! for efficient iteration over elements of a set.
3//!
4//! The main struct of this crate is [`PartitionVec<T>`] which has the functionality of a `Vec<T>`
5//! and in addition divides the elements of this vector in sets.
6//! The elements each start in their own set and sets can be joined with the [`union`] method.
7//! You can check if elements share a set with the [`same_set`] method and iterate on the elements
8//! in a set with the [`set`] method.
9//! The [`union`] and [`same_set`] methods are extremely fast and have an amortized complexity of
10//! `O(α(n))` where `α`` is the inverse Ackermann function and `n` is the length.
11//! This complexity is proven to be optimal and `α(n)` has value below 5 for any `n`
12//! that can be written in the observable universe.
13//! The next element of the iterator returned by [`set`] is found in `O(1)` time.
14//!
15//! The Disjoint-Sets algorithm is used in high-performance implementations of unification.
16//! It is also a key component in implementing Kruskal's algorithm to find the minimum spanning
17//! tree of a graph.
18//!
19//! This implementation stores three integers as `usize` values for every element in the
20//! [`PartitionVec<T>`], two values are needed to get the best complexity of the Disjoint-Sets
21//! algorithm and the third is used to allow iteration over sets and other methods like the
22//! [`make_singleton`] method that removes the element of its current set and gives it its own set.
23//!
24//! A more compact implementation is included that has the same functionality but only needs to
25//! store an additional two `usize` values instead of three for every element.
26//! This is done by using a few bits of these two integers to store the third.
27//! Because this third value is always very small we only need three bits on a 32 or 64 bit system.
28//! This does mean that the maximum amounts of elements stored on 32 and 64 bit systems are
29//! 536 870 912 and 2 305 843 009 213 693 952 respectively.
30//! This limit should never be reached under any normal circumstances but if you do the struct
31//! will panic.
32//! This representation can be enabled by adding the following to your `Cargo.toml` file:
33//! ```toml
34//! [dependencies.partitions]
35//! version = "0.2"
36//! features = ["compact"]
37//! ```
38//!
39//! [disjoint-sets/union-find]: https://en.wikipedia.org/wiki/Disjoint-set_data_structure
40//! [`PartitionVec<T>`]: partition_vec/struct.PartitionVec.html
41//! [`union`]: partition_vec/struct.PartitionVec.html#method.union
42//! [`same_set`]: partition_vec/struct.PartitionVec.html#method.same_set
43//! [`set`]: partition_vec/struct.PartitionVec.html#method.set
44//! [`make_singleton`]: partition_vec/struct.PartitionVec.html#method.make_singleton
45
46extern crate bit_vec;
47#[cfg(feature = "rayon")]
48extern crate rayon;
49
50/// We count the amount of expresions given to this macro.
51#[doc(hidden)]
52#[macro_export]
53macro_rules! partitions_count_expr {
54 () => { 0usize };
55 ($_single: expr) => { 1usize };
56 // Even amount of expresions.
57 ($($first: expr, $_second: expr),*) => {
58 (partitions_count_expr![$($first),*] << 1usize)
59 };
60 // Odd amount of expresions.
61 ($_single: expr, $($first: expr, $_second: expr),*) => {
62 (partitions_count_expr![$($first),*] << 1usize) | 1
63 };
64}
65
66/// A convenient macro to create a `BitVec` similar to `vec!`.
67macro_rules! bit_vec {
68 ($element: expr; $len: expr) => {
69 bit_vec::BitVec::from_elem($len, $element);
70 };
71 ($($value: expr),*) => {
72 {
73 let len = partitions_count_expr![$($value),*];
74 let mut bit_vec = bit_vec::BitVec::with_capacity(len);
75
76 $(
77 bit_vec.push($value);
78 )*
79
80 bit_vec
81 }
82 };
83 ($($value: expr,)*) => {
84 bit_vec![$($value),*];
85 };
86}
87
88mod metadata;
89pub mod partition_vec;
90
91pub use partition_vec::PartitionVec;
92
93/// This takes an mutable reference and return a mutable reference with a different lifetime.
94///
95/// This function is highly unsafe and every use of this function will have a
96/// comment explaining why it is necessary.
97/// The main motivation for making a function for this is that the code is not
98/// intuitive and this makes the intend clearer.
99unsafe fn extend_mut<'a, 'b, T>(ptr: &'a mut T) -> &'b mut T {
100 &mut *(ptr as *mut T)
101}