From f6a3dc0d5b6e8ad34d69929e37139a67e8de9e0f Mon Sep 17 00:00:00 2001 From: Moritz Hoffmann Date: Fri, 8 Nov 2024 17:05:45 +0100 Subject: [PATCH] progress --- src/bitmap.rs | 188 +++++++++++++++++++++++++ src/impls.rs | 3 +- src/impls/option.rs | 141 ++++++++++++++----- src/impls/tuple.rs | 56 ++++---- src/lib.rs | 335 +++++++++++++++++++++++++------------------- src/primitive.rs | 60 ++++++++ src/rank_select.rs | 182 ++++++++++++++++++++++++ 7 files changed, 756 insertions(+), 209 deletions(-) create mode 100644 src/bitmap.rs create mode 100644 src/primitive.rs create mode 100644 src/rank_select.rs diff --git a/src/bitmap.rs b/src/bitmap.rs new file mode 100644 index 0000000..ba004c7 --- /dev/null +++ b/src/bitmap.rs @@ -0,0 +1,188 @@ +//! Bitmaps + +use crate::{Clear, HeapSize, Index, IndexAs, Len, Push, Region, Reserve, ReserveItems}; +use serde::{Deserialize, Serialize}; + +/// TODO +#[derive(Default, Clone, Debug)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +pub struct Bools> { + values: V, + last_word: u64, + last_bits: u8, +} + +impl> Bools { + /// Number of blocks in the bitmap. + #[inline(always)] + pub fn blocks(&self) -> usize { + self.values.len() + (self.last_bits > 0) as usize + } + + /// Value of the last block. + #[inline(always)] + pub fn last_block(&self) -> (u64, u8) { + if self.last_bits > 0 || self.values.is_empty() { + (self.last_word, self.last_bits) + } else { + (self.values.index_as(self.values.len() - 1), 64) + } + } + + /// Value of the block at the given index. + pub fn block(&self, index: usize) -> (u64, u8) { + if index == self.values.len() { + (self.last_word, self.last_bits) + } else { + (self.values.index_as(index), 64) + } + } +} + +impl Len for Bools { + #[inline(always)] + fn len(&self) -> usize { + self.values.len() * 64 + self.last_bits as usize + } +} + +impl Clear for Bools { + #[inline(always)] + fn clear(&mut self) { + self.values.clear(); + self.last_word = 0; + self.last_bits = 0; + } +} + +impl HeapSize for Bools { + fn heap_size(&self, callback: F) { + self.values.heap_size(callback); + } +} + +impl Region for Bools +where + V: Region, +{ + fn merge_regions<'a>(regions: impl Iterator + Clone) -> Self + where + Self: 'a, + { + Self { + values: V::merge_regions(regions.map(|r| &r.values)), + last_word: 0, + last_bits: 0, + } + } + + fn reserve_regions<'a, I>(&mut self, regions: I) + where + Self: 'a, + I: Iterator + Clone, + { + self.values.reserve_regions(regions.map(|r| &r.values)); + } +} + +impl ReserveItems for Bools +where + V: Reserve, +{ + fn reserve_items(&mut self, items: I) + where + I: Iterator + Clone, + { + self.values.reserve((items.count() + 63) / 64); + } +} + +impl Index for Bools +where + V: Len + IndexAs, +{ + type Owned = bool; + type ReadItem<'a> = bool where Self: 'a; + + fn index(&self, index: usize) -> Self::ReadItem<'_> { + let block = index / 64; + let word = if block == self.values.len() { + self.last_word + } else { + self.values.index_as(block) + }; + let bit = index % 64; + word & (1 << bit) != 0 + } + + fn reborrow<'b, 'a: 'b>(item: Self::ReadItem<'a>) -> Self::ReadItem<'b> + where + Self: 'a, + { + item + } +} + +impl IndexAs for Bools +where + V: IndexAs + Len, +{ + #[inline(always)] + fn index_as(&self, index: usize) -> bool { + self.index(index) + } +} + +impl> Push for Bools { + #[inline(always)] + fn push(&mut self, item: bool) { + self.last_word |= (item as u64) << self.last_bits; + self.last_bits += 1; + // If we have filled the last word, push it to the values and reset the last word + if self.last_bits == 64 { + self.values.push(self.last_word); + self.last_word = 0; + self.last_bits = 0; + } + } +} + +impl Push<&bool> for Bools +where + Self: Push, +{ + #[inline(always)] + fn push(&mut self, item: &bool) { + self.push(*item); + } +} + +#[cfg(test)] +mod tests { + use crate::{Index, Push}; + + use super::*; + + #[test] + fn test_bitmap() { + let mut bitmap = ::default(); + for i in 0..100 { + bitmap.push(i % 2 == 0); + } + assert_eq!(bitmap.len(), 100); + for i in 0..100 { + assert_eq!(bitmap.index(i), i % 2 == 0); + } + + let mut bitmap = ::default(); + assert_eq!((0, 0), bitmap.last_block()); + bitmap.push(true); + assert_eq!((0b1, 1), bitmap.last_block()); + for _ in 0..63 { + bitmap.push(false); + } + bitmap.push(true); + assert_eq!((0b1, 1), bitmap.last_block()); + assert_eq!((0b1, 64), bitmap.block(0)); + } +} diff --git a/src/impls.rs b/src/impls.rs index 93b43ac..9380937 100644 --- a/src/impls.rs +++ b/src/impls.rs @@ -6,11 +6,10 @@ // pub mod huffman_container; // pub mod index; // pub mod mirror; -// pub mod option; +pub mod option; // pub mod result; pub mod slice; pub mod slice_owned; -// pub mod storage; pub mod string; pub mod tuple; mod vec; diff --git a/src/impls/option.rs b/src/impls/option.rs index ec518b6..47f681a 100644 --- a/src/impls/option.rs +++ b/src/impls/option.rs @@ -3,11 +3,14 @@ #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; -use crate::{IntoOwned, Push, Region, RegionPreference, ReserveItems}; +use crate::rank_select::RankSelect; +use crate::{ + Clear, HeapSize, Index, IndexAs, IntoOwned, Len, Push, Region, RegionPreference, ReserveItems, +}; impl RegionPreference for Option { type Owned = Option; - type Region = OptionRegion; + type Region = OptionRegion, Vec>; } /// A region to hold [`Option`]s. @@ -16,25 +19,27 @@ impl RegionPreference for Option { /// /// The region can hold options: /// ``` -/// # use flatcontainer::{RegionPreference, Push, OptionRegion, Region}; +/// # use flatcontainer::{RegionPreference, Push, OptionRegion, Index}; /// let mut r = ::Region>>::default(); /// -/// let some_index = r.push(Some(123)); +/// r.push(Some(123)); /// // Type annotations required for `None`: -/// let none_index = r.push(Option::::None); +/// r.push(Option::::None); /// -/// assert_eq!(Some(123), r.index(some_index)); -/// assert_eq!(None, r.index(none_index)); +/// assert_eq!(Some(&123), r.index(0)); +/// assert_eq!(None, r.index(1)); /// ``` #[derive(Default, Debug)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -pub struct OptionRegion { +pub struct OptionRegion, RV = Vec> { + ranks: RankSelect, inner: R, } -impl Clone for OptionRegion { +impl Clone for OptionRegion { fn clone(&self) -> Self { Self { + ranks: self.ranks.clone(), inner: self.inner.clone(), } } @@ -44,43 +49,76 @@ impl Clone for OptionRegion { } } -impl Region for OptionRegion { - type Owned = Option; - type ReadItem<'a> = Option<::ReadItem<'a>> where Self: 'a; - type Index = Option; - +impl Region for OptionRegion { #[inline] fn merge_regions<'a>(regions: impl Iterator + Clone) -> Self where Self: 'a, { Self { + ranks: RankSelect::merge_regions(regions.clone().map(|r| &r.ranks)), inner: R::merge_regions(regions.map(|r| &r.inner)), } } - #[inline] - fn index(&self, index: Self::Index) -> Self::ReadItem<'_> { - index.map(|t| self.inner.index(t)) - } - #[inline] fn reserve_regions<'a, I>(&mut self, regions: I) where Self: 'a, I: Iterator + Clone, { + self.ranks + .reserve_regions(regions.clone().map(|r| &r.ranks)); self.inner.reserve_regions(regions.map(|r| &r.inner)); } +} - #[inline] +impl HeapSize for OptionRegion +where + R: HeapSize, + RC: HeapSize, + RV: HeapSize, +{ + fn heap_size(&self, mut callback: F) { + self.ranks.heap_size(&mut callback); + self.inner.heap_size(callback); + } +} + +impl Clear for OptionRegion +where + R: Clear, + RC: Clear, + RV: Clear, +{ fn clear(&mut self) { + self.ranks.clear(); self.inner.clear(); } +} + +impl Len for OptionRegion { + fn len(&self) -> usize { + self.ranks.len() + } +} + +impl Index for OptionRegion +where + R: Index, + RC: IndexAs + Len, + RV: IndexAs + Len, +{ + type Owned = Option; + type ReadItem<'a> = Option<::ReadItem<'a>> where Self: 'a; #[inline] - fn heap_size(&self, callback: F) { - self.inner.heap_size(callback); + fn index(&self, index: usize) -> Self::ReadItem<'_> { + if self.ranks.index_as(index) { + Some(self.inner.index(self.ranks.rank(index))) + } else { + None + } } #[inline] @@ -118,27 +156,47 @@ where } } -impl Push> for OptionRegion +impl Push> for OptionRegion where - TR: Region + Push, + TR: Push, + RC: IndexAs + Len + Push, + RV: IndexAs + Len + Push, { #[inline] - fn push(&mut self, item: Option) -> as Region>::Index { - item.map(|t| self.inner.push(t)) + fn push(&mut self, item: Option) { + match item { + Some(t) => { + self.ranks.push(true); + self.inner.push(t); + } + None => { + self.ranks.push(false); + } + } } } -impl<'a, T: 'a, TR> Push<&'a Option> for OptionRegion +impl<'a, T: 'a, TR, RC, RV> Push<&'a Option> for OptionRegion where - TR: Region + Push<&'a T>, + TR: Push<&'a T>, + RC: IndexAs + Len + Push, + RV: IndexAs + Len + Push, { #[inline] - fn push(&mut self, item: &'a Option) -> as Region>::Index { - item.as_ref().map(|t| self.inner.push(t)) + fn push(&mut self, item: &'a Option) { + match item { + Some(t) => { + self.ranks.push(true); + self.inner.push(t); + } + None => { + self.ranks.push(false); + } + } } } -impl ReserveItems> for OptionRegion +impl ReserveItems> for OptionRegion where TR: Region + ReserveItems, { @@ -154,7 +212,7 @@ where } } -impl<'a, T: 'a, TR> ReserveItems<&'a Option> for OptionRegion +impl<'a, T: 'a, TR, RC, RV> ReserveItems<&'a Option> for OptionRegion where TR: Region + ReserveItems<&'a T>, { @@ -169,13 +227,13 @@ where #[cfg(test)] mod tests { - use crate::{MirrorRegion, OwnedRegion, Region, ReserveItems}; + use crate::{OwnedRegion, ReserveItems}; use super::*; #[test] fn test_reserve() { - let mut r = >>::default(); + let mut r = >>::default(); ReserveItems::reserve_items(&mut r, [Some(0), None].iter()); ReserveItems::reserve_items(&mut r, [Some(0), None].into_iter()); @@ -184,11 +242,24 @@ mod tests { #[test] fn test_heap_size() { let mut r = >>::default(); - ReserveItems::reserve_items(&mut r, [Some([1; 1]), None].iter()); + ReserveItems::reserve_items( + &mut r, + std::iter::once(Some(&[1; 1])).chain(std::iter::repeat_n(None, 1000)), + ); let mut cap = 0; r.heap_size(|_, ca| { cap += ca; }); assert!(cap > 0); + for item in std::iter::once(Some(&[1; 1])).chain(std::iter::repeat_n(None, 10000)) { + r.push(item); + } + let mut siz = 0; + r.heap_size(|s, _| { + siz += s; + }); + assert!(siz > 0); + println!("{siz}"); + println!("{r:?}") } } diff --git a/src/impls/tuple.rs b/src/impls/tuple.rs index 709bae0..0683908 100644 --- a/src/impls/tuple.rs +++ b/src/impls/tuple.rs @@ -4,7 +4,7 @@ use paste::paste; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; -use crate::{IntoOwned, Push, Region, RegionPreference, ReserveItems, Clear, Len, HeapSize, Index}; +use crate::{Clear, HeapSize, Index, IntoOwned, Len, Push, Region, RegionPreference, ReserveItems}; /// The macro creates the region implementation for tuples macro_rules! tuple_flatcontainer { @@ -86,14 +86,17 @@ macro_rules! tuple_flatcontainer { } #[allow(non_snake_case)] + #[allow(unused_variables)] impl<$($name: Len),*> Len for []<$($name),*> { #[inline(always)] fn len(&self) -> usize { - self.0.len() + $(let len = self.[].len();)* + len } #[inline(always)] fn is_empty(&self) -> bool { - self.0.is_empty() + $(let is_empty = self.[].is_empty();)* + is_empty } } @@ -249,44 +252,45 @@ cfg_if::cfg_if! { #[cfg(test)] mod tests { - use crate::impls::tuple::TupleABCRegion; - use crate::{Push, Region, StringRegion}; + use crate::{Push, StringRegion}; + + use super::*; #[test] fn test_tuple() { let t = (1, 2, 3); let mut r = , Vec<_>, Vec<_>>>::default(); - let index = r.push(t); - assert_eq!(t, r.index(index)); + r.push(t); + assert_eq!((&1, &2, &3), r.index(0)); - let index = r.push((&1, &2, &3)); - assert_eq!(t, r.index(index)); + r.push((&1, &2, &4)); + assert_eq!((&1, &2, &4), r.index(1)); - let index = r.push((&1, 2, 3)); - assert_eq!(t, r.index(index)); + r.push((&1, 2, 5)); + assert_eq!((&1, &2, &5), r.index(2)); - let index = r.push(&(1, 2, 3)); - assert_eq!(t, r.index(index)); + r.push(&(1, 2, 6)); + assert_eq!((&1, &2, &6), r.index(3)); - let index = r.push(&(1, &2, 3)); - assert_eq!(t, r.index(index)); + r.push(&(1, &2, 7)); + assert_eq!((&1, &2, &7), r.index(4)); } #[test] fn test_nested() { let t = ("abc", 2, 3); let mut r = , Vec<_>>>::default(); - let index = r.push(t); - assert_eq!(t, r.index(index)); + r.push(t); + assert_eq!(("abc", &2, &3), r.index(0)); - let index = r.push((&"abc", &2, &3)); - assert_eq!(t, r.index(index)); + r.push((&"abc", &2, &3)); + assert_eq!(("abc", &2, &3), r.index(1)); - let index = r.push((&"abc", 2, 3)); - assert_eq!(t, r.index(index)); + r.push((&"abc", 2, 3)); + assert_eq!(("abc", &2, &3), r.index(2)); - let index = r.push(&("abc", 2, 3)); - assert_eq!(t, r.index(index)); + r.push(&("abc", 2, 3)); + assert_eq!(("abc", &2, &3), r.index(3)); } #[test] @@ -311,10 +315,10 @@ mod tests { } #[test] fn test_reserve_items() { - let mut c = FlatStack::default_impl::<(usize, String, Vec)>(); - c.copy((1, format!("Hello"), &["abc"])); + let mut c = <(usize, String, Vec) as RegionPreference>::Region::default(); + c.push((1, format!("Hello"), &["abc"])); - let mut c2 = FlatStack::default_impl::<(usize, String, Vec)>(); + let mut c2 = <(usize, String, Vec) as RegionPreference>::Region::default(); c2.reserve_items(c.iter()); } } diff --git a/src/lib.rs b/src/lib.rs index 5b24e06..2c7c738 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,12 +3,16 @@ use std::borrow::Borrow; +mod bitmap; pub mod impls; +mod primitive; +mod rank_select; +// pub mod storage; // use crate::impls::index::IndexContainer; // pub use impls::columns::ColumnsRegion; // pub use impls::mirror::MirrorRegion; -// pub use impls::option::OptionRegion; +pub use impls::option::OptionRegion; // pub use impls::result::ResultRegion; pub use impls::slice::SliceRegion; pub use impls::slice_owned::OwnedRegion; @@ -444,154 +448,191 @@ pub trait Index { // { // item // } + + /// TODO + fn iter(&self) -> IntoIter<'_, Self> + where + Self: Len + Sized, + { + IntoIter { + index: 0, + region: self, + } + } +} + +#[derive(Clone, Copy, Debug)] +/// TODO +pub struct IntoIter<'a, R: Index + Len> { + /// TODO + index: usize, + /// TODO + region: &'a R, +} + +impl<'a, R: Index + Len> Iterator for IntoIter<'a, R> { + type Item = R::ReadItem<'a>; + + fn next(&mut self) -> Option { + if self.index < self.region.len() { + let item = self.region.index(self.index); + self.index += 1; + Some(item) + } else { + None + } + } } -/* #[cfg(test)] mod tests { - // use crate::impls::deduplicate::{CollapseSequence, ConsecutiveIndexPairs}; - // use crate::impls::tuple::TupleARegion; + use std::fmt::Debug; - use super::*; + use crate::impls::tuple::TupleARegion; - fn copy, T>(r: &mut R, item: T) -> R::Index { - r.push(item) - } + use super::*; - #[test] - fn test_readme() { - let r: Result<_, u16> = Ok("abc"); - let mut c = FlatStack::default_impl::>(); - c.copy(r); - assert_eq!(r, c.get(0)); - } + // #[test] + // fn test_readme() { + // let r: Result<_, u16> = Ok("abc"); + // let mut c = FlatStack::default_impl::>(); + // c.copy(r); + // assert_eq!(r, c.get(0)); + // } #[test] fn test_slice_string_onto() { let mut c = ::default(); - let index = c.push("abc".to_string()); - assert_eq!("abc", c.index(index)); - let index = c.push("def"); - assert_eq!("def", c.index(index)); + c.push("abc".to_string()); + assert_eq!("abc", c.index(0)); + c.push("def"); + assert_eq!("def", c.index(1)); } #[test] fn test_container_string() { - let mut c = FlatStack::default_impl::(); - c.copy(&"abc".to_string()); - assert_eq!("abc", c.get(0)); - c.copy("def"); - assert_eq!("def", c.get(1)); + let mut c = ::Region::default(); + c.push(&"abc".to_string()); + assert_eq!("abc", c.index(0)); + c.push("def"); + assert_eq!("def", c.index(1)); } #[test] fn test_vec() { - let mut c = >>::default(); + let mut c = >>::default(); let slice = &[1u8, 2, 3]; - let idx = c.push(slice); - assert!(slice.iter().copied().eq(c.index(idx))); + c.push(slice); + assert!(slice.iter().eq(c.index(0))); } #[test] fn test_vec_onto() { - let mut c = >>::default(); + let mut c = >>::default(); let slice = &[1u8, 2, 3][..]; - let idx = c.push(slice); - assert!(slice.iter().copied().eq(c.index(idx))); + c.push(slice); + assert!(slice.iter().eq(c.index(0))); } - #[test] - fn test_result() { - let r: Result<_, u16> = Ok("abc"); - let mut c = >>::default(); - let idx = copy(&mut c, r); - assert_eq!(r, c.index(idx)); - } + // #[test] + // fn test_result() { + // let r: Result<_, u16> = Ok("abc"); + // let mut c = >>::default(); + // let idx = copy(&mut c, r); + // assert_eq!(r, c.index(idx)); + // } #[test] fn all_types() { - fn test_copy(t: T) + fn test_copy(t: T) where - for<'a> R: Push + Push<::ReadItem<'a>>, + for<'a> R: Region + + Default + + Push + + Push<::ReadItem<'a>> + + Index + + Clone + + Clear + + HeapSize + Len, // Make sure that types are debug, even if we don't use this in the test. for<'a> R::ReadItem<'a>: Debug, { - let mut c = FlatStack::<_>::default(); - c.copy(t); + let mut c = R::default(); + c.push(t); let mut cc = c.clone(); - cc.copy(c.get(0)); + cc.push(c.index(0)); c.clear(); let mut r = R::default(); - let _ = r.push(cc.get(0)); + let _ = r.push(cc.index(0)); c.reserve_regions(std::iter::once(&r)); - let mut c = FlatStack::merge_capacity(std::iter::once(&c)); - c.copy(cc.get(0)); + let mut c = R::merge_regions(std::iter::once(&c)); + c.push(cc.index(0)); } test_copy::<_, StringRegion>(&"a".to_string()); test_copy::<_, StringRegion>("a".to_string()); test_copy::<_, StringRegion>("a"); - test_copy::<_, MirrorRegion<()>>(()); - test_copy::<_, MirrorRegion<()>>(&()); - test_copy::<_, MirrorRegion>(true); - test_copy::<_, MirrorRegion>(&true); - test_copy::<_, MirrorRegion>(' '); - test_copy::<_, MirrorRegion>(&' '); - test_copy::<_, MirrorRegion>(0u8); - test_copy::<_, MirrorRegion>(&0u8); - test_copy::<_, MirrorRegion>(0u16); - test_copy::<_, MirrorRegion>(&0u16); - test_copy::<_, MirrorRegion>(0u32); - test_copy::<_, MirrorRegion>(&0u32); - test_copy::<_, MirrorRegion>(0u64); - test_copy::<_, MirrorRegion>(&0u64); - test_copy::<_, MirrorRegion>(0u128); - test_copy::<_, MirrorRegion>(&0u128); - test_copy::<_, MirrorRegion>(0usize); - test_copy::<_, MirrorRegion>(&0usize); - test_copy::<_, MirrorRegion>(0i8); - test_copy::<_, MirrorRegion>(&0i8); - test_copy::<_, MirrorRegion>(0i16); - test_copy::<_, MirrorRegion>(&0i16); - test_copy::<_, MirrorRegion>(0i32); - test_copy::<_, MirrorRegion>(&0i32); - test_copy::<_, MirrorRegion>(0i64); - test_copy::<_, MirrorRegion>(&0i64); - test_copy::<_, MirrorRegion>(0i128); - test_copy::<_, MirrorRegion>(&0i128); - test_copy::<_, MirrorRegion>(0isize); - test_copy::<_, MirrorRegion>(&0isize); - test_copy::<_, MirrorRegion>(0f32); - test_copy::<_, MirrorRegion>(&0f32); - test_copy::<_, MirrorRegion>(0f64); - test_copy::<_, MirrorRegion>(&0f64); - test_copy::<_, MirrorRegion>>(std::num::Wrapping(0i8)); - test_copy::<_, MirrorRegion>>(&std::num::Wrapping(0i8)); - test_copy::<_, MirrorRegion>>(std::num::Wrapping(0i16)); - test_copy::<_, MirrorRegion>>(&std::num::Wrapping(0i16)); - test_copy::<_, MirrorRegion>>(std::num::Wrapping(0i32)); - test_copy::<_, MirrorRegion>>(&std::num::Wrapping(0i32)); - test_copy::<_, MirrorRegion>>(std::num::Wrapping(0i64)); - test_copy::<_, MirrorRegion>>(&std::num::Wrapping(0i64)); - test_copy::<_, MirrorRegion>>(std::num::Wrapping(0i128)); - test_copy::<_, MirrorRegion>>(&std::num::Wrapping(0i128)); - test_copy::<_, MirrorRegion>>(std::num::Wrapping(0isize)); - test_copy::<_, MirrorRegion>>(&std::num::Wrapping(0isize)); - - test_copy::<_, ResultRegion, MirrorRegion>>(Result::::Ok(0)); - test_copy::<_, ResultRegion, MirrorRegion>>(&Result::::Ok(0)); - test_copy::<_, ResultRegion, MirrorRegion>>(Result::::Err(0)); - test_copy::<_, ResultRegion, MirrorRegion>>(&Result::::Err(0)); - - test_copy::<_, SliceRegion>>([0u8].as_slice()); - test_copy::<_, SliceRegion>>(vec![0u8]); - test_copy::<_, SliceRegion>>(&vec![0u8]); + // test_copy::<_, MirrorRegion<()>>(()); + // test_copy::<_, MirrorRegion<()>>(&()); + // test_copy::<_, MirrorRegion>(true); + // test_copy::<_, MirrorRegion>(&true); + // test_copy::<_, MirrorRegion>(' '); + // test_copy::<_, MirrorRegion>(&' '); + // test_copy::<_, MirrorRegion>(0u8); + // test_copy::<_, MirrorRegion>(&0u8); + // test_copy::<_, MirrorRegion>(0u16); + // test_copy::<_, MirrorRegion>(&0u16); + // test_copy::<_, MirrorRegion>(0u32); + // test_copy::<_, MirrorRegion>(&0u32); + // test_copy::<_, MirrorRegion>(0u64); + // test_copy::<_, MirrorRegion>(&0u64); + // test_copy::<_, MirrorRegion>(0u128); + // test_copy::<_, MirrorRegion>(&0u128); + // test_copy::<_, MirrorRegion>(0usize); + // test_copy::<_, MirrorRegion>(&0usize); + // test_copy::<_, MirrorRegion>(0i8); + // test_copy::<_, MirrorRegion>(&0i8); + // test_copy::<_, MirrorRegion>(0i16); + // test_copy::<_, MirrorRegion>(&0i16); + // test_copy::<_, MirrorRegion>(0i32); + // test_copy::<_, MirrorRegion>(&0i32); + // test_copy::<_, MirrorRegion>(0i64); + // test_copy::<_, MirrorRegion>(&0i64); + // test_copy::<_, MirrorRegion>(0i128); + // test_copy::<_, MirrorRegion>(&0i128); + // test_copy::<_, MirrorRegion>(0isize); + // test_copy::<_, MirrorRegion>(&0isize); + // test_copy::<_, MirrorRegion>(0f32); + // test_copy::<_, MirrorRegion>(&0f32); + // test_copy::<_, MirrorRegion>(0f64); + // test_copy::<_, MirrorRegion>(&0f64); + // test_copy::<_, MirrorRegion>>(std::num::Wrapping(0i8)); + // test_copy::<_, MirrorRegion>>(&std::num::Wrapping(0i8)); + // test_copy::<_, MirrorRegion>>(std::num::Wrapping(0i16)); + // test_copy::<_, MirrorRegion>>(&std::num::Wrapping(0i16)); + // test_copy::<_, MirrorRegion>>(std::num::Wrapping(0i32)); + // test_copy::<_, MirrorRegion>>(&std::num::Wrapping(0i32)); + // test_copy::<_, MirrorRegion>>(std::num::Wrapping(0i64)); + // test_copy::<_, MirrorRegion>>(&std::num::Wrapping(0i64)); + // test_copy::<_, MirrorRegion>>(std::num::Wrapping(0i128)); + // test_copy::<_, MirrorRegion>>(&std::num::Wrapping(0i128)); + // test_copy::<_, MirrorRegion>>(std::num::Wrapping(0isize)); + // test_copy::<_, MirrorRegion>>(&std::num::Wrapping(0isize)); + // + // test_copy::<_, ResultRegion, MirrorRegion>>(Result::::Ok(0)); + // test_copy::<_, ResultRegion, MirrorRegion>>(&Result::::Ok(0)); + // test_copy::<_, ResultRegion, MirrorRegion>>(Result::::Err(0)); + // test_copy::<_, ResultRegion, MirrorRegion>>(&Result::::Err(0)); + // + // test_copy::<_, SliceRegion>>([0u8].as_slice()); + // test_copy::<_, SliceRegion>>(vec![0u8]); + // test_copy::<_, SliceRegion>>(&vec![0u8]); test_copy::<_, SliceRegion>(["a"].as_slice()); test_copy::<_, SliceRegion>(vec!["a"]); @@ -607,89 +648,92 @@ mod tests { test_copy::<_, <(u8, u8) as RegionPreference>::Region>((1, 2)); test_copy::<_, <(u8, u8) as RegionPreference>::Region>(&(1, 2)); - test_copy::<_, ConsecutiveIndexPairs>>([1, 2, 3].as_slice()); + // test_copy::<_, ConsecutiveIndexPairs>>([1, 2, 3].as_slice()); - test_copy::<_, CollapseSequence>>([1, 2, 3].as_slice()); - test_copy::<_, CollapseSequence>>(&[1, 2, 3]); + // test_copy::<_, CollapseSequence>>([1, 2, 3].as_slice()); + // test_copy::<_, CollapseSequence>>(&[1, 2, 3]); test_copy::<_, OptionRegion>(Some("abc")); test_copy::<_, OptionRegion>(&Some("abc")); test_copy::<_, OptionRegion>(Option::<&'static str>::None); test_copy::<_, OptionRegion>(&Option::<&'static str>::None); - test_copy::<_, ResultRegion>>( - Result::<&'static str, u8>::Ok("abc"), - ); - test_copy::<_, ResultRegion>>( - &Result::<&'static str, u8>::Ok("abc"), - ); - test_copy::<_, ResultRegion>>( - Result::<&'static str, u8>::Err(1), - ); - test_copy::<_, ResultRegion>>( - Result::<&'static str, u8>::Err(2), - ); + // test_copy::<_, ResultRegion>>( + // Result::<&'static str, u8>::Ok("abc"), + // ); + // test_copy::<_, ResultRegion>>( + // &Result::<&'static str, u8>::Ok("abc"), + // ); + // test_copy::<_, ResultRegion>>( + // Result::<&'static str, u8>::Err(1), + // ); + // test_copy::<_, ResultRegion>>( + // Result::<&'static str, u8>::Err(2), + // ); } #[test] fn slice_region_read_item() { fn is_clone(_: &T) {} - let mut c = FlatStack::>>::default(); - c.copy(vec![1, 2, 3]); + let mut c = >>::default(); + c.push(vec![1, 2, 3]); - let mut r = SliceRegion::>::default(); - let idx = r.push([1, 2, 3]); - let read_item = r.index(idx); + let mut r = SliceRegion::>::default(); + r.push([1, 2, 3]); + let read_item = r.index(0); is_clone(&read_item); let _read_item3 = read_item; - assert_eq!(vec![1, 2, 3], read_item.into_iter().collect::>()); + assert_eq!( + vec![1, 2, 3], + read_item.into_iter().copied().collect::>() + ); } #[test] fn nested_slice_copy() { - let mut c = FlatStack::default_impl::<[[[[[u8; 1]; 1]; 1]; 1]; 1]>(); - - c.copy([[[[[1]]]]]); - c.copy(&[[[[[1]]]]]); - c.copy(&[[[[[&1]]]]]); - c.copy([[[[[&1]]]]]); - c.copy([[&[[[&1]]]]]); - c.copy([[[[[1]]; 1]; 1]; 1]); - c.copy(&[[[[[1; 1]; 1]; 1]; 1]; 1]); - c.copy(&[[[[[&1; 1]; 1]; 1]; 1]; 1]); - c.copy([[[[[&1; 1]; 1]; 1]; 1]; 1]); - c.copy([[&[[[&1; 1]; 1]; 1]; 1]; 1]); - c.copy([[vec![[[1; 1]; 1]; 1]; 1]; 1]); - c.copy(&[[vec![[[1; 1]; 1]; 1]; 1]; 1]); - c.copy(&[[vec![[[&1; 1]; 1]; 1]; 1]; 1]); - c.copy([[[vec![[&1; 1]; 1]; 1]; 1]; 1]); - c.copy([[&vec![[[&1; 1]; 1]; 1]; 1]; 1]); + let mut c = <[[[[[u8; 1]; 1]; 1]; 1]; 1] as RegionPreference>::Region::default(); + + c.push([[[[[1]]]]]); + c.push(&[[[[[1]]]]]); + c.push(&[[[[[&1]]]]]); + c.push([[[[[&1]]]]]); + c.push([[&[[[&1]]]]]); + c.push([[[[[1]]; 1]; 1]; 1]); + c.push(&[[[[[1; 1]; 1]; 1]; 1]; 1]); + c.push(&[[[[[&1; 1]; 1]; 1]; 1]; 1]); + c.push([[[[[&1; 1]; 1]; 1]; 1]; 1]); + c.push([[&[[[&1; 1]; 1]; 1]; 1]; 1]); + c.push([[vec![[[1; 1]; 1]; 1]; 1]; 1]); + c.push(&[[vec![[[1; 1]; 1]; 1]; 1]; 1]); + c.push(&[[vec![[[&1; 1]; 1]; 1]; 1]; 1]); + c.push([[[vec![[&1; 1]; 1]; 1]; 1]; 1]); + c.push([[&vec![[[&1; 1]; 1]; 1]; 1]; 1]); } #[test] fn test_owned() { - fn owned_roundtrip(region: &mut R, index: R::Index) + fn owned_roundtrip(region: &mut R, index: usize) where - for<'a> R: Region + Push<<::ReadItem<'a> as IntoOwned<'a>>::Owned>, + for<'a> R: Index + Push<<::ReadItem<'a> as IntoOwned<'a>>::Owned> + Len, for<'a> R::ReadItem<'a>: IntoOwned<'a, Owned = O> + Eq + Debug, { let item = region.index(index); let owned = item.into_owned(); - let index2 = region.push(owned); + region.push(owned); let item = region.index(index); - assert_eq!(item, region.index(index2)); + assert_eq!(item, region.index(region.len() - 1)); } let mut c = ::default(); - let index = c.push("abc".to_string()); - owned_roundtrip::(&mut c, index); + c.push("abc".to_string()); + owned_roundtrip::(&mut c, 0); } /// Test that items and owned variants can be reborrowed to shorten their lifetimes. fn _test_reborrow(item: R::ReadItem<'_>, owned: &R::Owned) where - R: Region, + R: Index, for<'a> R::ReadItem<'a>: Eq, { // The following line requires `reborrow` because otherwise owned must outlive '_. @@ -704,4 +748,3 @@ mod tests { let _ = R::reborrow(item) == R::reborrow(IntoOwned::borrow_as(owned)); } } -*/ diff --git a/src/primitive.rs b/src/primitive.rs new file mode 100644 index 0000000..7e116bd --- /dev/null +++ b/src/primitive.rs @@ -0,0 +1,60 @@ +//! Support for primitive types. + +use crate::{IntoOwned, RegionPreference}; + +macro_rules! impl_region_preference { + ($($index_type:ty),*) => { + $( + impl RegionPreference for $index_type { + type Owned = Self; + type Region = Vec; + } + + impl<'a> IntoOwned<'a> for $index_type { + type Owned = $index_type; + + #[inline] + fn into_owned(self) -> Self::Owned { + self + } + + #[inline] + fn clone_onto(self, other: &mut Self::Owned) { + *other = self; + } + + #[inline] + fn borrow_as(owned: &'a Self::Owned) -> Self { + *owned + } + } + )* + }; +} + +impl_region_preference!( + u8, + u16, + u32, + u64, + u128, + usize, + i8, + i16, + i32, + i64, + i128, + isize, + f32, + f64, + char, + bool, + (), + std::num::Wrapping, + std::num::Wrapping, + std::num::Wrapping, + std::num::Wrapping, + std::num::Wrapping, + std::num::Wrapping, + std::time::Duration +); diff --git a/src/rank_select.rs b/src/rank_select.rs new file mode 100644 index 0000000..be37ea3 --- /dev/null +++ b/src/rank_select.rs @@ -0,0 +1,182 @@ +//! Rank select structures + +use crate::bitmap::Bools; +use crate::{Clear, HeapSize, Index, IndexAs, Len, Push, Region, Reserve, ReserveItems}; +use serde::{Deserialize, Serialize}; + +#[derive(Default, Clone, Debug)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +pub struct RankSelect, V = Vec> { + counts: C, + values: Bools, +} + +impl Region for RankSelect { + fn merge_regions<'a>(regions: impl Iterator + Clone) -> Self + where + Self: 'a, + { + Self { + counts: C::merge_regions(regions.clone().map(|r| &r.counts)), + values: Bools::merge_regions(regions.map(|r| &r.values)), + } + } + + fn reserve_regions<'a, I>(&mut self, regions: I) + where + Self: 'a, + I: Iterator + Clone, + { + self.counts + .reserve_regions(regions.clone().map(|r| &r.counts)); + self.values.reserve_regions(regions.map(|r| &r.values)); + } +} + +impl HeapSize for RankSelect +where + C: HeapSize, + V: HeapSize, +{ + fn heap_size(&self, mut callback: F) { + self.counts.heap_size(&mut callback); + self.values.heap_size(callback); + } +} + +impl Clear for RankSelect +where + C: Clear, + V: Clear, +{ + fn clear(&mut self) { + self.counts.clear(); + self.values.clear(); + } +} + +impl Len for RankSelect +where + V: Len, +{ + fn len(&self) -> usize { + self.values.len() + } +} + +impl RankSelect +where + C: IndexAs + Len, + V: IndexAs + Len, +{ + pub fn rank(&self, index: usize) -> usize { + let bit = index % 64; + let block = index / 64; + let chunk = block / 16; + let mut count = if chunk > 0 { + self.counts.index_as(chunk - 1) as usize + } else { + 0 + }; + for index in (chunk * 16)..block { + count += self.counts.index_as(index).count_ones() as usize; + } + let word = self.values.last_block().0; + let mask = (1 << bit) - 1; + let bits = word & mask; + count + bits.count_ones() as usize + } + + #[allow(unused)] + pub fn select(&self, rank: u64) -> Option { + let mut chunk = 0; + while chunk < self.counts.len() && self.counts.index_as(chunk) <= rank { + chunk += 1; + } + let mut count = if chunk < self.counts.len() { + self.counts.index_as(chunk) + } else { + 0 + }; + let mut block = chunk * 16; + while block < self.values.blocks() + && count + ::from(self.values.block(block).0.count_ones()) <= rank + { + count += ::from(self.values.block(block).0.count_ones()); + block += 1; + } + + let (last_word, last_bits) = self.values.last_block(); + for shift in 0..last_bits { + if last_word & (1 << shift) != 0 && count + 1 == rank { + return Some(block * 64 + shift as usize); + } + count += last_word & (1 << shift); + } + + None + } +} + +impl Push for RankSelect +where + C: Push + Len + IndexAs, + V: Push + Len + IndexAs, +{ + fn push(&mut self, item: bool) { + self.values.push(item); + while self.counts.len() < self.values.len() / 1024 { + let mut count = if self.counts.is_empty() { + 0 + } else { + self.counts.index_as(self.counts.len() - 1) + }; + let lower = self.counts.len() * 16; + let upper = lower + 16; + for index in lower..upper { + count += self.values.block(index).0.count_ones() as u64; + } + self.counts.push(count); + } + } +} + +impl IndexAs for RankSelect +where + V: IndexAs + Len, +{ + fn index_as(&self, index: usize) -> bool { + self.values.index(index) + } +} + +impl ReserveItems for RankSelect +where + C: Reserve, + V: Reserve, +{ + fn reserve_items(&mut self, items: I) + where + I: Iterator + Clone, + { + self.counts.reserve((items.clone().count() + 1023) / 1024); + self.values.reserve_items(items.clone()); + } +} + +#[cfg(test)] +mod tests { + use super::*; + #[test] + fn test_rank() { + let mut rs = ::default(); + rs.push(true); + assert_eq!(rs.rank(0), 0); + assert_eq!(rs.select(0), None); + assert_eq!(rs.select(1), None); + rs.push(true); + assert_eq!(rs.rank(0), 0); + assert_eq!(rs.select(0), None); + assert_eq!(rs.select(1), Some(0)); + } +}