Skip to main content

bv/
storage.rs

1use std::mem;
2use std::ops;
3
4/// Interface to primitive bit storage.
5///
6/// Types implementing this trait can be used as the blocks of a bit-vector.
7pub trait BlockType: Copy +
8                     PartialEq +
9                     Ord +
10                     ops::BitAnd<Output = Self> +
11                     ops::BitOr<Output = Self> +
12                     ops::BitXor<Output = Self> +
13                     ops::Not<Output = Self> +
14                     ops::Shl<usize, Output = Self> +
15                     ops::Shr<usize, Output = Self> +
16                     ops::Sub<Output = Self>
17{
18    /// The number of bits in a block.
19    #[inline]
20    fn nbits() -> usize {
21        8 * mem::size_of::<Self>()
22    }
23
24    /// Returns `index / Self::nbits()`, computed by shifting.
25    ///
26    /// This is intended for converting a bit address into a block
27    /// address, which is why it takes `u64` and returns `usize`.
28    /// There is no check that the result actually fits in a `usize`,
29    /// so this should only be used when `index` is already known to
30    /// be small enough.
31    #[inline]
32    fn div_nbits(index: u64) -> usize {
33        (index >> Self::lg_nbits()) as usize
34    }
35
36    /// Returns `index / Self::nbits()`, computed by shifting.
37    ///
38    /// This is intended for converting a bit address into a block
39    /// address, which is why it takes `u64` and returns `usize`. It can only fail (returning
40    /// `None`) if `usize` is 32 bits.
41    #[inline]
42    fn checked_div_nbits(index: u64) -> Option<usize> {
43        (index >> Self::lg_nbits()).to_usize()
44    }
45
46    /// Returns `index / Self::nbits()` rounded up, computed by shifting.
47    ///
48    /// This is intended for converting a bit size into a block
49    /// size, which is why it takes `u64` and returns `usize`.
50    #[inline]
51    fn ceil_div_nbits(index: u64) -> usize {
52        Self::div_nbits(index + (Self::nbits() as u64 - 1))
53    }
54
55    /// Returns `index / Self::nbits()` rounded up, computed by shifting.
56    ///
57    /// This is intended for converting a bit size into a block
58    /// size, which is why it takes `u64` and returns `usize`.
59    /// There is no check that the result actually fits in a `usize`,
60    /// so this should only be used when `index` is already known to
61    /// be small enough.
62    #[inline]
63    fn checked_ceil_div_nbits(index: u64) -> Option<usize> {
64        Self::checked_div_nbits(index + (Self::nbits() as u64 - 1))
65    }
66
67    /// Returns `index % Self::nbits()`, computed by masking.
68    ///
69    /// This is intended for converting a bit address into a bit offset
70    /// within a block, which is why it takes `u64` and returns `usize`.
71    #[inline]
72    fn mod_nbits(index: u64) -> usize {
73        let mask: u64 = Self::lg_nbits_mask();
74        (index & mask) as usize
75    }
76
77    /// Returns `index * Self::nbits()`, computed by shifting.
78    ///
79    /// This is intended for converting a block address into a bit address,
80    /// which is why it takes a `usize` and returns a `u64`.
81    #[inline]
82    fn mul_nbits(index: usize) -> u64 {
83        (index as u64) << Self::lg_nbits()
84    }
85
86    /// The number of bits in the block at `position`, given a total bit length
87    /// of `len`.
88    ///
89    /// This will be `Self::nbits()` for all but the last block, for which it may
90    /// be less.
91    ///
92    /// # Precondition
93    ///
94    /// `position * Self::nbits() <= len`, or the block doesn't exist and the result
95    /// is undefined.
96    #[inline]
97    fn block_bits(len: u64, position: usize) -> usize {
98        let block_start = Self::mul_nbits(position);
99        let block_limit = block_start + Self::nbits() as u64;
100
101        debug_assert!( block_start <= len,
102                       "BlockType::block_bits: precondition" );
103
104        usize::if_then_else(
105            block_limit <= len,
106            Self::nbits(),
107            len.wrapping_sub(block_start) as usize
108        )
109    }
110
111    /// Log-base-2 of the number of bits in a block.
112    #[inline]
113    fn lg_nbits() -> usize {
114        Self::nbits().floor_lg()
115    }
116
117    /// Mask with the lowest-order `lg_nbits()` set.
118    #[inline]
119    fn lg_nbits_mask<Result: BlockType>() -> Result {
120        Result::low_mask(Self::lg_nbits())
121    }
122
123    /// The bit mask consisting of `Self::nbits() - element_bits` zeroes
124    /// followed by `element_bits` ones.
125    ///
126    /// The default implementation has a branch, but should be overrided with
127    /// a branchless algorithm if possible.
128    ///
129    /// # Precondition
130    ///
131    /// `element_bits <= Self::nbits()`
132    #[inline]
133    fn low_mask(element_bits: usize) -> Self {
134        debug_assert!(element_bits <= Self::nbits());
135
136        if element_bits == Self::nbits() {
137            !Self::zero()
138        } else {
139            (Self::one() << element_bits) - Self::one()
140        }
141    }
142
143    /// The bit mask with the `bit_index`th bit set.
144    ///
145    /// Bits are indexed in little-endian style based at 0.
146    ///
147    /// # Precondition
148    ///
149    /// `bit_index < Self::nbits()`
150    #[inline]
151    fn nth_mask(bit_index: usize) -> Self {
152        Self::one() << bit_index
153    }
154
155    // Methods for getting and setting bits.
156
157    /// Extracts the value of the `bit_index`th bit.
158    ///
159    /// # Panics
160    ///
161    /// Panics if `bit_index` is out of bounds.
162    #[inline]
163    fn get_bit(self, bit_index: usize) -> bool {
164        assert!(bit_index < Self::nbits(), "Block::get_bit: out of bounds");
165        self & Self::nth_mask(bit_index) != Self::zero()
166    }
167
168    /// Functionally updates the value of the `bit_index`th bit to `bit_value`.
169    ///
170    /// # Panics
171    ///
172    /// Panics if `bit_index` is out of bounds.
173    #[inline]
174    fn with_bit(self, bit_index: usize, bit_value: bool) -> Self {
175        assert!(bit_index < Self::nbits(), "Block::with_bit: out of bounds");
176        if bit_value {
177            self | Self::nth_mask(bit_index)
178        } else {
179            self & !Self::nth_mask(bit_index)
180        }
181    }
182
183    /// Extracts `len` bits starting at bit offset `start`.
184    ///
185    /// # Panics
186    ///
187    /// Panics of the bit span is out of bounds.
188    #[inline]
189    fn get_bits(self, start: usize, len: usize) -> Self {
190        assert!(start + len <= Self::nbits(),
191                "Block::get_bits: out of bounds");
192
193        (self >> start) & Self::low_mask(len)
194    }
195
196    /// Functionally updates `len` bits to `value` starting at offset `start`.
197    ///
198    /// # Panics
199    ///
200    /// Panics of the bit span is out of bounds.
201    #[inline]
202    fn with_bits(self, start: usize, len: usize, value: Self) -> Self {
203        assert!(start + len <= Self::nbits(),
204                "Block::with_bits: out of bounds");
205
206        let mask = Self::low_mask(len) << start;
207        let shifted_value = value << start;
208
209        (self & !mask) | (shifted_value & mask)
210    }
211
212    /// Returns the smallest number `n` such that `2.pow(n) >= self`.
213    #[inline]
214    fn ceil_lg(self) -> usize {
215        usize::if_then(
216            self > Self::one(),
217            Self::nbits().wrapping_sub((self.wrapping_sub(Self::one())).leading_zeros() as usize)
218        )
219    }
220
221    /// Returns the largest number `n` such that `2.pow(n) <= self`.
222    #[inline]
223    fn floor_lg(self) -> usize {
224        usize::if_then(
225            self > Self::one(),
226            Self::nbits().wrapping_sub(1).wrapping_sub(self.leading_zeros() as usize)
227        )
228    }
229
230    /// A shift-left operation that does not overflow.
231    fn wrapping_shl(self, shift: u32) -> Self;
232
233    /// A subtraction operation that does not overflow.
234    fn wrapping_sub(self, other: Self) -> Self;
235
236    /// Returns the number of leading zero bits in the given number.
237    fn leading_zeros(self) -> usize;
238
239    /// Converts the number to a `usize`, if it fits.
240    fn to_usize(self) -> Option<usize>;
241
242    /// Returns 0.
243    fn zero() -> Self;
244
245    /// Returns 1.
246    fn one() -> Self;
247}
248
249trait IfThenElse {
250    fn if_then_else(cond: bool, then_val: Self, else_val: Self) -> Self;
251    fn if_then(cond: bool, then_val: Self) -> Self;
252}
253
254macro_rules! impl_block_type {
255    ( $ty:ident )
256        =>
257    {
258        impl IfThenElse for $ty {
259            #[inline]
260            fn if_then_else(cond: bool, then_val: Self, else_val: Self) -> Self {
261                let then_cond = cond as Self;
262                let else_cond = 1 - then_cond;
263                (then_cond * then_val) | (else_cond * else_val)
264            }
265
266            #[inline]
267            fn if_then(cond: bool, then_val: Self) -> Self {
268                (cond as Self) * then_val
269            }
270        }
271
272        impl BlockType for $ty {
273            // The default `low_mask` has a branch, but we can do better if we have
274            // `wrapping_shl`. That isn't a member of any trait, but all the primitive
275            // numeric types have it, so we can override low_mask in this macro.
276            #[inline]
277            fn low_mask(k: usize) -> Self {
278                debug_assert!(k <= Self::nbits());
279
280                // Compute the mask when element_bits is not the word size:
281                let a = Self::one().wrapping_shl(k as u32).wrapping_sub(1);
282
283                // Special case for the word size:
284                let b = (Self::div_nbits(k as u64) & 1) as Self * !0;
285
286                a | b
287            }
288
289            #[inline]
290            fn wrapping_shl(self, shift: u32) -> Self {
291                self.wrapping_shl(shift)
292            }
293
294            #[inline]
295            fn wrapping_sub(self, other: Self) -> Self {
296                self.wrapping_sub(other)
297            }
298
299            #[inline]
300            fn leading_zeros(self) -> usize {
301                self.leading_zeros() as usize
302            }
303
304            #[inline]
305            fn to_usize(self) -> Option<usize> {
306                if self as usize as Self == self {
307                    Some(self as usize)
308                } else {
309                    None
310                }
311            }
312
313            #[inline]
314            fn zero() -> Self {
315                0
316            }
317
318            #[inline]
319            fn one() -> Self {
320                1
321            }
322        }
323    }
324}
325
326impl_block_type!(u8);
327impl_block_type!(u16);
328impl_block_type!(u32);
329impl_block_type!(u64);
330#[cfg(int_128)]
331impl_block_type!(u128);
332impl_block_type!(usize);
333
334/// Represents the address of a bit, broken into a block component
335/// and a bit offset component.
336#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
337pub struct Address {
338    /// The index of the block containing the bit in question.
339    pub block_index: usize,
340    /// The position of the bit in question within its block.
341    pub bit_offset: usize,
342}
343
344impl Address {
345    /// Creates an `Address` for the given bit index for storage in
346    /// block type `Block`.
347    ///
348    /// # Panics
349    ///
350    /// Panics if `bit_index` divided by the block size doesn’t fit in a
351    /// `usize`.
352    #[inline]
353    pub fn new<Block: BlockType>(bit_index: u64) -> Self {
354        Address {
355            block_index: Block::checked_div_nbits(bit_index)
356                .expect("Address::new: index overflow"),
357            bit_offset: Block::mod_nbits(bit_index),
358        }
359    }
360
361//    /// Converts an `Address` back into a raw bit index.
362//    ///
363//    /// This method and `new` should be inverses.
364//    #[inline]
365//    pub fn bit_index<Block: BlockType>(&self) -> u64 {
366//        Block::mul_nbits(self.block_index) + self.bit_offset as u64
367//    }
368}
369
370#[cfg(test)]
371mod test {
372    use super::*;
373    use quickcheck::{quickcheck, TestResult};
374
375    #[test]
376    fn nbits() {
377        assert_eq!(8, u8::nbits());
378        assert_eq!(16, u16::nbits());
379        assert_eq!(32, u32::nbits());
380        assert_eq!(64, u64::nbits());
381    }
382
383    quickcheck!{
384        fn prop_div_nbits(n: u32) -> bool {
385            u32::div_nbits(n as u64) == (n / 32) as usize
386        }
387
388        fn prop_ceil_div_nbits1(n: u32) -> bool {
389            u32::ceil_div_nbits(n as u64) ==
390                (n as f32 / 32.0f32).ceil() as usize
391        }
392
393        fn prop_ceil_div_nbits2(n: u32) -> bool {
394            let result = u32::ceil_div_nbits(n as u64);
395            result * 32 >= n as usize &&
396                (result == 0 || (result - 1) * 32 < n as usize)
397        }
398
399        fn prop_mod_nbits(n: u32) -> bool {
400            u32::mod_nbits(n as u64) == n as usize % 32
401        }
402
403        fn prop_mul_nbits(n: u32) -> bool {
404            u32::mul_nbits(n as usize) == n as u64 * 32
405        }
406    }
407
408    #[test]
409    fn lg_nbits() {
410        assert_eq!( u8::lg_nbits(), 3 );
411        assert_eq!( u16::lg_nbits(), 4 );
412        assert_eq!( u32::lg_nbits(), 5 );
413        assert_eq!( u64::lg_nbits(), 6 );
414    }
415
416    #[test]
417    fn low_mask() {
418        assert_eq!(0b00011111, u8::low_mask(5));
419        assert_eq!(0b0011111111111111, u16::low_mask(14));
420        assert_eq!(0b1111111111111111, u16::low_mask(16));
421    }
422
423    #[test]
424    fn nth_mask() {
425        assert_eq!(0b10000000, u8::nth_mask(7));
426        assert_eq!(0b01000000, u8::nth_mask(6));
427        assert_eq!(0b00100000, u8::nth_mask(5));
428        assert_eq!(0b00000010, u8::nth_mask(1));
429        assert_eq!(0b00000001, u8::nth_mask(0));
430
431        assert_eq!(0b0000000000000001, u16::nth_mask(0));
432        assert_eq!(0b1000000000000000, u16::nth_mask(15));
433    }
434
435    #[test]
436    fn get_bits() {
437        assert_eq!(0b0,
438                   0b0100110001110000u16.get_bits(0, 0));
439        assert_eq!(0b010,
440                   0b0100110001110000u16.get_bits(13, 3));
441        assert_eq!(    0b110001,
442                       0b0100110001110000u16.get_bits(6, 6));
443        assert_eq!(           0b10000,
444                              0b0100110001110000u16.get_bits(0, 5));
445        assert_eq!(0b0100110001110000,
446                   0b0100110001110000u16.get_bits(0, 16));
447    }
448
449    #[test]
450    fn with_bits() {
451        assert_eq!(0b0111111111000001,
452                   0b0110001111000001u16.with_bits(10, 3, 0b111));
453        assert_eq!(0b0101110111000001,
454                   0b0110001111000001u16.with_bits(9, 5, 0b01110));
455        assert_eq!(0b0110001111000001,
456                   0b0110001111000001u16.with_bits(14, 0, 0b01110));
457        assert_eq!(0b0110001110101010,
458                   0b0110001111000001u16.with_bits(0, 8, 0b10101010));
459        assert_eq!(0b0000000000000010,
460                   0b0110001111000001u16.with_bits(0, 16, 0b10));
461    }
462
463    #[test]
464    fn get_bit() {
465        assert!(! 0b00000000u8.get_bit(0));
466        assert!(! 0b00000000u8.get_bit(1));
467        assert!(! 0b00000000u8.get_bit(2));
468        assert!(! 0b00000000u8.get_bit(3));
469        assert!(! 0b00000000u8.get_bit(7));
470        assert!(! 0b10101010u8.get_bit(0));
471        assert!(  0b10101010u8.get_bit(1));
472        assert!(! 0b10101010u8.get_bit(2));
473        assert!(  0b10101010u8.get_bit(3));
474        assert!(  0b10101010u8.get_bit(7));
475    }
476
477    #[test]
478    fn with_bit() {
479        assert_eq!(0b00100000, 0b00000000u8.with_bit(5, true));
480        assert_eq!(0b00000000, 0b00000000u8.with_bit(5, false));
481        assert_eq!(0b10101010, 0b10101010u8.with_bit(7, true));
482        assert_eq!(0b00101010, 0b10101010u8.with_bit(7, false));
483        assert_eq!(0b10101011, 0b10101010u8.with_bit(0, true));
484        assert_eq!(0b10101010, 0b10101010u8.with_bit(0, false));
485    }
486
487    #[test]
488    fn floor_lg() {
489        assert_eq!(0, 1u32.floor_lg());
490        assert_eq!(1, 2u32.floor_lg());
491        assert_eq!(1, 3u32.floor_lg());
492        assert_eq!(2, 4u32.floor_lg());
493        assert_eq!(2, 5u32.floor_lg());
494        assert_eq!(2, 7u32.floor_lg());
495        assert_eq!(3, 8u32.floor_lg());
496
497        fn prop(n: u64) -> TestResult {
498            if n == 0 { return TestResult::discard(); }
499
500            TestResult::from_bool(
501                2u64.pow(n.floor_lg() as u32) <= n
502                    && 2u64.pow(n.floor_lg() as u32 + 1) > n)
503        }
504
505        quickcheck(prop as fn(u64) -> TestResult);
506    }
507
508    #[test]
509    fn ceil_lg() {
510        assert_eq!(0, 1u32.ceil_lg());
511        assert_eq!(1, 2u32.ceil_lg());
512        assert_eq!(2, 3u32.ceil_lg());
513        assert_eq!(2, 4u32.ceil_lg());
514        assert_eq!(3, 5u32.ceil_lg());
515        assert_eq!(3, 7u32.ceil_lg());
516        assert_eq!(3, 8u32.ceil_lg());
517        assert_eq!(4, 9u32.ceil_lg());
518
519        fn prop(n: u64) -> TestResult {
520            if n <= 1 { return TestResult::discard(); }
521
522            TestResult::from_bool(
523                2u64.pow(n.ceil_lg() as u32) >= n
524                    && 2u64.pow(n.ceil_lg() as u32 - 1) < n)
525        }
526        quickcheck(prop as fn(u64) -> TestResult);
527    }
528
529    #[test]
530    fn block_bits() {
531        assert_eq!( u16::block_bits(1, 0), 1 );
532        assert_eq!( u16::block_bits(2, 0), 2 );
533        assert_eq!( u16::block_bits(16, 0), 16 );
534        assert_eq!( u16::block_bits(16, 1), 0 ); // boundary condition
535        assert_eq!( u16::block_bits(23, 0), 16 );
536        assert_eq!( u16::block_bits(23, 1), 7 );
537        assert_eq!( u16::block_bits(35, 0), 16 );
538        assert_eq!( u16::block_bits(35, 1), 16 );
539        assert_eq!( u16::block_bits(35, 2), 3 );
540        assert_eq!( u16::block_bits(48, 0), 16 );
541        assert_eq!( u16::block_bits(48, 1), 16 );
542        assert_eq!( u16::block_bits(48, 2), 16 );
543        assert_eq!( u16::block_bits(48, 3), 0 ); // boundary condition
544    }
545}