diff --git a/benches/benches.rs b/benches/benches.rs index ac999b0..49eae4e 100644 --- a/benches/benches.rs +++ b/benches/benches.rs @@ -3,7 +3,7 @@ extern crate test; extern crate fixedbitset; use test::Bencher; -use fixedbitset::{FixedBitSet}; +use fixedbitset::{FixedBitSet, Block}; use std::mem::size_of; #[inline] @@ -18,8 +18,8 @@ fn iter_ones_using_contains(fb: &FixedBitSet, f: &mut F) { #[inline] fn iter_ones_using_slice_directly(fb: &FixedBitSet, f: &mut F) { for (block_idx, &block) in fb.as_slice().iter().enumerate() { - let mut bit_pos = block_idx * size_of::() * 8; - let mut block: u32 = block; + let mut bit_pos = block_idx * size_of::() * 8; + let mut block: Block = block; while block != 0 { if (block & 1) == 1 { diff --git a/src/lib.rs b/src/lib.rs index fb58e28..84f32f6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -37,12 +37,12 @@ use std::cmp::{Ord, Ordering}; use std::iter::{Chain, FromIterator}; use std::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Index}; -const BITS: usize = 32; -type Block = u32; +const BITS: usize = std::mem::size_of::() * 8; +pub type Block = usize; #[inline] -fn div_rem(x: usize, d: usize) -> (usize, usize) { - (x / d, x % d) +fn div_rem(x: usize) -> (usize, usize) { + (x / BITS, x % BITS) } /// `FixedBitSet` is a simple fixed size set of bits that each can @@ -73,7 +73,7 @@ impl FixedBitSet { /// Create a new **FixedBitSet** with a specific number of bits, /// all initially clear. pub fn with_capacity(bits: usize) -> Self { - let (mut blocks, rem) = div_rem(bits, BITS); + let (mut blocks, rem) = div_rem(bits); blocks += (rem > 0) as usize; FixedBitSet { data: vec![0; blocks], @@ -95,7 +95,7 @@ impl FixedBitSet { /// assert_eq!(format!("{:b}", bs), "0010"); /// ``` pub fn with_capacity_and_blocks>(bits: usize, blocks: I) -> Self { - let (mut n_blocks, rem) = div_rem(bits, BITS); + let (mut n_blocks, rem) = div_rem(bits); n_blocks += (rem > 0) as usize; let mut data: Vec = blocks.into_iter().collect(); // Pad data with zeros if smaller or truncate if larger @@ -103,7 +103,7 @@ impl FixedBitSet { data.resize(n_blocks, 0); } // Disable bits in blocks beyond capacity - let end = data.len() * 32; + let end = data.len() * BITS; for (block, mask) in Masks::new(bits..end, end) { unsafe { *data.get_unchecked_mut(block) &= !mask; @@ -114,7 +114,7 @@ impl FixedBitSet { /// Grow capacity to **bits**, all new bits initialized to zero pub fn grow(&mut self, bits: usize) { - let (mut blocks, rem) = div_rem(bits, BITS); + let (mut blocks, rem) = div_rem(bits); blocks += (rem > 0) as usize; if bits > self.length { self.length = bits; @@ -185,7 +185,7 @@ impl FixedBitSet { /// Note: Also available with index syntax: `bitset[bit]`. #[inline] pub fn contains(&self, bit: usize) -> bool { - let (block, i) = div_rem(bit, BITS); + let (block, i) = div_rem(bit); match self.data.get(block) { None => false, Some(b) => (b & (1 << i)) != 0, @@ -211,7 +211,7 @@ impl FixedBitSet { bit, self.length ); - let (block, i) = div_rem(bit, BITS); + let (block, i) = div_rem(bit); unsafe { *self.data.get_unchecked_mut(block) |= 1 << i; } @@ -228,7 +228,7 @@ impl FixedBitSet { bit, self.length ); - let (block, i) = div_rem(bit, BITS); + let (block, i) = div_rem(bit); unsafe { let word = self.data.get_unchecked_mut(block); let prev = *word & (1 << i) != 0; @@ -247,7 +247,7 @@ impl FixedBitSet { bit, self.length ); - let (block, i) = div_rem(bit, BITS); + let (block, i) = div_rem(bit); unsafe { *self.data.get_unchecked_mut(block) ^= 1 << i; } @@ -261,7 +261,7 @@ impl FixedBitSet { bit, self.length ); - let (block, i) = div_rem(bit, BITS); + let (block, i) = div_rem(bit); unsafe { let elt = self.data.get_unchecked_mut(block); if enabled { @@ -283,7 +283,7 @@ impl FixedBitSet { to, self.length ); - let (to_block, t) = div_rem(to, BITS); + let (to_block, t) = div_rem(to); let enabled = self.contains(from); unsafe { let to_elt = self.data.get_unchecked_mut(to_block); @@ -352,16 +352,16 @@ impl FixedBitSet { } } - /// View the bitset as a slice of `u32` blocks + /// View the bitset as a slice of `Block` blocks #[inline] - pub fn as_slice(&self) -> &[u32] { + pub fn as_slice(&self) -> &[Block] { &self.data } - /// View the bitset as a mutable slice of `u32` blocks. Writing past the bitlength in the last + /// View the bitset as a mutable slice of `Block` blocks. Writing past the bitlength in the last /// will cause `contains` to return potentially incorrect results for bits past the bitlength. #[inline] - pub fn as_mut_slice(&mut self) -> &mut [u32] { + pub fn as_mut_slice(&mut self) -> &mut [Block] { &mut self.data } @@ -374,12 +374,12 @@ impl FixedBitSet { Some((&block, rem)) => Ones { bitset: block, block_idx: 0, - remaining_blocks: rem, + remaining_blocks: rem.iter(), }, None => Ones { bitset: 0, block_idx: 0, - remaining_blocks: &[], + remaining_blocks: [].iter(), }, } } @@ -615,8 +615,8 @@ impl Masks { length ); - let (first_block, first_rem) = div_rem(start, BITS); - let (last_block, last_rem) = div_rem(end, BITS); + let (first_block, first_rem) = div_rem(start); + let (last_block, last_rem) = div_rem(end); Masks { first_block: first_block as usize, @@ -660,7 +660,7 @@ impl Iterator for Masks { pub struct Ones<'a> { bitset: Block, block_idx: usize, - remaining_blocks: &'a [Block], + remaining_blocks: std::slice::Iter<'a, Block>, } impl<'a> Iterator for Ones<'a> { @@ -669,17 +669,13 @@ impl<'a> Iterator for Ones<'a> { #[inline] fn next(&mut self) -> Option { while self.bitset == 0 { - if self.remaining_blocks.is_empty() { - return None; - } - self.bitset = self.remaining_blocks[0]; - self.remaining_blocks = &self.remaining_blocks[1..]; - self.block_idx += 1; + self.bitset = *self.remaining_blocks.next()?; + self.block_idx += BITS; } let t = self.bitset & (0 as Block).wrapping_sub(self.bitset); let r = self.bitset.trailing_zeros() as usize; self.bitset ^= t; - Some(self.block_idx * BITS + r) + Some(self.block_idx + r) } } @@ -860,7 +856,7 @@ mod tests { #[test] fn with_blocks() { - let fb = FixedBitSet::with_capacity_and_blocks(50, vec![8u32, 0u32]); + let fb = FixedBitSet::with_capacity_and_blocks(50, vec![8, 0]); assert!(fb.contains(3)); let ones: Vec<_> = fb.ones().collect(); @@ -869,14 +865,14 @@ mod tests { #[test] fn with_blocks_too_small() { - let mut fb = FixedBitSet::with_capacity_and_blocks(500, vec![8u32, 0u32]); + let mut fb = FixedBitSet::with_capacity_and_blocks(500, vec![8, 0]); fb.insert(400); assert!(fb.contains(400)); } #[test] fn with_blocks_too_big() { - let fb = FixedBitSet::with_capacity_and_blocks(1, vec![8u32]); + let fb = FixedBitSet::with_capacity_and_blocks(1, vec![8]); // since capacity is 1, 3 shouldn't be set here assert!(!fb.contains(3));