#![deny(missing_docs)]
pub fn index(depth: u64, offset: u64) -> u64 {
return (offset << depth + 1) | ((1 << depth) - 1);
}
pub fn depth(i: u64) -> u64 {
let mut depth = 0;
let mut i = i;
while i & 1 != 0 {
i >>= 1;
depth += 1;
}
return depth;
}
pub fn offset_with_depth(i: u64, depth: u64) -> u64 {
return i >> (depth + 1);
}
pub fn offset(i: u64) -> u64 {
return offset_with_depth(i, depth(i));
}
pub fn parent_with_depth(i: u64, depth: u64) -> u64 {
return index(depth + 1, offset_with_depth(i, depth) >> 1);
}
pub fn parent(i: u64) -> u64 {
return parent_with_depth(i, depth(i));
}
pub fn sibling_with_depth(i: u64, depth: u64) -> u64 {
return index(depth, offset(i) ^ 1);
}
pub fn sibling(i: u64) -> u64 {
return sibling_with_depth(i, depth(i));
}
pub fn uncle_with_depth(i: u64, depth: u64) -> u64 {
return sibling_with_depth(parent_with_depth(i, depth), depth + 1);
}
pub fn uncle(i: u64) -> u64 {
return uncle_with_depth(i, depth(i));
}
pub fn children_with_depth(i: u64, depth: u64) -> (u64, u64) {
if depth == 0 {
return (i, i);
}
let off = offset_with_depth(i, depth) >> 1;
return (index(depth - 1, off), index(depth - 1, off + 1));
}
pub fn children(i: u64) -> (u64, u64) {
return children_with_depth(i, depth(i));
}
pub fn left_child_with_depth(i: u64, depth: u64) -> u64 {
if depth == 0 {
return i;
}
return index(depth - 1, offset_with_depth(i, depth) << 1);
}
pub fn left_child(i: u64) -> u64 {
return left_child_with_depth(i, depth(i));
}
pub fn right_child_with_depth(i: u64, depth: u64) -> u64 {
if depth == 0 {
return i;
}
return index(depth - 1, (offset_with_depth(i, depth) << 1) + 1);
}
pub fn right_child(i: u64) -> u64 {
return right_child_with_depth(i, depth(i));
}
pub fn right_span_with_depth(i: u64, depth: u64) -> u64 {
if depth == 0 {
return i;
}
return (offset_with_depth(i, depth) + 1) * (2 << depth) - 2;
}
pub fn right_span(i: u64) -> u64 {
return right_span_with_depth(i, depth(i));
}
pub fn left_span_with_depth(i: u64, depth: u64) -> u64 {
if depth == 0 {
return i;
}
return offset_with_depth(i, depth) * (2 << depth);
}
pub fn left_span(i: u64) -> u64 {
return left_span_with_depth(i, depth(i));
}
pub fn spans_with_depth(i: u64, depth: u64) -> (u64, u64) {
return (
left_span_with_depth(i, depth),
right_span_with_depth(i, depth),
);
}
pub fn spans(i: u64) -> (u64, u64) {
return spans_with_depth(i, depth(i));
}
pub fn count_with_depth(_: u64, depth: u64) -> u64 {
return (2 << depth) - 1;
}
pub fn count(i: u64) -> u64 {
return count_with_depth(i, depth(i));
}
pub fn full_roots(i: u64) -> Vec<u64> {
let mut result = Vec::with_capacity(64);
if i & 1 != 0 {
return result;
}
let mut tmp = i >> 1;
let mut offset = 0;
let mut factor = 1;
loop {
if tmp == 0 {
return result;
}
while factor * 2 <= tmp {
factor *= 2;
}
result.push(offset + factor - 1);
offset += 2 * factor;
tmp -= factor;
factor = 1;
}
}
#[test]
fn test_parent_gt_int32() {
assert_eq!(parent(10000000000), 10000000001);
}
#[test]
fn test_child_to_parent_to_child() {
let mut child = 0;
for _ in 0..50 {
child = parent(child)
}
assert_eq!(child, 1125899906842623);
for _ in 0..50 {
child = left_child(child)
}
assert_eq!(child, 0);
}