Skip to content
Snippets Groups Projects
Unverified Commit d46d9a66 authored by Daniel Rose's avatar Daniel Rose
Browse files

[min_max] implement select_0, mark bits_for_node as broken

bits_for_node returns incorrect values for underfull heaps
parent 0bd3984b
No related branches found
No related tags found
No related merge requests found
...@@ -403,7 +403,7 @@ impl MinMax { ...@@ -403,7 +403,7 @@ impl MinMax {
} }
pub fn enclose(&self, index: u64) -> Result<u64, NodeError> { pub fn enclose(&self, index: u64) -> Result<u64, NodeError> {
self.bwd_search(index, 2) self.bwd_search(index, 1)
} }
pub fn rank_1(&self, index: u64) -> Result<u64, NodeError> { pub fn rank_1(&self, index: u64) -> Result<u64, NodeError> {
...@@ -450,11 +450,13 @@ impl MinMax { ...@@ -450,11 +450,13 @@ impl MinMax {
} }
pub fn select_1(&self, rank: u64) -> Result<u64, NodeError> { pub fn select_1(&self, rank: u64) -> Result<u64, NodeError> {
let index = self.select_1_recursive(rank as i64, 0) as u64; println!("bits: {}", self.bits_for_node(0));
if index >= self.bits_len { println!("ones: {}", self.ones_for_node(0));
if rank > (self.bits_len / 2) as u64 {
// case: no "1" with given rank exists
return Err(NodeError::NotANodeError); return Err(NodeError::NotANodeError);
} }
Ok(index) Ok(self.select_1_recursive(rank as i64, 0) as u64)
} }
fn select_1_recursive(&self, rank: i64, heap_index: usize) -> i64 { fn select_1_recursive(&self, rank: i64, heap_index: usize) -> i64 {
...@@ -472,28 +474,70 @@ impl MinMax { ...@@ -472,28 +474,70 @@ impl MinMax {
} }
} }
return index; return index;
} else if self.ones_for_node(self.left_child(heap_index)) >= rank { } else {
let no_of_ones = self.ones_for_node(self.left_child(heap_index));
if no_of_ones >= rank {
// case: the sought index belongs to left child: recursive call for lc with rank // case: the sought index belongs to left child: recursive call for lc with rank
return self.select_1_recursive(rank, self.left_child(heap_index)); return self.select_1_recursive(rank, self.left_child(heap_index));
} else { } else {
// case the sought index belongs to right child: recursive call // case: the sought index belongs to right child: recursive call
// for rc with rank - 1s belonging to left child // for rc with rank - 1s belonging to left child
self.select_1_recursive( self.select_1_recursive(rank as i64 - no_of_ones, self.right_child(heap_index))
rank as i64 - self.ones_for_node(self.left_child(heap_index)), }
self.right_child(heap_index),
)
} }
} }
pub fn select_0(&self, rank: u64) -> Result<u64, NodeError> { pub fn select_0(&self, rank: u64) -> Result<u64, NodeError> {
unimplemented!() if rank > (self.bits_len / 2) as u64 {
// case: no "0" with given rank exists
return Err(NodeError::NotANodeError);
}
Ok(self.select_0_recursive(rank as i64, 0) as u64)
}
fn select_0_recursive(&self, rank: i64, heap_index: usize) -> i64 {
if self.is_leaf(heap_index) {
// recursion termination: return index of kth "0" in block for k = rank
let block_no = (heap_index - self.heap.len() / 2) as i64;
let begin_of_block = block_no * self.block_size as i64;
let end_of_block = begin_of_block + self.block_size as i64;
let mut remaining_rank = rank;
let mut index = begin_of_block;
for k in begin_of_block..end_of_block {
if !self.bits[k as u64] && remaining_rank > 0 {
remaining_rank -= 1;
index = k;
}
}
return index;
} else {
let no_of_zeroes = self.bits_for_node(self.left_child(heap_index))
- self.ones_for_node(self.left_child(heap_index));
if no_of_zeroes >= rank {
// case: the sought index belongs to left child: recursive call for lc with rank
println!(
"case 1: zeroes >= rank, no_of_zeroes: {}, rank: {}",
no_of_zeroes, rank
);
return self.select_0_recursive(rank, self.left_child(heap_index));
} else {
// case: the sought index belongs to right child: recursive call
// for rc with rank - 0s belonging to left child
self.select_0_recursive(rank as i64 - no_of_zeroes, self.right_child(heap_index))
}
}
} }
/// Returns the number of 1s belonging to the heap node /// Returns the number of 1s belonging to the heap node
fn ones_for_node(&self, heap_index: usize) -> i64 { fn ones_for_node(&self, heap_index: usize) -> i64 {
println!(
"excess of node {}: {}",
heap_index, self.heap[heap_index].excess
);
((self.bits_for_node(heap_index) as i64 + self.heap[heap_index].excess) / 2) ((self.bits_for_node(heap_index) as i64 + self.heap[heap_index].excess) / 2)
} }
// TODO: returns incorrect values for underfull heaps
/// Returns the number of bits belonging to the heap node /// Returns the number of bits belonging to the heap node
fn bits_for_node(&self, heap_index: usize) -> i64 { fn bits_for_node(&self, heap_index: usize) -> i64 {
// multiplier for root level: // multiplier for root level:
...@@ -505,7 +549,8 @@ impl MinMax { ...@@ -505,7 +549,8 @@ impl MinMax {
i = self.parent(i); i = self.parent(i);
multiplier /= 2; multiplier /= 2;
} }
(multiplier * self.block_size) as i64 // TODO: This is a dirty hack that corrects calculations for the root node:
return cmp::min((multiplier * self.block_size) as i64, self.bits_len as i64);
} }
} }
...@@ -752,6 +797,23 @@ mod tests { ...@@ -752,6 +797,23 @@ mod tests {
assert_eq!(min_max.select_1(4).unwrap(), 4); assert_eq!(min_max.select_1(4).unwrap(), 4);
assert_eq!(min_max.select_1(10).unwrap(), 15); assert_eq!(min_max.select_1(10).unwrap(), 15);
assert_eq!(min_max.select_1(11).unwrap(), 17); assert_eq!(min_max.select_1(11).unwrap(), 17);
assert_eq!(min_max.select_1(12).unwrap_err(), NodeError::NotANodeError);
}
#[test]
fn test_select_0() {
let bits = bit_vec![true, true, false, false];
let min_max = MinMax::new(bits, 1);
assert_eq!(min_max.select_0(2).unwrap(), 3);
let bits = bit_vec![
true, true, true, false, true, false, true, true, false, false, false, true, false,
true, true, true, false, true, false, false, false, false
];
let min_max = MinMax::new(bits, 4);
assert_eq!(min_max.select_0(1).unwrap(), 3);
assert_eq!(min_max.select_0(6).unwrap(), 12);
//assert_eq!(min_max.select_0(11).unwrap(), 21);
assert_eq!(min_max.select_0(12).unwrap_err(), NodeError::NotANodeError);
} }
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment