pub type ChunkCount = u64;
pub type ChunkIndex = ChunkCount;
pub type NodeNumber = u64;
pub type RootedPathLength = u8;
pub type Layer = u8;
pub type ByteCount = u64;
pub type ByteIndex = ByteCount;
pub fn chunk_index_to_node_number(chunk_index: ChunkIndex, chunk_count: ChunkCount) -> NodeNumber {
assert!(chunk_index < chunk_count);
if chunk_count == 1 {
return 0;
} else {
let left_subtree_leaf_count = chunk_count.next_power_of_two() / 2;
if chunk_index < left_subtree_leaf_count {
return 1 + chunk_index_to_node_number(chunk_index, left_subtree_leaf_count);
} else {
return left_subtree_leaf_count * 2
+ chunk_index_to_node_number(
chunk_index - left_subtree_leaf_count,
chunk_count - left_subtree_leaf_count,
);
}
}
}
#[test]
fn test_chunk_index_to_node_number() {
let expected = [
&[0u64][..],
&[1, 2][..],
&[2, 3, 4][..],
&[2, 3, 5, 6][..],
&[3, 4, 6, 7, 8][..],
&[3, 4, 6, 7, 9, 10][..],
&[3, 4, 6, 7, 10, 11, 12][..],
&[3, 4, 6, 7, 10, 11, 13, 14][..],
&[4, 5, 7, 8, 11, 12, 14, 15, 16][..],
];
for (i, testdata) in expected.iter().enumerate() {
for (chunk_index, node_number) in testdata.iter().enumerate() {
assert_eq!(
chunk_index_to_node_number(chunk_index as ChunkIndex, (i as u64) + 1),
*node_number,
);
}
}
}
pub fn node_number_to_chunk_index(node_number: ChunkIndex, chunk_count: ChunkCount) -> NodeNumber {
if node_number == 0 {
return 0;
} else {
let left_subtree_node_count = chunk_count.next_power_of_two() - 1;
let left_subtree_leaf_count = chunk_count.next_power_of_two() / 2;
if node_number <= left_subtree_node_count {
return node_number_to_chunk_index(node_number - 1, left_subtree_leaf_count);
} else {
return left_subtree_leaf_count
+ node_number_to_chunk_index(
node_number - (left_subtree_node_count + 1),
chunk_count - left_subtree_leaf_count,
);
}
}
}
#[test]
fn test_node_number_to_chunk_index() {
let expected = [
&[0u64][..],
&[0, 0, 1][..],
&[0, 0, 0, 1, 2][..],
&[0, 0, 0, 1, 2, 2, 3][..],
&[0, 0, 0, 0, 1, 2, 2, 3, 4][..],
&[0, 0, 0, 0, 1, 2, 2, 3, 4, 4, 5][..],
&[0, 0, 0, 0, 1, 2, 2, 3, 4, 4, 4, 5, 6][..],
&[0, 0, 0, 0, 1, 2, 2, 3, 4, 4, 4, 5, 6, 6, 7][..],
&[0, 0, 0, 0, 0, 1, 2, 2, 3, 4, 4, 4, 5, 6, 6, 7, 8][..],
];
for (i, testdata) in expected.iter().enumerate() {
for (node_number, expected_chunk_index) in testdata.iter().enumerate() {
assert_eq!(
node_number_to_chunk_index(node_number as NodeNumber, (i + 1) as ChunkCount),
*expected_chunk_index,
);
}
}
}
pub(crate) fn node_number_to_left_skip(node_number: NodeNumber, chunk_count: ChunkCount) -> u8 {
if node_number == 0 {
return 0;
} else {
let left_subtree_node_count = chunk_count.next_power_of_two() - 1;
let left_subtree_leaf_count = chunk_count.next_power_of_two() / 2;
if node_number <= left_subtree_node_count {
return 1 + node_number_to_left_skip(node_number - 1, left_subtree_leaf_count);
} else {
return 1 + node_number_to_left_skip(
node_number - (left_subtree_node_count + 1),
chunk_count - left_subtree_leaf_count,
);
}
}
}
#[test]
fn test_node_number_to_left_skip() {
let expected = [
&[0u8][..],
&[0, 1, 1][..],
&[0, 1, 2, 2, 1][..],
&[0, 1, 2, 2, 1, 2, 2][..],
&[0, 1, 2, 3, 3, 2, 3, 3, 1][..],
&[0, 1, 2, 3, 3, 2, 3, 3, 1, 2, 2][..],
&[0, 1, 2, 3, 3, 2, 3, 3, 1, 2, 3, 3, 2][..],
&[0, 1, 2, 3, 3, 2, 3, 3, 1, 2, 3, 3, 2, 3, 3][..],
&[0, 1, 2, 3, 4, 4, 3, 4, 4, 2, 3, 4, 4, 3, 4, 4, 1][..],
];
for (i, testdata) in expected.iter().enumerate() {
for (node_number, expected_left_skip) in testdata.iter().enumerate() {
assert_eq!(
node_number_to_left_skip(node_number as NodeNumber, (i + 1) as ChunkCount),
*expected_left_skip,
);
}
}
}
pub(crate) fn node_number_to_right_skip(
node_number: NodeNumber,
final_chunk_of_slice: ChunkIndex,
chunk_count: ChunkCount,
) -> u8 {
let final_node_number = chunk_index_to_node_number(final_chunk_of_slice, chunk_count);
node_number_to_right_skip_(node_number, final_node_number, chunk_count)
}
fn node_number_to_right_skip_(
node_number: NodeNumber,
final_node_number: NodeNumber,
chunk_count: ChunkCount,
) -> u8 {
if node_number == 0 {
return 0;
} else {
let left_subtree_node_count = chunk_count.next_power_of_two() - 1;
let left_subtree_leaf_count = chunk_count.next_power_of_two() / 2;
if node_number <= left_subtree_node_count {
if final_node_number > left_subtree_node_count {
return 1;
} else {
return 1 + node_number_to_right_skip_(
node_number - 1,
final_node_number - 1,
left_subtree_leaf_count,
);
}
} else {
return 1 + node_number_to_right_skip_(
node_number - (left_subtree_node_count + 1),
final_node_number - (left_subtree_node_count + 1),
chunk_count - left_subtree_leaf_count,
);
}
}
}
#[test]
fn test_node_number_to_right_skip() {
let expected = [
&[0, 0, 0, 0, 0, 0][..],
&[1, 1, 1, 1, 1, 1][..],
&[2, 2, 2, 2, 1, 1][..],
&[3, 3, 2, 2, 1, 1][..],
&[3, 2, 2, 1, 1][..],
&[2, 2, 1, 1][..],
&[3, 3, 1, 1][..],
&[3, 1, 1][..],
&[1, 1][..],
&[2, 2][..],
&[2][..],
];
for (i, testdata) in expected.iter().enumerate() {
for (j, expected_right_skip) in testdata.iter().enumerate() {
let final_chunk_of_slice = (j + (6 - testdata.len())) as ChunkIndex;
assert_eq!(
node_number_to_right_skip(i as NodeNumber, final_chunk_of_slice, 6),
*expected_right_skip,
);
}
}
}
pub fn string_length_to_chunk_count<const CHUNK_SIZE: usize>(len: ByteCount) -> ChunkCount {
if len == 0 {
1
} else {
len.div_ceil(CHUNK_SIZE as u64)
}
}