extern crate alloc;
use alloc::collections::BTreeMap;
use alloc::vec::Vec;
use core::num::NonZeroU64;
use super::super::placement::Dot;
use super::NIL;
use super::region::{RegionBoundary, RegionEnds};
const BRANCH: usize = 8;
const LEAF_FRAGS: usize = 8;
const FRAG_CAP: usize = 64;
#[derive(Clone, Copy, Debug)]
struct Fragment {
station: u32,
base: NonZeroU64,
len: u8,
visible: u64,
}
impl Fragment {
const fn single(dot: Dot, visible: bool) -> Self {
Self {
station: dot.station(),
base: dot.counter_nonzero(),
len: 1,
visible: if visible { 1 } else { 0 },
}
}
const fn slots(&self) -> usize {
self.len as usize
}
const fn visible_count(&self) -> usize {
self.visible.count_ones() as usize
}
const fn base_dot(&self) -> Dot {
Dot::new(self.station, self.base)
}
}
#[derive(Debug)]
pub(in crate::metis::rhapsody) struct Extraction {
frags: Vec<Fragment>,
}
impl Extraction {
pub(in crate::metis::rhapsody) const fn fragments(&self) -> usize {
self.frags.len()
}
}
#[derive(Clone, Debug)]
struct Node {
parent: u32,
slots: usize,
visible: usize,
kind: NodeKind,
}
#[derive(Clone, Debug)]
enum NodeKind {
Internal(Vec<u32>),
Leaf(Vec<Fragment>),
}
#[derive(Clone, Debug)]
pub(in crate::metis::rhapsody) struct OrderThread {
nodes: Vec<Node>,
free: Vec<u32>,
root: u32,
index: BTreeMap<Dot, u32>,
regions: RegionEnds,
}
impl Default for OrderThread {
fn default() -> Self {
Self::new()
}
}
impl OrderThread {
pub(in crate::metis::rhapsody) const fn new() -> Self {
Self {
nodes: Vec::new(),
free: Vec::new(),
root: NIL,
index: BTreeMap::new(),
regions: RegionEnds::new(),
}
}
pub(in crate::metis::rhapsody) fn insert_region_dot(&mut self, dot: Dot) -> bool {
self.regions.insert(dot)
}
pub(in crate::metis::rhapsody) fn insert_region_run(&mut self, head: Dot, tail: Dot) -> bool {
self.regions.insert_run(head, tail)
}
pub(in crate::metis::rhapsody) fn rebuild_regions(
&mut self,
placed: impl Iterator<Item = Dot>,
ends_edges: &BTreeMap<Dot, Dot>,
starts_edges: &BTreeMap<Dot, Dot>,
) {
self.regions.rebuild(placed, ends_edges, starts_edges);
}
pub(in crate::metis::rhapsody) fn remove_region_dot(&mut self, dot: Dot) -> bool {
self.regions.remove(dot)
}
pub(in crate::metis::rhapsody) fn region_start(&mut self, dot: Dot) -> Option<Dot> {
self.regions.endpoint(dot, RegionBoundary::Start)
}
pub(in crate::metis::rhapsody) fn region_end(&mut self, dot: Dot) -> Option<Dot> {
self.regions.endpoint(dot, RegionBoundary::End)
}
pub(in crate::metis::rhapsody) fn replace_region_start(
&mut self,
dot: Dot,
child: Option<Dot>,
) -> bool {
self.regions.replace(dot, child, RegionBoundary::Start)
}
pub(in crate::metis::rhapsody) fn replace_region_end(
&mut self,
dot: Dot,
child: Option<Dot>,
) -> bool {
self.regions.replace(dot, child, RegionBoundary::End)
}
#[cfg(test)]
pub(in crate::metis::rhapsody) fn region_nodes(&self) -> usize {
self.regions.covered()
}
#[cfg(test)]
pub(in crate::metis::rhapsody) fn region_segments(&self) -> usize {
self.regions.segments()
}
#[cfg(test)]
pub(in crate::metis::rhapsody) fn region_forest_nodes(&self) -> usize {
self.regions.forest_nodes()
}
fn alloc(&mut self, node: Node) -> u32 {
if let Some(id) = self.free.pop() {
self.nodes[id as usize] = node;
id
} else {
let id = u32::try_from(self.nodes.len())
.ok()
.filter(|&id| id != NIL)
.expect("the plane's live-entry ceiling bounds the thread's node count");
self.nodes.push(node);
id
}
}
fn refresh(&mut self, id: u32) {
let (slots, visible) = match &self.nodes[id as usize].kind {
NodeKind::Internal(children) => children.iter().fold((0, 0), |(s, v), &child| {
let node = &self.nodes[child as usize];
(s + node.slots, v + node.visible)
}),
NodeKind::Leaf(frags) => frags.iter().fold((0, 0), |(s, v), frag| {
(s + frag.slots(), v + frag.visible_count())
}),
};
self.nodes[id as usize].slots = slots;
self.nodes[id as usize].visible = visible;
}
fn refresh_to_root(&mut self, mut id: u32) {
while id != NIL {
self.refresh(id);
id = self.nodes[id as usize].parent;
}
}
fn leaf_at_slot(&self, position: usize) -> (u32, usize) {
let mut id = self.root;
let mut remaining = position;
loop {
match &self.nodes[id as usize].kind {
NodeKind::Internal(children) => {
let mut next = None;
for &child in children {
let slots = self.nodes[child as usize].slots;
if remaining <= slots {
next = Some(child);
break;
}
remaining -= slots;
}
id = next.expect("an in-range position always lands");
}
NodeKind::Leaf(_) => return (id, remaining),
}
}
}
fn split_leaf_if_over(&mut self, leaf: u32) {
let NodeKind::Leaf(frags) = &mut self.nodes[leaf as usize].kind else {
unreachable!("only leaves split here");
};
if frags.len() <= LEAF_FRAGS {
return;
}
let tail = frags.split_off(frags.len() / 2);
let parent = self.nodes[leaf as usize].parent;
let moved: Vec<Dot> = tail.iter().map(Fragment::base_dot).collect();
let sibling = self.alloc(Node {
parent,
slots: 0,
visible: 0,
kind: NodeKind::Leaf(tail),
});
for dot in moved {
let _ = self.index.insert(dot, sibling);
}
self.refresh(leaf);
self.refresh(sibling);
self.attach_after(leaf, sibling);
}
fn attach_after(&mut self, child: u32, sibling: u32) {
let parent = self.nodes[child as usize].parent;
if parent == NIL {
let root = self.alloc(Node {
parent: NIL,
slots: 0,
visible: 0,
kind: NodeKind::Internal(alloc::vec![child, sibling]),
});
self.nodes[child as usize].parent = root;
self.nodes[sibling as usize].parent = root;
self.root = root;
self.refresh(root);
return;
}
self.nodes[sibling as usize].parent = parent;
let NodeKind::Internal(children) = &mut self.nodes[parent as usize].kind else {
unreachable!("a parent is internal");
};
let at = children
.iter()
.position(|&c| c == child)
.expect("the child is under its parent");
children.insert(at + 1, sibling);
if children.len() > BRANCH {
let tail = children.split_off(children.len() / 2);
let split = self.alloc(Node {
parent: NIL,
slots: 0,
visible: 0,
kind: NodeKind::Internal(tail),
});
let NodeKind::Internal(tail_children) = &self.nodes[split as usize].kind else {
unreachable!("just built internal");
};
let reparent: Vec<u32> = tail_children.clone();
for moved in reparent {
self.nodes[moved as usize].parent = split;
}
self.refresh(parent);
self.refresh(split);
self.attach_after(parent, split);
} else {
self.refresh(parent);
}
}
fn detach_empty(&mut self, id: u32) {
let parent = self.nodes[id as usize].parent;
self.free.push(id);
if parent == NIL {
self.root = NIL;
return;
}
let NodeKind::Internal(children) = &mut self.nodes[parent as usize].kind else {
unreachable!("a parent is internal");
};
let at = children
.iter()
.position(|&c| c == id)
.expect("the child is under its parent");
let _ = children.remove(at);
if children.is_empty() {
self.detach_empty(parent);
} else {
self.refresh_to_root(parent);
}
}
fn build_from_fragments(&mut self, frags: &[Fragment]) {
debug_assert_eq!(self.root, NIL, "the bulk build starts empty");
if frags.is_empty() {
return;
}
let mut level: Vec<u32> = Vec::new();
for chunk in frags.chunks(LEAF_FRAGS) {
let taken = chunk.to_vec();
let bases: Vec<Dot> = taken.iter().map(Fragment::base_dot).collect();
let leaf = self.alloc(Node {
parent: NIL,
slots: 0,
visible: 0,
kind: NodeKind::Leaf(taken),
});
for dot in bases {
let _ = self.index.insert(dot, leaf);
}
self.refresh(leaf);
level.push(leaf);
}
while level.len() > 1 {
let mut above: Vec<u32> = Vec::new();
for group in level.chunks(BRANCH) {
let node = self.alloc(Node {
parent: NIL,
slots: 0,
visible: 0,
kind: NodeKind::Internal(group.to_vec()),
});
for &child in group {
self.nodes[child as usize].parent = node;
}
self.refresh(node);
above.push(node);
}
level = above;
}
self.root = level[0];
}
pub(in crate::metis::rhapsody) fn from_slots(
slots: impl IntoIterator<Item = (Dot, bool)>,
) -> Self {
let mut frags: Vec<Fragment> = Vec::new();
for (dot, visible) in slots {
if let Some(last) = frags.last_mut()
&& last.station == dot.station()
&& last.base.checked_add(u64::from(last.len)) == Some(dot.counter_nonzero())
&& last.slots() < FRAG_CAP
{
if visible {
last.visible |= 1u64 << last.len;
}
last.len += 1;
} else {
frags.push(Fragment::single(dot, visible));
}
}
let mut thread = Self::new();
thread.build_from_fragments(&frags);
thread
}
#[cfg(test)]
pub(in crate::metis::rhapsody) fn check_invariants(&self) {
self.regions.check_invariants();
if self.root == NIL {
assert!(self.index.is_empty(), "an empty thread indexes nothing");
assert!(
self.regions.is_empty(),
"an empty thread has no region segments"
);
return;
}
assert_eq!(self.nodes[self.root as usize].parent, NIL);
let mut seen_frags = 0usize;
let mut stack = alloc::vec![self.root];
while let Some(id) = stack.pop() {
let node = &self.nodes[id as usize];
match &node.kind {
NodeKind::Internal(children) => {
assert!(!children.is_empty(), "internals hold children");
let (mut slots, mut visible) = (0, 0);
for &child in children {
assert_eq!(self.nodes[child as usize].parent, id, "parent links agree");
slots += self.nodes[child as usize].slots;
visible += self.nodes[child as usize].visible;
stack.push(child);
}
assert_eq!((node.slots, node.visible), (slots, visible));
}
NodeKind::Leaf(frags) => {
assert!(!frags.is_empty(), "leaves hold fragments");
assert!(
frags.len() <= LEAF_FRAGS,
"a bulk splice split every overfull leaf"
);
let (mut slots, mut visible) = (0, 0);
for frag in frags {
assert!(frag.len >= 1 && frag.slots() <= FRAG_CAP);
if frag.len < 64 {
assert_eq!(
frag.visible >> frag.len,
0,
"mask bits above len stay zero"
);
}
assert_eq!(self.index.get(&frag.base_dot()), Some(&id));
slots += frag.slots();
visible += frag.visible_count();
seen_frags += 1;
}
assert_eq!((node.slots, node.visible), (slots, visible));
}
}
}
assert_eq!(
seen_frags,
self.index.len(),
"the index covers every fragment"
);
}
}
mod mutate;
mod reads;
mod splice;
#[cfg(test)]
use reads::nth_set_bit;
#[cfg(test)]
mod tests;