1 #include "integer-pool.hpp"
8 const unsigned special_level
= 21;
9 uint64_t level_base
[] = {
30 164703072086692425ULL,
31 1317624576693539401ULL,
32 3623467585907233353ULL, //Special: Fits 2^64 bits.
34 uint64_t level_size
[] = {
54 144115188075855872ULL,
55 1152921504606846976ULL,
56 2305843009213693952ULL, //Special: 2^64 bits.
59 const unsigned levels
= 22;
60 unsigned level_from_size(uint64_t size
)
62 for(unsigned i
= 0; i
< levels
; i
++) {
63 if(size
<= level_base
[i
+ 1]) return i
;
68 unsigned lsbz(uint8_t b
)
70 return ((b
& 1) ? ((b
& 2) ? ((b
& 4) ? ((b
& 8) ? ((b
& 16) ? ((b
& 32) ? ((b
& 64) ?
71 ((b
& 128) ? 8 : 7) : 6) : 5) : 4) : 3) : 2) : 1) : 0);
75 integer_pool::integer_pool() throw()
82 uint64_t integer_pool::operator()() throw(std::bad_alloc
)
84 if(invalid
) throw std::bad_alloc();
85 //If the first byte is 0xFF, we got to expand the array.
87 unsigned level
= level_from_size(_bits
.size()); //If bits.size() == 0, this correctly returns 0.
88 assert(level
< special_level
);
89 std::vector
<uint8_t> newbits
;
90 newbits
.resize(level_base
[level
+ 2]);
91 memset(&newbits
[0], 0, level_base
[level
+ 2]);
92 for(unsigned i
= 0; i
<= level
; i
++)
93 memcpy(&newbits
[level_base
[i
+ 1]], &bits
[level_base
[i
]], level_size
[i
]);
95 std::swap(_bits
, newbits
);
99 unsigned level
= level_from_size(_bits
.size()); //If bits.size() == 0, this correctly returns 0.
100 uint64_t pathbits
= 0;
101 for(unsigned i
= 0; i
< level
; i
++) {
102 uint64_t byte
= level_base
[i
] + pathbits
;
103 assert(bits
[byte
] < 255);
104 unsigned lsb
= lsbz(bits
[byte
]);
105 pathbits
= 8 * pathbits
+ lsb
;
108 //Check if there are free integers in pool.
109 if(pathbits
> 0x1FFFFFFFFFFFFFFFULL
) throw std::bad_alloc();
111 //Reserve it, and propagate fullness downward if needed.
112 uint64_t byte
= level_base
[level
] + pathbits
;
113 assert(bits
[byte
] < 255);
114 unsigned lsb
= lsbz(bits
[byte
]);
115 pathbits
= 8 * pathbits
+ lsb
;
116 uint64_t bit
= pathbits
;
118 for(unsigned i
= level
; i
<= level
; i
--) {
120 byte
= level_base
[i
] + (pathbits
>> 3);
121 bits
[byte
] |= (1 << (pathbits
& 7));
122 carry
= (bits
[byte
] == 255);
130 void integer_pool::operator()(uint64_t num
) throw()
133 unsigned level
= level_from_size(_bits
.size()); //If bits.size() == 0, this correctly returns 0.
134 for(unsigned i
= level
; i
<= level
; i
--) {
135 uint64_t byte
= level_base
[i
] + (num
>> 3);
136 bits
[byte
] &= ~(1 << (num
& 7));
141 integer_pool::~integer_pool() throw()