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