From d46d9a66a4f73c13bac68cf4da9d3ccf4dbac978 Mon Sep 17 00:00:00 2001 From: Daniel Rose <droseger@protonmail.com> Date: Wed, 11 Jul 2018 23:43:24 +0200 Subject: [PATCH] [min_max] implement select_0, mark bits_for_node as broken bits_for_node returns incorrect values for underfull heaps --- src/common/min_max.rs | 92 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 77 insertions(+), 15 deletions(-) diff --git a/src/common/min_max.rs b/src/common/min_max.rs index 7ce0edd..519c6f1 100644 --- a/src/common/min_max.rs +++ b/src/common/min_max.rs @@ -403,7 +403,7 @@ impl MinMax { } 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> { @@ -450,11 +450,13 @@ impl MinMax { } pub fn select_1(&self, rank: u64) -> Result<u64, NodeError> { - let index = self.select_1_recursive(rank as i64, 0) as u64; - if index >= self.bits_len { + println!("bits: {}", self.bits_for_node(0)); + 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); } - Ok(index) + Ok(self.select_1_recursive(rank as i64, 0) as u64) } fn select_1_recursive(&self, rank: i64, heap_index: usize) -> i64 { @@ -472,28 +474,70 @@ impl MinMax { } } return index; - } else if self.ones_for_node(self.left_child(heap_index)) >= 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)); } else { - // case the sought index belongs to right child: recursive call - // for rc with rank - 1s belonging to left child - self.select_1_recursive( - rank as i64 - self.ones_for_node(self.left_child(heap_index)), - self.right_child(heap_index), - ) + 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 + return self.select_1_recursive(rank, self.left_child(heap_index)); + } else { + // case: the sought index belongs to right child: recursive call + // for rc with rank - 1s belonging to left child + self.select_1_recursive(rank as i64 - no_of_ones, self.right_child(heap_index)) + } } } 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 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) } + // TODO: returns incorrect values for underfull heaps /// Returns the number of bits belonging to the heap node fn bits_for_node(&self, heap_index: usize) -> i64 { // multiplier for root level: @@ -505,7 +549,8 @@ impl MinMax { i = self.parent(i); 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 { assert_eq!(min_max.select_1(4).unwrap(), 4); assert_eq!(min_max.select_1(10).unwrap(), 15); 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); } } -- GitLab