~ntietz/isabella-db

31726ab3bae9fe99cafb40af78f8e992050e6b14 — Nicholas Tietz-Sokolsky 17 days ago 564c53f
Add bitwise and and or operations
1 files changed, 148 insertions(+), 4 deletions(-)

M bitmap/src/sparse.rs
M bitmap/src/sparse.rs => bitmap/src/sparse.rs +148 -4
@@ 1,10 1,13 @@
use std::fmt::Debug;
use std::{
    fmt::Debug,
    ops::{BitAnd, BitOr},
};

use serde::{Deserialize, Serialize};

use super::{BitmapError, ItemID};

#[derive(Clone, Copy, Debug, Default, Serialize, Deserialize)]
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Serialize, Deserialize)]
pub struct Run {
    pub start: u32,
    pub length: u32,


@@ 14,12 17,42 @@ impl Run {
    pub fn contains(&self, key: u32) -> bool {
        key >= self.start && key < self.start + self.length
    }

    pub fn overlap(&self, rhs: Run) -> bool {
        self.contains(rhs.start) || rhs.contains(self.start)
    }

    pub fn end(&self) -> u32 {
        self.start + self.length - 1
    }

    pub fn intersect(&self, rhs: Run) -> Option<Run> {
        if self.overlap(rhs) {
            let start = self.start.max(rhs.start);
            let end = self.end().min(rhs.end());
            let length = end - start + 1;
            Some(Run { start, length })
        } else {
            None
        }
    }

    pub fn union(&self, rhs: Run) -> Option<Run> {
        if self.overlap(rhs) {
            let start = self.start.min(rhs.start);
            let end = self.end().max(rhs.end());
            let length = end - start + 1;
            Some(Run { start, length })
        } else {
            None
        }
    }
}

/// SparseBitmap stores contiguous runs of the same value, rather than each bit
/// individually. It has a fixed size assigned at creation and cannot be
/// resized.
#[derive(Clone, Serialize, Deserialize)]
#[derive(Clone, Eq, PartialEq, Serialize, Deserialize)]
pub struct SparseBitmap {
    runs: Vec<Run>,
    size: usize,


@@ 93,6 126,14 @@ impl SparseBitmap {

        Some(false)
    }

    fn add_run(&mut self, run: Run) {
        if let Some(last) = self.runs.last_mut() && last.overlap(run) {
            *last = last.union(run).unwrap();
        } else {
            self.runs.push(run);
        }
    }
}

pub struct SparseBitmapIterator<'a> {


@@ 140,6 181,74 @@ impl<'a> IntoIterator for &'a SparseBitmap {
    }
}

impl BitAnd for &SparseBitmap {
    type Output = SparseBitmap;

    fn bitand(self, rhs: Self) -> Self::Output {
        let size = self.size.max(rhs.size);

        let mut result = SparseBitmap::of_size(size);

        let mut left_iter = self.runs.iter();
        let mut right_iter = rhs.runs.iter();

        let mut left_opt = left_iter.next();
        let mut right_opt = right_iter.next();

        while let Some(left) = left_opt && let Some(right) = right_opt {
            if let Some(run) = left.intersect(*right) {
                result.runs.push(run);
            }

            if left.start < right.start {
                left_opt = left_iter.next();
            } else {
                right_opt = right_iter.next();
            }
        }

        result
    }
}

impl BitOr for &SparseBitmap {
    type Output = SparseBitmap;

    fn bitor(self, rhs: Self) -> Self::Output {
        let size = self.size.max(rhs.size);

        let mut result = SparseBitmap::of_size(size);

        let mut left_iter = self.runs.iter().peekable();
        let mut right_iter = rhs.runs.iter().peekable();

        let mut left_opt = left_iter.next();
        let mut right_opt = right_iter.next();

        while let Some(left) = left_opt && let Some(right) = right_opt {
            if left.start < right.start {
                result.add_run(*left);
                left_opt = left_iter.next();
            } else {
                result.add_run(*right);
                right_opt = right_iter.next();
            }
        }

        while let Some(left) = left_opt {
            result.add_run(*left);
            left_opt = left_iter.next();
        }

        while let Some(right) = right_opt {
            result.add_run(*right);
            right_opt = right_iter.next();
        }

        result
    }
}

#[cfg(test)]
mod tests {
    use super::*;


@@ 204,6 313,41 @@ mod tests {

        assert_eq!(bits, expected_bits);
    }

    #[test]
    fn sparse_bitmap_bitwise_and() {
        let size = 16;

        let a = bitmap_from_vec(size, vec![0, 4, 5, 9, 10, 11]);
        let b = bitmap_from_vec(size, vec![4, 5, 7, 9, 10, 11, 12]);

        let and_bitm = &a & &b;
        let expected_and_bitm = bitmap_from_vec(size, vec![4, 5, 9, 10, 11]);

        assert_eq!(and_bitm, expected_and_bitm);
    }

    #[test]
    fn sparse_bitmap_bitwise_ops() {}
    fn sparse_bitmap_bitwise_or() {
        let size = 16;

        let a = bitmap_from_vec(size, vec![0, 4, 5, 9, 10, 11]);
        let b = bitmap_from_vec(size, vec![4, 5, 7, 9, 10, 11, 12]);

        let or_bitm = &a | &b;
        let expected_or_bitm = bitmap_from_vec(size, vec![0, 4, 5, 7, 9, 10, 11, 12]);

        assert_eq!(or_bitm, expected_or_bitm);
    }

    /// Helper to build a bitmap from a **sorted** list of bit indexes.
    fn bitmap_from_vec(size: usize, bits: Vec<ItemID>) -> SparseBitmap {
        let mut bm = SparseBitmap::of_size(size);

        for bit in bits {
            bm.set(bit).expect("should set the value");
        }

        bm
    }
}