use core::cmp::Ordering;
const LEAF_MAX: usize = 256;
const LEAF_MIN: usize = LEAF_MAX / 2;
const BRANCH_MAX: usize = 128;
const BRANCH_MIN: usize = BRANCH_MAX / 2;
const NIL: u32 = u32::MAX;
#[derive(Debug, Clone, Default)]
struct Rows {
at: Vec<u8>,
}
impl Rows {
fn with_room() -> Self {
Self {
at: Vec::with_capacity(LEAF_MAX * 3),
}
}
fn len(&self) -> usize {
self.at.len() / 3
}
fn get(&self, i: usize) -> u32 {
let at = i * 3;
u32::from(self.at[at]) | u32::from(self.at[at + 1]) << 8 | u32::from(self.at[at + 2]) << 16
}
fn set(&mut self, i: usize, row: u32) {
let at = i * 3;
self.at[at..at + 3].copy_from_slice(&row.to_le_bytes()[..3]);
}
fn push(&mut self, row: u32) {
self.at.extend_from_slice(&row.to_le_bytes()[..3]);
}
fn insert(&mut self, i: usize, row: u32) {
let at = i * 3;
self.at.extend_from_slice(&[0, 0, 0]);
let end = self.at.len();
self.at.copy_within(at..end - 3, at + 3);
self.at[at..at + 3].copy_from_slice(&row.to_le_bytes()[..3]);
}
fn remove(&mut self, i: usize) -> u32 {
let row = self.get(i);
let at = i * 3;
self.at.copy_within(at + 3.., at);
self.at.truncate(self.at.len() - 3);
row
}
fn split_off(&mut self, i: usize) -> Self {
let mut out = Self::with_room();
out.at.extend_from_slice(&self.at[i * 3..]);
self.at.truncate(i * 3);
out
}
fn append(&mut self, other: &Self) {
self.at.extend_from_slice(&other.at);
}
fn partition_point<F: FnMut(u32) -> bool>(&self, mut keep: F) -> usize {
let (mut lo, mut hi) = (0, self.len());
while lo < hi {
let mid = (lo + hi) / 2;
if keep(self.get(mid)) {
lo = mid + 1;
} else {
hi = mid;
}
}
lo
}
fn bytes(&self) -> usize {
self.at.capacity()
}
}
#[derive(Debug, Clone)]
struct Leaf {
rows: Rows,
prev: u32,
next: u32,
}
#[derive(Debug, Clone)]
struct Branch {
kids: Vec<u32>,
counts: Vec<u32>,
firsts: Vec<u32>,
}
struct Split {
node: u32,
count: u32,
first: u32,
}
#[derive(Debug, Clone)]
pub struct Rank {
leaves: Vec<Leaf>,
branches: Vec<Branch>,
free_leaves: Vec<u32>,
free_branches: Vec<u32>,
root: u32,
depth: u8,
len: usize,
head: u32,
tail: u32,
}
impl Default for Rank {
fn default() -> Self {
Self::new()
}
}
impl Rank {
#[must_use]
pub fn new() -> Self {
Self {
leaves: vec![Leaf {
rows: Rows::with_room(),
prev: NIL,
next: NIL,
}],
branches: Vec::new(),
free_leaves: Vec::new(),
free_branches: Vec::new(),
root: 0,
depth: 0,
len: 0,
head: 0,
tail: 0,
}
}
#[must_use]
pub const fn len(&self) -> usize {
self.len
}
#[must_use]
pub const fn is_empty(&self) -> bool {
self.len == 0
}
#[must_use]
pub fn bytes(&self) -> usize {
let leaves: usize = self
.leaves
.iter()
.map(|l| l.rows.bytes() + size_of::<Leaf>())
.sum();
let branches: usize = self
.branches
.iter()
.map(|b| {
(b.kids.capacity() + b.counts.capacity() + b.firsts.capacity()) * size_of::<u32>()
+ size_of::<Branch>()
})
.sum();
leaves + branches
}
#[must_use]
pub fn row_at(&self, rank: usize) -> Option<u32> {
if rank >= self.len {
return None;
}
let (leaf, at) = self.find(rank);
Some(self.leaves[leaf as usize].rows.get(at))
}
fn find(&self, rank: usize) -> (u32, usize) {
let mut node = self.root;
let mut at = rank;
for _ in 0..self.depth {
let b = &self.branches[node as usize];
let mut i = 0;
while at >= b.counts[i] as usize && i + 1 < b.kids.len() {
at -= b.counts[i] as usize;
i += 1;
}
node = b.kids[i];
}
(node, at)
}
pub fn seek<F: FnMut(u32) -> Ordering>(&self, mut probe: F) -> usize {
let mut node = self.root;
let mut base = 0;
for _ in 0..self.depth {
let b = &self.branches[node as usize];
let mut i = 0;
while i + 1 < b.kids.len() && probe(b.firsts[i + 1]) == Ordering::Greater {
base += b.counts[i] as usize;
i += 1;
}
node = b.kids[i];
}
let rows = &self.leaves[node as usize].rows;
base + rows.partition_point(|r| probe(r) == Ordering::Greater)
}
pub fn insert_at(&mut self, rank: usize, row: u32) {
assert!(
rank <= self.len,
"rank {rank} is past the end of {}",
self.len
);
let split = if self.depth == 0 {
self.leaf_insert(self.root, rank, row)
} else {
self.branch_insert(self.root, self.depth, rank, row)
};
if let Some(split) = split {
let left = self.root;
let left_count = (self.len + 1 - split.count as usize) as u32;
let left_first = self.first_of(left, self.depth);
let root = self.take_branch();
let b = &mut self.branches[root as usize];
b.kids.push(left);
b.counts.push(left_count);
b.firsts.push(left_first);
b.kids.push(split.node);
b.counts.push(split.count);
b.firsts.push(split.first);
self.root = root;
self.depth += 1;
}
self.len += 1;
}
pub fn remove_at(&mut self, rank: usize) -> u32 {
assert!(
rank < self.len,
"rank {rank} is past the end of {}",
self.len
);
let row = if self.depth == 0 {
let leaf = &mut self.leaves[self.root as usize];
leaf.rows.remove(rank)
} else {
self.branch_remove(self.root, self.depth, rank)
};
while self.depth > 0 && self.branches[self.root as usize].kids.len() == 1 {
let old = self.root;
self.root = self.branches[old as usize].kids[0];
self.drop_branch(old);
self.depth -= 1;
}
self.len -= 1;
row
}
pub fn set_at(&mut self, rank: usize, row: u32) {
assert!(
rank < self.len,
"rank {rank} is past the end of {}",
self.len
);
let mut node = self.root;
let mut at = rank;
for _ in 0..self.depth {
let b = &mut self.branches[node as usize];
let mut i = 0;
while at >= b.counts[i] as usize && i + 1 < b.kids.len() {
at -= b.counts[i] as usize;
i += 1;
}
if at == 0 {
b.firsts[i] = row;
}
node = b.kids[i];
}
self.leaves[node as usize].rows.set(at, row);
}
#[must_use]
pub fn iter_from(&self, rank: usize) -> Walk<'_> {
if rank >= self.len {
return Walk {
tree: self,
leaf: NIL,
at: 0,
left: 0,
};
}
let (leaf, at) = self.find(rank);
Walk {
tree: self,
leaf,
at,
left: self.len - rank,
}
}
#[must_use]
pub fn iter_back_from(&self, rank: usize) -> Back<'_> {
if rank >= self.len {
return Back {
tree: self,
leaf: NIL,
at: 0,
left: 0,
};
}
let (leaf, at) = self.find(rank);
Back {
tree: self,
leaf,
at,
left: rank + 1,
}
}
fn leaf_insert(&mut self, id: u32, at: usize, row: u32) -> Option<Split> {
let leaf = &mut self.leaves[id as usize];
if leaf.rows.len() < LEAF_MAX {
leaf.rows.insert(at, row);
return None;
}
if at == LEAF_MAX {
let new = self.take_leaf();
self.leaves[new as usize].rows.push(row);
self.link_after(id, new);
return Some(Split {
node: new,
count: 1,
first: row,
});
}
if at == 0 {
let new = self.take_leaf();
let full = core::mem::replace(&mut self.leaves[id as usize].rows, Rows::with_room());
let count = full.len() as u32;
let first = full.get(0);
self.leaves[new as usize].rows = full;
self.leaves[id as usize].rows.push(row);
self.link_after(id, new);
return Some(Split {
node: new,
count,
first,
});
}
let new = self.take_leaf();
let tail = self.leaves[id as usize].rows.split_off(LEAF_MAX / 2);
self.leaves[new as usize].rows = tail;
self.link_after(id, new);
if at <= LEAF_MAX / 2 {
self.leaves[id as usize].rows.insert(at, row);
} else {
self.leaves[new as usize]
.rows
.insert(at - LEAF_MAX / 2, row);
}
let first = self.leaves[new as usize].rows.get(0);
let count = self.leaves[new as usize].rows.len() as u32;
Some(Split {
node: new,
count,
first,
})
}
fn branch_insert(&mut self, id: u32, level: u8, at: usize, row: u32) -> Option<Split> {
let (mut i, mut local) = (0, at);
{
let b = &self.branches[id as usize];
while local > b.counts[i] as usize && i + 1 < b.kids.len() {
local -= b.counts[i] as usize;
i += 1;
}
}
let kid = self.branches[id as usize].kids[i];
let split = if level == 1 {
self.leaf_insert(kid, local, row)
} else {
self.branch_insert(kid, level - 1, local, row)
};
{
let b = &mut self.branches[id as usize];
b.counts[i] += 1;
if local == 0 {
b.firsts[i] = row;
}
}
let split = split?;
let kept = self.branches[id as usize].kids[i];
let kept_count = self.branches[id as usize].counts[i] - split.count;
{
let b = &mut self.branches[id as usize];
b.counts[i] = kept_count;
}
let kept_first = self.first_of(kept, level - 1);
{
let b = &mut self.branches[id as usize];
b.firsts[i] = kept_first;
b.kids.insert(i + 1, split.node);
b.counts.insert(i + 1, split.count);
b.firsts.insert(i + 1, split.first);
if b.kids.len() <= BRANCH_MAX {
return None;
}
}
let new = self.take_branch();
let (kids, counts, firsts) = {
let b = &mut self.branches[id as usize];
(
b.kids.split_off(BRANCH_MAX / 2),
b.counts.split_off(BRANCH_MAX / 2),
b.firsts.split_off(BRANCH_MAX / 2),
)
};
let count: u32 = counts.iter().sum();
let first = firsts[0];
let b = &mut self.branches[new as usize];
b.kids = kids;
b.counts = counts;
b.firsts = firsts;
Some(Split {
node: new,
count,
first,
})
}
fn branch_remove(&mut self, id: u32, level: u8, at: usize) -> u32 {
let (mut i, mut local) = (0, at);
{
let b = &self.branches[id as usize];
while local >= b.counts[i] as usize && i + 1 < b.kids.len() {
local -= b.counts[i] as usize;
i += 1;
}
}
let kid = self.branches[id as usize].kids[i];
let row = if level == 1 {
self.leaves[kid as usize].rows.remove(local)
} else {
self.branch_remove(kid, level - 1, local)
};
self.branches[id as usize].counts[i] -= 1;
if local == 0 && self.branches[id as usize].counts[i] > 0 {
let first = self.first_of(kid, level - 1);
self.branches[id as usize].firsts[i] = first;
}
self.mend(id, level, i);
row
}
fn mend(&mut self, id: u32, level: u8, i: usize) {
let (small, kids) = {
let b = &self.branches[id as usize];
let kid = b.kids[i];
let small = if level == 1 {
self.leaves[kid as usize].rows.len() < LEAF_MIN
} else {
self.branches[kid as usize].kids.len() < BRANCH_MIN
};
(small, b.kids.len())
};
if !small || kids == 1 {
return;
}
let at = if i + 1 == kids { i - 1 } else { i };
let (left, right) = {
let b = &self.branches[id as usize];
(b.kids[at], b.kids[at + 1])
};
let room = if level == 1 {
self.leaves[left as usize].rows.len() + self.leaves[right as usize].rows.len()
<= LEAF_MAX
} else {
self.branches[left as usize].kids.len() + self.branches[right as usize].kids.len()
<= BRANCH_MAX
};
if room {
self.join(id, level, at);
} else {
self.share(id, level, at);
}
}
fn join(&mut self, id: u32, level: u8, at: usize) {
let (left, right) = {
let b = &self.branches[id as usize];
(b.kids[at], b.kids[at + 1])
};
if level == 1 {
let rows = core::mem::take(&mut self.leaves[right as usize].rows);
self.leaves[left as usize].rows.append(&rows);
self.unlink(right);
self.drop_leaf(right);
} else {
let (kids, counts, firsts) = {
let b = &mut self.branches[right as usize];
(
core::mem::take(&mut b.kids),
core::mem::take(&mut b.counts),
core::mem::take(&mut b.firsts),
)
};
let b = &mut self.branches[left as usize];
b.kids.extend_from_slice(&kids);
b.counts.extend_from_slice(&counts);
b.firsts.extend_from_slice(&firsts);
self.drop_branch(right);
}
{
let b = &mut self.branches[id as usize];
b.counts[at] += b.counts[at + 1];
b.kids.remove(at + 1);
b.counts.remove(at + 1);
b.firsts.remove(at + 1);
}
let first = self.first_of(left, level - 1);
self.branches[id as usize].firsts[at] = first;
}
fn share(&mut self, id: u32, level: u8, at: usize) {
let (left, right) = {
let b = &self.branches[id as usize];
(b.kids[at], b.kids[at + 1])
};
let moved = if level == 1 {
let row = self.leaves[right as usize].rows.remove(0);
self.leaves[left as usize].rows.push(row);
1
} else {
let b = &mut self.branches[right as usize];
let kid = b.kids.remove(0);
let count = b.counts.remove(0);
let first = b.firsts.remove(0);
let b = &mut self.branches[left as usize];
b.kids.push(kid);
b.counts.push(count);
b.firsts.push(first);
count
};
let first = self.first_of(right, level - 1);
let b = &mut self.branches[id as usize];
b.counts[at] += moved;
b.counts[at + 1] -= moved;
b.firsts[at + 1] = first;
}
fn first_of(&self, id: u32, level: u8) -> u32 {
if level == 0 {
return self.leaves[id as usize].rows.get(0);
}
self.branches[id as usize].firsts[0]
}
fn take_leaf(&mut self) -> u32 {
if let Some(id) = self.free_leaves.pop() {
return id;
}
self.leaves.push(Leaf {
rows: Rows::with_room(),
prev: NIL,
next: NIL,
});
(self.leaves.len() - 1) as u32
}
fn drop_leaf(&mut self, id: u32) {
let leaf = &mut self.leaves[id as usize];
leaf.rows = Rows::default();
leaf.prev = NIL;
leaf.next = NIL;
self.free_leaves.push(id);
}
fn take_branch(&mut self) -> u32 {
if let Some(id) = self.free_branches.pop() {
return id;
}
self.branches.push(Branch {
kids: Vec::new(),
counts: Vec::new(),
firsts: Vec::new(),
});
(self.branches.len() - 1) as u32
}
fn drop_branch(&mut self, id: u32) {
let b = &mut self.branches[id as usize];
b.kids = Vec::new();
b.counts = Vec::new();
b.firsts = Vec::new();
self.free_branches.push(id);
}
fn link_after(&mut self, id: u32, new: u32) {
let next = self.leaves[id as usize].next;
self.leaves[new as usize].prev = id;
self.leaves[new as usize].next = next;
self.leaves[id as usize].next = new;
if next == NIL {
self.tail = new;
} else {
self.leaves[next as usize].prev = new;
}
}
fn unlink(&mut self, id: u32) {
let (prev, next) = {
let l = &self.leaves[id as usize];
(l.prev, l.next)
};
if prev == NIL {
self.head = next;
} else {
self.leaves[prev as usize].next = next;
}
if next == NIL {
self.tail = prev;
} else {
self.leaves[next as usize].prev = prev;
}
}
}
#[derive(Debug)]
pub struct Walk<'a> {
tree: &'a Rank,
leaf: u32,
at: usize,
left: usize,
}
impl Iterator for Walk<'_> {
type Item = u32;
fn next(&mut self) -> Option<u32> {
if self.left == 0 || self.leaf == NIL {
return None;
}
let leaf = &self.tree.leaves[self.leaf as usize];
let row = leaf.rows.get(self.at);
self.at += 1;
self.left -= 1;
if self.at == leaf.rows.len() {
self.leaf = leaf.next;
self.at = 0;
}
Some(row)
}
fn size_hint(&self) -> (usize, Option<usize>) {
(self.left, Some(self.left))
}
}
impl ExactSizeIterator for Walk<'_> {}
#[derive(Debug)]
pub struct Back<'a> {
tree: &'a Rank,
leaf: u32,
at: usize,
left: usize,
}
impl Iterator for Back<'_> {
type Item = u32;
fn next(&mut self) -> Option<u32> {
if self.left == 0 || self.leaf == NIL {
return None;
}
let leaf = &self.tree.leaves[self.leaf as usize];
let row = leaf.rows.get(self.at);
self.left -= 1;
if self.at == 0 {
self.leaf = leaf.prev;
if self.leaf != NIL {
self.at = self.tree.leaves[self.leaf as usize].rows.len() - 1;
}
} else {
self.at -= 1;
}
Some(row)
}
fn size_hint(&self) -> (usize, Option<usize>) {
(self.left, Some(self.left))
}
}
impl ExactSizeIterator for Back<'_> {}
#[cfg(test)]
mod tests {
use super::*;
fn rows(tree: &Rank) -> Vec<u32> {
tree.iter_from(0).collect()
}
fn sound(tree: &Rank) {
let total = check(tree, tree.root, tree.depth);
assert_eq!(
total, tree.len,
"the root's counts do not add up to the length"
);
let mut walked = 0;
let mut at = tree.head;
let mut prev = NIL;
while at != NIL {
assert_eq!(tree.leaves[at as usize].prev, prev, "a back link is wrong");
walked += tree.leaves[at as usize].rows.len();
prev = at;
at = tree.leaves[at as usize].next;
}
assert_eq!(prev, tree.tail, "the tail is not the end of the chain");
assert_eq!(walked, tree.len, "the leaf chain does not hold every row");
}
fn check(tree: &Rank, id: u32, level: u8) -> usize {
if level == 0 {
return tree.leaves[id as usize].rows.len();
}
let b = &tree.branches[id as usize];
assert!(!b.kids.is_empty(), "a branch with no kids");
let mut total = 0;
for (i, &kid) in b.kids.iter().enumerate() {
let under = check(tree, kid, level - 1);
assert_eq!(
under, b.counts[i] as usize,
"a count does not match what is under it"
);
assert_eq!(
b.firsts[i],
tree.first_of(kid, level - 1),
"a first row is stale"
);
total += under;
}
total
}
#[test]
fn an_empty_tree_answers_nothing() {
let tree = Rank::new();
assert_eq!(tree.len(), 0);
assert!(tree.is_empty());
assert_eq!(tree.row_at(0), None);
assert_eq!(tree.seek(|_| Ordering::Greater), 0);
assert_eq!(rows(&tree), Vec::<u32>::new());
}
#[test]
fn a_sorted_run_of_appends_fills_its_leaves() {
let mut tree = Rank::new();
let n = 10_000;
for i in 0..n {
tree.insert_at(i as usize, i);
}
sound(&tree);
assert_eq!(rows(&tree), (0..n).collect::<Vec<_>>());
let per = tree.bytes() as f64 / n as f64;
assert!(per < 5.0, "{per} bytes a row on a sorted run");
}
#[test]
fn a_sorted_run_of_prepends_fills_its_leaves_too() {
let mut tree = Rank::new();
let n = 10_000;
for i in 0..n {
tree.insert_at(0, i);
}
sound(&tree);
assert_eq!(rows(&tree), (0..n).rev().collect::<Vec<_>>());
let per = tree.bytes() as f64 / n as f64;
assert!(per < 5.0, "{per} bytes a row on a reversed run");
}
#[test]
fn a_row_can_go_in_anywhere_and_come_out_where_it_went() {
let mut tree = Rank::new();
let mut model: Vec<u32> = Vec::new();
let mut seed = 0x9E37_79B9_7F4A_7C15u64;
let roll = |seed: &mut u64, n: usize| {
*seed ^= *seed << 13;
*seed ^= *seed >> 7;
*seed ^= *seed << 17;
(*seed % (n as u64 + 1)) as usize
};
for i in 0..4_000u32 {
let at = roll(&mut seed, model.len());
tree.insert_at(at, i);
model.insert(at, i);
}
sound(&tree);
assert_eq!(rows(&tree), model);
for rank in [0, 1, 999, 3_999] {
assert_eq!(tree.row_at(rank), Some(model[rank]));
}
assert_eq!(tree.row_at(4_000), None);
}
#[test]
fn taking_rows_out_puts_the_tree_back_together() {
let mut tree = Rank::new();
for i in 0..5_000u32 {
tree.insert_at(i as usize, i);
}
let mut model: Vec<u32> = (0..5_000).collect();
let mut seed = 0x2545_F491_4F6C_DD1Du64;
while !model.is_empty() {
seed ^= seed << 13;
seed ^= seed >> 7;
seed ^= seed << 17;
let at = (seed % model.len() as u64) as usize;
assert_eq!(tree.remove_at(at), model.remove(at));
if model.len().is_multiple_of(97) {
sound(&tree);
assert_eq!(rows(&tree), model);
}
}
sound(&tree);
assert_eq!(tree.len(), 0);
assert_eq!(tree.depth, 0, "an emptied tree should be one leaf again");
}
#[test]
fn a_tree_that_has_been_emptied_reuses_what_it_had() {
let mut tree = Rank::new();
for i in 0..2_000u32 {
tree.insert_at(i as usize, i);
}
let leaves = tree.leaves.len();
let branches = tree.branches.len();
for _ in 0..2_000 {
tree.remove_at(0);
}
for i in 0..2_000u32 {
tree.insert_at(i as usize, i);
}
sound(&tree);
assert_eq!(tree.leaves.len(), leaves, "leaves were not reused");
assert_eq!(tree.branches.len(), branches, "branches were not reused");
}
#[test]
fn a_search_finds_where_a_value_belongs() {
let mut tree = Rank::new();
let value = |row: u32| i64::from(row) * 10;
for i in 0..3_000u32 {
tree.insert_at(i as usize, i);
}
for want in [0i64, 5, 10, 15, 29_990, 29_995, 30_000, 40_000] {
let lower = tree.seek(|row| want.cmp(&value(row)));
let expect = (0..3_000).filter(|&r| value(r) < want).count();
assert_eq!(lower, expect, "lower bound of {want}");
}
let upper = tree.seek(|row| match 100i64.cmp(&value(row)) {
Ordering::Equal => Ordering::Greater,
other => other,
});
assert_eq!(upper, 11);
}
#[test]
fn a_search_over_a_run_of_equal_values_finds_both_of_its_ends() {
let mut tree = Rank::new();
for i in 0..1_000u32 {
tree.insert_at(i as usize, i);
}
let value = |_row: u32| 7i64;
let first = tree.seek(|row| 7i64.cmp(&value(row)));
let past = tree.seek(|row| match 7i64.cmp(&value(row)) {
Ordering::Equal => Ordering::Greater,
other => other,
});
assert_eq!(first, 0);
assert_eq!(past, 1_000);
}
#[test]
fn a_walk_can_start_anywhere_and_go_either_way() {
let mut tree = Rank::new();
for i in 0..1_000u32 {
tree.insert_at(i as usize, i);
}
assert_eq!(tree.iter_from(998).collect::<Vec<_>>(), vec![998, 999]);
assert_eq!(tree.iter_from(1_000).count(), 0);
assert_eq!(tree.iter_back_from(2).collect::<Vec<_>>(), vec![2, 1, 0]);
assert_eq!(tree.iter_back_from(999).count(), 1_000);
assert_eq!(tree.iter_back_from(1_000).count(), 0);
let mut walk = tree.iter_from(500);
assert_eq!(walk.len(), 500);
assert_eq!(walk.next(), Some(500));
assert_eq!(walk.len(), 499);
}
#[test]
fn a_million_rows_cost_under_five_bytes_each() {
let mut tree = Rank::new();
let n = 1_000_000u32;
for i in 0..n {
tree.insert_at(i as usize, i);
}
sound(&tree);
let per = tree.bytes() as f64 / f64::from(n);
assert!(per < 3.4, "{per} bytes a row");
}
}