Skip to content

Commit

Permalink
Merge branch 'generic'
Browse files Browse the repository at this point in the history
  • Loading branch information
Nemo157 committed Jan 28, 2015
2 parents 803b12f + bbb93ec commit ffd76c8
Show file tree
Hide file tree
Showing 18 changed files with 561 additions and 642 deletions.
6 changes: 3 additions & 3 deletions benches/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@ use roaring::RoaringBitmap;
#[bench]
fn create(b: &mut Bencher) {
b.iter(|| {
let mut bitmap = RoaringBitmap::new();
let mut bitmap: RoaringBitmap<u32> = RoaringBitmap::new();
bitmap
})
}

#[bench]
fn insert1(b: &mut Bencher) {
b.iter(|| {
let mut bitmap = RoaringBitmap::new();
let mut bitmap: RoaringBitmap<u32> = RoaringBitmap::new();
bitmap.insert(1);
bitmap
})
Expand All @@ -28,7 +28,7 @@ fn insert1(b: &mut Bencher) {
#[bench]
fn insert2(b: &mut Bencher) {
b.iter(|| {
let mut bitmap = RoaringBitmap::new();
let mut bitmap: RoaringBitmap<u32> = RoaringBitmap::new();
bitmap.insert(1);
bitmap.insert(2);
bitmap
Expand Down
9 changes: 5 additions & 4 deletions src/container.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
use std::num::Int;
use std::fmt::{ Debug, Formatter, Result };

use util::ExtInt;
use store::Store::{ self, Array, Bitmap };

#[derive(PartialEq, Clone)]
pub struct Container<Size> where Size: Int {
pub struct Container<Size: ExtInt> {
key: Size,
len: Size,
store: Store<Size>,
}

impl<Size> Container<Size> where Size: Int {
impl<Size: ExtInt> Container<Size> {
pub fn new(key: Size) -> Container<Size> {
Container {
key: key,
Expand All @@ -20,7 +21,7 @@ impl<Size> Container<Size> where Size: Int {
}
}

impl<Size> Container<Size> where Size: Int {
impl<Size: ExtInt> Container<Size> {
#[inline]
pub fn key(&self) -> Size { self.key }

Expand Down Expand Up @@ -126,7 +127,7 @@ impl<Size> Container<Size> where Size: Int {
}
}

impl<Size> Debug for Container<Size> where Size: Int + Debug {
impl<Size: ExtInt + Debug> Debug for Container<Size> {
#[inline]
fn fmt(&self, formatter: &mut Formatter) -> Result {
format!("Container<{:?} @ {:?}>", self.len(), self.key()).fmt(formatter)
Expand Down
130 changes: 54 additions & 76 deletions src/imp.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@
use std::{ u16, u32 };
use std::cmp::Ordering;
use std::cmp::Ordering::{ Equal, Less, Greater };
use std::num::Int;
use std::slice;

use iter::{ self, Iter, UnionIter, IntersectionIter, DifferenceIter, SymmetricDifferenceIter };
use container::Container;
use util;
use util::{ Halveable, ExtInt };

type RB = ::RoaringBitmap;
type RB<Size> = ::RoaringBitmap<Size>;

#[inline]
pub fn new() -> RB {
pub fn new<Size: ExtInt + Halveable>() -> RB<Size> {
RB { containers: Vec::new() }
}

pub fn insert(this: &mut RB, value: u32) -> bool {
let (key, index) = calc_loc(value);
pub fn insert<Size: ExtInt + Halveable>(this: &mut RB<Size>, value: Size) -> bool {
let (key, index) = value.split();
let container = match this.containers.binary_search_by(|container| container.key().cmp(&key)) {
Ok(loc) => &mut this.containers[loc],
Err(loc) => {
Expand All @@ -23,12 +27,12 @@ pub fn insert(this: &mut RB, value: u32) -> bool {
container.insert(index)
}

pub fn remove(this: &mut RB, value: u32) -> bool {
let (key, index) = calc_loc(value);
pub fn remove<Size: ExtInt + Halveable>(this: &mut RB<Size>, value: Size) -> bool {
let (key, index) = value.split();
match this.containers.binary_search_by(|container| container.key().cmp(&key)) {
Ok(loc) => {
if this.containers[loc].remove(index) {
if this.containers[loc].len() == 0 {
if this.containers[loc].len() == Int::zero() {
this.containers.remove(loc);
}
true
Expand All @@ -40,47 +44,47 @@ pub fn remove(this: &mut RB, value: u32) -> bool {
}
}

pub fn contains(this: &RB, value: u32) -> bool {
let (key, index) = calc_loc(value);
pub fn contains<Size: ExtInt + Halveable>(this: &RB<Size>, value: Size) -> bool {
let (key, index) = value.split();
match this.containers.binary_search_by(|container| container.key().cmp(&key)) {
Ok(loc) => this.containers[loc].contains(index),
Err(_) => false,
}
}

#[inline]
pub fn clear(this: &mut RB) {
pub fn clear<Size: ExtInt + Halveable>(this: &mut RB<Size>) {
this.containers.clear();
}

#[inline]
pub fn is_empty(this: &RB) -> bool {
pub fn is_empty<Size: ExtInt + Halveable>(this: &RB<Size>) -> bool {
this.containers.is_empty()
}

pub fn len(this: &RB) -> usize {
pub fn len<Size: ExtInt + Halveable>(this: &RB<Size>) -> Size {
this.containers
.iter()
.map(|container| container.len() as usize)
.fold(0, |sum, len| sum + len)
.map(|container| container.len())
.fold(Int::zero(), |sum: Size, len| sum + util::cast(len))
}

#[inline]
pub fn iter<'a>(this: &'a RB) -> Iter<'a> {
pub fn iter<'a, Size: ExtInt + Halveable>(this: &'a RB<Size>) -> Iter<'a, Size> where <Size as Halveable>::HalfSize : 'a {
iter::new(this.containers.iter())
}

fn pairs<'a>(this: &'a RB, other: &'a RB) -> Pairs<'a> {
fn pairs<'a, Size: ExtInt + Halveable>(this: &'a RB<Size>, other: &'a RB<Size>) -> Pairs<'a, Size> where <Size as Halveable>::HalfSize : 'a {
Pairs::new(this.containers.iter(), other.containers.iter())
}

pub fn is_disjoint(this: &RB, other: &RB) -> bool {
pub fn is_disjoint<Size: ExtInt + Halveable>(this: &RB<Size>, other: &RB<Size>) -> bool {
pairs(this, other)
.filter(|&(c1, c2)| c1.is_some() && c2.is_some())
.all(|(c1, c2)| c1.unwrap().is_disjoint(c2.unwrap()))
}

pub fn is_subset(this: &RB, other: &RB) -> bool {
pub fn is_subset<Size: ExtInt + Halveable>(this: &RB<Size>, other: &RB<Size>) -> bool {
pairs(this, other).all(|pairs| match pairs {
(None, _) => return true,
(_, None) => return false,
Expand All @@ -89,32 +93,32 @@ pub fn is_subset(this: &RB, other: &RB) -> bool {
}

#[inline]
pub fn is_superset(this: &RB, other: &RB) -> bool {
pub fn is_superset<Size: ExtInt + Halveable>(this: &RB<Size>, other: &RB<Size>) -> bool {
other.is_subset(this)
}

#[inline]
pub fn union<'a>(this: &'a RB, other: &'a RB) -> UnionIter<'a> {
pub fn union<'a, Size: ExtInt + Halveable>(this: &'a RB<Size>, other: &'a RB<Size>) -> UnionIter<'a, Size> where <Size as Halveable>::HalfSize : 'a {
iter::union::new(this.iter(), other.iter())
}

#[inline]
pub fn intersection<'a>(this: &'a RB, other: &'a RB) -> IntersectionIter<'a> {
pub fn intersection<'a, Size: ExtInt + Halveable>(this: &'a RB<Size>, other: &'a RB<Size>) -> IntersectionIter<'a, Size> where <Size as Halveable>::HalfSize : 'a {
iter::intersection::new(this.iter(), other.iter())
}

#[inline]
pub fn difference<'a>(this: &'a RB, other: &'a RB) -> DifferenceIter<'a> {
pub fn difference<'a, Size: ExtInt + Halveable>(this: &'a RB<Size>, other: &'a RB<Size>) -> DifferenceIter<'a, Size> where <Size as Halveable>::HalfSize : 'a {
iter::difference::new(this.iter(), other.iter())
}

#[inline]
pub fn symmetric_difference<'a>(this: &'a RB, other: &'a RB) -> SymmetricDifferenceIter<'a> {
pub fn symmetric_difference<'a, Size: ExtInt + Halveable>(this: &'a RB<Size>, other: &'a RB<Size>) -> SymmetricDifferenceIter<'a, Size> where <Size as Halveable>::HalfSize : 'a {
iter::symmetric_difference::new(this.iter(), other.iter())
}

#[inline]
pub fn union_with(this: &mut RB, other: &RB) {
pub fn union_with<Size: ExtInt + Halveable>(this: &mut RB<Size>, other: &RB<Size>) {
for container in other.containers.iter() {
let key = container.key();
match this.containers.binary_search_by(|container| container.key().cmp(&key)) {
Expand All @@ -125,7 +129,7 @@ pub fn union_with(this: &mut RB, other: &RB) {
}

#[inline]
pub fn intersect_with(this: &mut RB, other: &RB) {
pub fn intersect_with<Size: ExtInt + Halveable>(this: &mut RB<Size>, other: &RB<Size>) {
let mut index = 0;
while index < this.containers.len() {
let key = this.containers[index].key();
Expand All @@ -142,13 +146,13 @@ pub fn intersect_with(this: &mut RB, other: &RB) {
}

#[inline]
pub fn difference_with(this: &mut RB, other: &RB) {
pub fn difference_with<Size: ExtInt + Halveable>(this: &mut RB<Size>, other: &RB<Size>) {
for index in 0..this.containers.len() {
let key = this.containers[index].key();
match other.containers.binary_search_by(|container| container.key().cmp(&key)) {
Ok(loc) => {
this.containers[index].difference_with(&other.containers[loc]);
if this.containers[index].len() == 0 {
if this.containers[index].len() == Int::zero() {
this.containers.remove(index);
}
},
Expand All @@ -158,14 +162,14 @@ pub fn difference_with(this: &mut RB, other: &RB) {
}

#[inline]
pub fn symmetric_difference_with(this: &mut RB, other: &RB) {
pub fn symmetric_difference_with<Size: ExtInt + Halveable>(this: &mut RB<Size>, other: &RB<Size>) {
for container in other.containers.iter() {
let key = container.key();
match this.containers.binary_search_by(|container| container.key().cmp(&key)) {
Err(loc) => this.containers.insert(loc, (*container).clone()),
Ok(loc) => {
this.containers[loc].symmetric_difference_with(container);
if this.containers[loc].len() == 0 {
if this.containers[loc].len() == Int::zero() {
this.containers.remove(loc);
}
}
Expand All @@ -174,64 +178,56 @@ pub fn symmetric_difference_with(this: &mut RB, other: &RB) {
}

#[inline]
pub fn from_iter<I: Iterator<Item = u32>>(iterator: I) -> RB {
pub fn from_iter<Size: ExtInt + Halveable, I: Iterator<Item = Size>>(iterator: I) -> RB<Size> {
let mut rb = new();
rb.extend(iterator);
rb
}

#[inline]
pub fn from_iter_ref<'a, I: Iterator<Item = &'a u32>>(iterator: I) -> RB {
pub fn from_iter_ref<'a, Size: ExtInt + Halveable + 'a, I: Iterator<Item = &'a Size>>(iterator: I) -> RB<Size> {
let mut rb = new();
rb.extend(iterator);
rb
}

#[inline]
pub fn extend<I: Iterator<Item = u32>>(this: &mut RB, mut iterator: I) {
pub fn extend<Size: ExtInt + Halveable, I: Iterator<Item = Size>>(this: &mut RB<Size>, mut iterator: I) {
for value in iterator {
this.insert(value);
}
}

#[inline]
pub fn extend_ref<'a, I: Iterator<Item = &'a u32>>(this: &mut RB, mut iterator: I) {
pub fn extend_ref<'a, Size: ExtInt + Halveable + 'a, I: Iterator<Item = &'a Size>>(this: &mut RB<Size>, mut iterator: I) {
for value in iterator {
this.insert(*value);
}
}

pub fn min(this: &RB) -> u32 {
pub fn min<Size: ExtInt + Halveable>(this: &RB<Size>) -> Size {
match &this.containers[] {
[ref head, ..] => calc(head.key(), head.min()),
[] => u32::MIN,
[ref head, ..] => Halveable::join(head.key(), head.min()),
[] => Int::min_value(),
}
}

pub fn max(this: &RB) -> u32 {
pub fn max<Size: ExtInt + Halveable>(this: &RB<Size>) -> Size {
match &this.containers[] {
[.., ref tail] => calc(tail.key(), tail.max()),
[] => u32::MAX,
[.., ref tail] => Halveable::join(tail.key(), tail.max()),
[] => Int::max_value(),
}
}

#[inline]
fn calc(key: u16, value: u16) -> u32 {
((key as u32) << u16::BITS) + (value as u32)
}

#[inline]
fn calc_loc(index: u32) -> (u16, u16) { ((index >> u16::BITS) as u16, index as u16) }

struct Pairs<'a> {
iter1: slice::Iter<'a, Container<u16>>,
iter2: slice::Iter<'a, Container<u16>>,
current1: Option<&'a Container<u16>>,
current2: Option<&'a Container<u16>>,
struct Pairs<'a, Size: ExtInt + Halveable + 'a> where <Size as Halveable>::HalfSize : 'a {
iter1: slice::Iter<'a, Container<<Size as Halveable>::HalfSize>>,
iter2: slice::Iter<'a, Container<<Size as Halveable>::HalfSize>>,
current1: Option<&'a Container<<Size as Halveable>::HalfSize>>,
current2: Option<&'a Container<<Size as Halveable>::HalfSize>>,
}

impl<'a> Pairs<'a> {
fn new(mut iter1: slice::Iter<'a, Container<u16>>, mut iter2: slice::Iter<'a, Container<u16>>) -> Pairs<'a> {
impl<'a, Size: ExtInt + Halveable> Pairs<'a, Size> {
fn new(mut iter1: slice::Iter<'a, Container<<Size as Halveable>::HalfSize>>, mut iter2: slice::Iter<'a, Container<<Size as Halveable>::HalfSize>>) -> Pairs<'a, Size> {
Pairs {
iter1: iter1,
iter2: iter2,
Expand All @@ -241,10 +237,10 @@ impl<'a> Pairs<'a> {
}
}

impl<'a> Iterator for Pairs<'a> {
type Item = (Option<&'a Container<u16>>, Option<&'a Container<u16>>);
impl<'a, Size: ExtInt + Halveable> Iterator for Pairs<'a, Size> {
type Item = (Option<&'a Container<<Size as Halveable>::HalfSize>>, Option<&'a Container<<Size as Halveable>::HalfSize>>);

fn next(&mut self) -> Option<(Option<&'a Container<u16>>, Option<&'a Container<u16>>)> {
fn next(&mut self) -> Option<(Option<&'a Container<<Size as Halveable>::HalfSize>>, Option<&'a Container<<Size as Halveable>::HalfSize>>)> {
match (self.current1, self.current2) {
(None, None) => None,
(Some(c1), None) => {
Expand Down Expand Up @@ -274,21 +270,3 @@ impl<'a> Iterator for Pairs<'a> {
}
}
}

#[cfg(test)]
mod test {
use std::{ u16, u32 };
use super::{ calc_loc };

#[test]
fn test_calc_location() {
assert_eq!((0, 0), calc_loc(0));
assert_eq!((0, 1), calc_loc(1));
assert_eq!((0, u16::MAX - 1), calc_loc(u16::MAX as u32 - 1));
assert_eq!((0, u16::MAX), calc_loc(u16::MAX as u32));
assert_eq!((1, 0), calc_loc(u16::MAX as u32 + 1));
assert_eq!((1, 1), calc_loc(u16::MAX as u32 + 2));
assert_eq!((u16::MAX, u16::MAX - 1), calc_loc(u32::MAX - 1));
assert_eq!((u16::MAX, u16::MAX), calc_loc(u32::MAX));
}
}
Loading

0 comments on commit ffd76c8

Please sign in to comment.