1use std::mem;
2use std::ops;
3
4pub 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 #[inline]
20 fn nbits() -> usize {
21 8 * mem::size_of::<Self>()
22 }
23
24 #[inline]
32 fn div_nbits(index: u64) -> usize {
33 (index >> Self::lg_nbits()) as usize
34 }
35
36 #[inline]
42 fn checked_div_nbits(index: u64) -> Option<usize> {
43 (index >> Self::lg_nbits()).to_usize()
44 }
45
46 #[inline]
51 fn ceil_div_nbits(index: u64) -> usize {
52 Self::div_nbits(index + (Self::nbits() as u64 - 1))
53 }
54
55 #[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 #[inline]
72 fn mod_nbits(index: u64) -> usize {
73 let mask: u64 = Self::lg_nbits_mask();
74 (index & mask) as usize
75 }
76
77 #[inline]
82 fn mul_nbits(index: usize) -> u64 {
83 (index as u64) << Self::lg_nbits()
84 }
85
86 #[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 #[inline]
113 fn lg_nbits() -> usize {
114 Self::nbits().floor_lg()
115 }
116
117 #[inline]
119 fn lg_nbits_mask<Result: BlockType>() -> Result {
120 Result::low_mask(Self::lg_nbits())
121 }
122
123 #[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 #[inline]
151 fn nth_mask(bit_index: usize) -> Self {
152 Self::one() << bit_index
153 }
154
155 #[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 #[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 #[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 #[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 #[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 #[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 fn wrapping_shl(self, shift: u32) -> Self;
232
233 fn wrapping_sub(self, other: Self) -> Self;
235
236 fn leading_zeros(self) -> usize;
238
239 fn to_usize(self) -> Option<usize>;
241
242 fn zero() -> Self;
244
245 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 #[inline]
277 fn low_mask(k: usize) -> Self {
278 debug_assert!(k <= Self::nbits());
279
280 let a = Self::one().wrapping_shl(k as u32).wrapping_sub(1);
282
283 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#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
337pub struct Address {
338 pub block_index: usize,
340 pub bit_offset: usize,
342}
343
344impl Address {
345 #[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}
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 ); 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 ); }
545}