Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make append O(N) #132

Merged
merged 12 commits into from
Jan 12, 2022
12 changes: 12 additions & 0 deletions src/bitmap/container.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,18 @@ impl Container {
}
}

///
/// Pushes `index` at the end of the container.
/// It is up to the caller to have validated index > self.max()
///
/// # Panics
///
/// If debug_assertions enabled and index is > self.max()
pub(crate) fn push_unchecked(&mut self, index: u16) {
self.store.push_unchecked(index);
self.ensure_correct_store();
}

pub fn remove(&mut self, index: u16) -> bool {
if self.store.remove(index) {
self.ensure_correct_store();
Expand Down
23 changes: 23 additions & 0 deletions src/bitmap/inherent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,29 @@ impl RoaringBitmap {
}
}

///
/// Pushes `value` at the end of the bitmap.
/// It is up to the caller to have validated index > self.max()
///
/// # Panics
///
/// If debug_assertions enabled and index is > self.max()
pub(crate) fn push_unchecked(&mut self, value: u32) {
Kerollmops marked this conversation as resolved.
Show resolved Hide resolved
let (key, index) = util::split(value);

match self.containers.last_mut() {
Some(container) if container.key == key => container.push_unchecked(index),
Some(container) if cfg!(debug_assertions) && container.key > key => {
panic!("last container key > key of value")
}
_otherwise => {
let mut container = Container::new(key);
container.push_unchecked(index);
self.containers.push(container);
}
}
}

/// Removes a value from the set. Returns `true` if the value was present in the set.
///
/// # Examples
Expand Down
26 changes: 11 additions & 15 deletions src/bitmap/iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -187,30 +187,26 @@ impl RoaringBitmap {
// Name shadowed to prevent accidentally referencing the param
let mut iterator = iterator.into_iter();

let mut prev: u32 = match iterator.next() {
None => return Ok(0),
Some(first) => {
if let Some(max) = self.max() {
if first <= max {
return Err(NonSortedIntegers { valid_until: 0 });
}
}

first
let mut prev = match (iterator.next(), self.max()) {
(None, _) => return Ok(0),
(Some(first), Some(max)) if first <= max => {
return Err(NonSortedIntegers { valid_until: 0 })
}
(Some(first), _) => first,
};

self.insert(prev);
let mut count = 1;
// It is now guaranteed that so long as the values of the iterator are
// monotonically increasing they must also be the greatest in the set.

self.push_unchecked(prev);

// It is now guaranteed that so long as the values are iterator are monotonically
// increasing they must also be the greatest in the set.
let mut count = 1;

for value in iterator {
if value <= prev {
return Err(NonSortedIntegers { valid_until: count });
} else {
self.insert(value);
self.push_unchecked(value);
prev = value;
count += 1;
}
Expand Down
16 changes: 16 additions & 0 deletions src/bitmap/store/array_store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,22 @@ impl ArrayStore {
}
}

///
/// Pushes `index` at the end of the store.
/// It is up to the caller to have validated index > self.max()
///
/// # Panics
///
/// If debug_assertions enabled and index is > self.max()
pub(crate) fn push_unchecked(&mut self, index: u16) {
if cfg!(debug_assertions) {
if let Some(max) = self.max() {
assert!(index > max, "store max >= index")
}
}
self.vec.push(index);
}

pub fn remove(&mut self, index: u16) -> bool {
self.vec.binary_search(&index).map(|loc| self.vec.remove(loc)).is_ok()
}
Expand Down
16 changes: 16 additions & 0 deletions src/bitmap/store/bitmap_store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,22 @@ impl BitmapStore {
}
}

///
/// Pushes `index` at the end of the store.
/// It is up to the caller to have validated index > self.max()
///
/// # Panics
///
/// If debug_assertions enabled and index is > self.max()
pub(crate) fn push_unchecked(&mut self, index: u16) {
if cfg!(debug_assertions) {
if let Some(max) = self.max() {
assert!(index > max, "store max >= index")
}
}
self.insert(index);
}

pub fn remove(&mut self, index: u16) -> bool {
let (key, bit) = (key(index), bit(index));
let old_w = self.bits[key];
Expand Down
14 changes: 14 additions & 0 deletions src/bitmap/store/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,20 @@ impl Store {
}
}

///
/// Pushes `index` at the end of the store.
/// It is up to the caller to have validated index > self.max()
///
/// # Panics
///
/// If debug_assertions enabled and index is > self.max()
pub(crate) fn push_unchecked(&mut self, index: u16) {
match self {
Array(vec) => vec.push_unchecked(index),
Bitmap(bits) => bits.push_unchecked(index),
}
}

pub fn remove(&mut self, index: u16) -> bool {
match *self {
Array(ref mut vec) => vec.remove(index),
Expand Down
24 changes: 24 additions & 0 deletions src/treemap/inherent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,30 @@ impl RoaringTreemap {
self.map.entry(hi).or_insert_with(RoaringBitmap::new).push(lo)
}

///
/// Pushes `value` in the treemap only if it is greater than the current maximum value.
/// It is up to the caller to have validated index > self.max()
///
/// # Panics
///
/// If debug_assertions enabled and index is > self.max()
pub(crate) fn push_unchecked(&mut self, value: u64) {
Kerollmops marked this conversation as resolved.
Show resolved Hide resolved
let (hi, lo) = util::split(value);
// BTreeMap last_mut not stabilized see https://github.com/rust-lang/rust/issues/62924
match self.map.iter_mut().next_back() {
Some((&key, bitmap)) if key == hi => bitmap.push_unchecked(lo),
Some((&key, _)) if cfg!(debug_assertions) && key > hi => {
panic!("last bitmap key > key of value")
}
_otherwise => {
// The tree is empty
let mut rb = RoaringBitmap::new();
rb.push_unchecked(lo);
self.map.insert(hi, rb);
}
}
}

/// Removes a value from the set. Returns `true` if the value was present in the set.
///
/// # Examples
Expand Down
23 changes: 19 additions & 4 deletions src/treemap/iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -255,13 +255,28 @@ impl RoaringTreemap {
&mut self,
iterator: I,
) -> Result<u64, NonSortedIntegers> {
let mut count = 0;
let mut iterator = iterator.into_iter();
let mut prev = match (iterator.next(), self.max()) {
(None, _) => return Ok(0),
(Some(first), Some(max)) if first <= max => {
return Err(NonSortedIntegers { valid_until: 0 })
}
(Some(first), _) => first,
};

// It is now guaranteed that so long as the values of the iterator are
// monotonically increasing they must also be the greatest in the set.

self.push_unchecked(prev);

let mut count = 1;
for value in iterator {
if self.push(value) {
count += 1;
} else {
if value <= prev {
return Err(NonSortedIntegers { valid_until: count });
} else {
self.push_unchecked(value);
prev = value;
count += 1;
}
}

Expand Down