Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
bit_vector.cpp
Go to the documentation of this file.
2
4
5#include <string.h>
6#include <stdlib.h>
7#include <algorithm>
8#include <new>
9
10#ifndef ROUTING_KIT_NO_ALIGNED_ALLOC
11#ifdef _MSC_VER
12#include <malloc.h>
13// Let us hope that this workaround does not break when MS finally implements the C11 standard function aligned_alloc from <stdlib.h>...
14// If it does break then please open an issue with the information of upto what values of _MSC_VER the workaround is needed.
15#define aligned_alloc(alignment, size) _aligned_malloc(size, alignment)
16#define aligned_free(ptr) _aligned_free(ptr)
17#else
18#define aligned_free(ptr) free(ptr)
19#endif
20#endif
21
22namespace RoutingKit{
23
24// Not all compilers support aligned_alloc such as GCC 4.6. If you have such a compiler then define ROUTING_KIT_NO_ALIGNED_ALLOC
25
26#ifdef ROUTING_KIT_NO_ALIGNED_ALLOC
27void*aligned_alloc(uint8_t alignment, uint64_t size){
28 uint64_t potentially_unaligned_buffer = (uint64_t)malloc(size+alignment);
29 uint64_t aligned_buffer = ((potentially_unaligned_buffer + alignment)/alignment) * alignment;
30 uint8_t*buffer = (uint8_t*)aligned_buffer;
31 *(buffer-1) = aligned_buffer - potentially_unaligned_buffer;
32 return buffer;
33}
34
35void aligned_free(void* ptr){
36 if(ptr){
37 uint8_t*buffer = (uint8_t*)ptr;
38 uint8_t shift = *(buffer-1);
39 buffer -= shift;
40 free(buffer);
41 }
42}
43#endif
44
45
46namespace {
47 #ifndef ROUTING_KIT_NO_GCC_EXTENSIONS
48 typedef uint64_t v8_uint64_t __attribute__((vector_size(64)));
49 #else
50 struct v8_uint64_t{
51 v8_uint64_t(){}
52
53 v8_uint64_t(unsigned x){
54 for(unsigned i=0; i<8; ++i)
55 v[i] = x;
56 }
57
58 uint64_t v[8];
59 void operator^=(v8_uint64_t o){
60 for(unsigned i=0; i<8; ++i)
61 v[i] ^= o.v[i];
62 }
63
64 void operator&=(v8_uint64_t o){
65 for(unsigned i=0; i<8; ++i)
66 v[i] &= o.v[i];
67 }
68
69 void operator|=(v8_uint64_t o){
70 for(unsigned i=0; i<8; ++i)
71 v[i] |= o.v[i];
72 }
73
74 v8_uint64_t operator~()const{
75 v8_uint64_t r;
76 for(unsigned i=0; i<8; ++i)
77 r.v[i] = ~v[i];
78 return r;
79 }
80
81 uint64_t&operator[](uint64_t i){return v[i];};
82 const uint64_t&operator[](uint64_t i)const{return v[i];};
83
84 };
85
86 v8_uint64_t operator^(v8_uint64_t l, v8_uint64_t r){
87 l ^= r;
88 return l;
89 }
90
91 v8_uint64_t operator&(v8_uint64_t l, v8_uint64_t r){
92 l &= r;
93 return l;
94 }
95
96 v8_uint64_t operator|(v8_uint64_t l, v8_uint64_t r){
97 l |= r;
98 return l;
99 }
100 #endif
101
102
103 uint64_t get_v8_uint64_count(uint64_t bit_count){
104 return (bit_count+511)/512;
105 }
106
107 uint64_t get_uint64_count(uint64_t bit_count){
108 return get_v8_uint64_count(bit_count)*8;
109 }
110
111 uint64_t get_uint8_count(uint64_t bit_count){
112 return get_v8_uint64_count(bit_count)*64;
113 }
114
115 v8_uint64_t get_padding_mask(uint64_t size){
116 v8_uint64_t u = {0};
117
118 uint64_t x = size % 512;
119 uint8_t i = 0;
120 while(x >= 64){
121 u[i++] = ~0ull;
122 x -= 64;
123 }
124 if(x != 0)
125 u[i] = (1ull<<x)-1;
126
127 return u;
128 }
129
130 bool is_any_bit_set(const v8_uint64_t*x){
131 v8_uint64_t u = *x;
132
133 u[0] |= u[1];
134 u[2] |= u[3];
135 u[4] |= u[5];
136 u[6] |= u[7];
137
138 u[0] |= u[4];
139 u[2] |= u[6];
140
141 u[0] |= u[2];
142
143 return u[0] != 0;
144 }
145
146 bool are_all_bits_set(const v8_uint64_t*x){
147 v8_uint64_t u = *x;
148
149 u[0] &= u[1];
150 u[2] &= u[3];
151 u[4] &= u[5];
152 u[6] &= u[7];
153
154 u[0] &= u[4];
155 u[2] &= u[6];
156
157 u[0] &= u[2];
158
159 return u[0] == ~0ull;
160 }
161
162 #ifndef NDEBUG
163 bool are_all_padding_bits_zero(const BitVector&v){
164 if(v.size() % 512 == 0){
165 return true;
166 } else {
167 auto x = get_padding_mask(v.size());
168 x = ((const v8_uint64_t*)v.data())[v.size()/512] & ~x;
169 return !is_any_bit_set(&x);
170 }
171 }
172 #endif
173}
174
176 data_(nullptr), size_(0){}
177
179{
180 if(__builtin_expect(size != 0, true)){
181 data_ = (uint64_t*)(aligned_alloc(64, get_uint8_count(size)));
182 if(data_ == nullptr)
183 throw std::bad_alloc();
184 size_ = size;
186 }else{
187 data_ = nullptr;
188 size_ = 0;
189 }
190
191 assert(are_all_padding_bits_zero(*this));
192}
193
194BitVector::BitVector(uint64_t size, bool init_value)
195{
196 if(__builtin_expect(size != 0, true)){
197 data_ = (uint64_t*)(aligned_alloc(64, get_uint8_count(size)));
198 if(data_ == nullptr)
199 throw std::bad_alloc();
200 size_ = size;
201
202 v8_uint64_t init_vec = {0};
203 assert(init_vec[0] == 0ull);
204 if(init_value)
205 init_vec = ~init_vec;
206 assert(!init_value || init_vec[0] == ~0ull);
207 assert(init_value || init_vec[0] == 0ull);
208
209 for(
210 v8_uint64_t*i = (v8_uint64_t*)data_;
211 i<((v8_uint64_t*)data_)+get_v8_uint64_count(size);
212 ++i
213 )
214 *i = init_vec;
215
216 if(init_value)
218 }else{
219 data_ = nullptr;
220 size_ = 0;
221 }
222
223 assert(are_all_padding_bits_zero(*this));
224}
225
229
231 data_(static_cast<uint64_t*>(aligned_alloc(64, get_uint8_count(o.size_)))), size_(o.size_){
232 if(data_ == nullptr)
233 throw std::bad_alloc();
234
235 assert(are_all_padding_bits_zero(o));
236
237 for(
238 v8_uint64_t*i = (v8_uint64_t*)data_, *j=(v8_uint64_t*)o.data_;
239 i<((v8_uint64_t*)data_)+get_v8_uint64_count(size_);
240 ++i, ++j
241 )
242 *i = *j;
243
244 assert(are_all_padding_bits_zero(*this));
245}
246
248 data_(o.data_), size_(o.size_){
249
250 assert(are_all_padding_bits_zero(o));
251
252 o.data_ = nullptr;
253 o.size_ = 0;
254}
255
257 assert(are_all_padding_bits_zero(o));
258
259 swap(o);
260 return *this;
261}
262
264 assert(are_all_padding_bits_zero(o));
265 assert(are_all_padding_bits_zero(*this));
266
267 uint64_t*x = o.data_;
268 o.data_ = data_;
269 data_ = x;
270
271 uint64_t y = o.size_;
272 o.size_ = size_;
273 size_ = y;
274}
275
277 if(size_ % 512 != 0){
278 v8_uint64_t* v = (v8_uint64_t*)data_ + size_/512;
279 *v &= get_padding_mask(size_);
280 }
281
282 assert(are_all_padding_bits_zero(*this));
283}
284
286 if(data_ == nullptr){
287 *this = BitVector(new_size, uninitialized);
288 }else{
289
290 assert(are_all_padding_bits_zero(*this));
291 if(get_uint8_count(new_size) == get_uint8_count(size_)){
292 size_ = new_size;
294 }else{
295 BitVector o(new_size);
296
297 for(
298 v8_uint64_t*i = (v8_uint64_t*)data_, *j=(v8_uint64_t*)o.data_;
299 i<((v8_uint64_t*)data_)+std::min(get_v8_uint64_count(size_), get_v8_uint64_count(new_size));
300 ++i, ++j
301 ){
302 *j = *i;
303 }
305 assert(are_all_padding_bits_zero(o));
306 swap(o);
307 }
308 assert(are_all_padding_bits_zero(*this));
309 }
310}
311
312void BitVector::resize(uint64_t new_size, bool value){
313 if(data_ == nullptr){
314 *this = BitVector(new_size, value);
315 }else{
316 assert(are_all_padding_bits_zero(*this));
317 if(new_size < size_) {
318 resize(new_size, uninitialized);
319 } else if(get_uint8_count(new_size) == get_uint8_count(size_)){
320 if(value == false){
321 size_ = new_size;
322 } else {
323 ((v8_uint64_t*)data_)[size_/512] |= get_padding_mask(new_size) & ~get_padding_mask(size_);
324 size_ = new_size;
325 }
326 } else {
327 BitVector o(new_size);
328
329 v8_uint64_t
330 *i = (v8_uint64_t*)data_,
331 *j = (v8_uint64_t*)o.data_;
332
333 while(i < (v8_uint64_t*)data_ + get_v8_uint64_count(size_)){
334 *j = *i;
335 ++i;
336 ++j;
337 }
338
339 if(value){
340 *(j-1) |= ~get_padding_mask(size_);
341
342 v8_uint64_t all_one = {0};
343 all_one = ~all_one;
344
345 while(j < (v8_uint64_t*)o.data_ + get_v8_uint64_count(o.size_)){
346 *j = all_one;
347 ++j;
348 }
349
350 *(j-1) &= get_padding_mask(o.size_);
351 assert(are_all_padding_bits_zero(o));
352 }else{
353 v8_uint64_t all_zero = {0};
354
355 while(j < (v8_uint64_t*)o.data_ + get_v8_uint64_count(o.size_)){
356 *j = all_zero;
357 ++j;
358 }
359 assert(are_all_padding_bits_zero(o));
360 }
361
362 assert(are_all_padding_bits_zero(*this));
363 swap(o);
364 }
365 assert(are_all_padding_bits_zero(*this));
366 }
367}
368
370 assert(are_all_padding_bits_zero(*this));
371 if(size_ <= x) {
372 uint64_t n = 1;
373 while(n <= x) {
374 n <<= 1;
375 }
377 }
378 assert(are_all_padding_bits_zero(*this));
379 assert(size_ > x);
380}
381
382void BitVector::make_large_enough_for(uint64_t x, bool init_value){
383 assert(are_all_padding_bits_zero(*this));
384 if(size_ <= x) {
385 uint64_t n = 1;
386 while(n <= x) {
387 n <<= 1;
388 }
389 assert(n > x);
390 resize(n, init_value);
391 }
392 assert(are_all_padding_bits_zero(*this));
393 assert(size_ > x);
394}
395
396
398 assert(are_all_padding_bits_zero(*this));
399 uint64_t n = 0;
400 for(uint64_t*i=data_; i<data_ + get_uint64_count(size_); ++i)
401 n += __builtin_popcountll(*i);
402 return n;
403}
404
406 v8_uint64_t x = {0};
407 x = ~x;
408 for(v8_uint64_t*i = (v8_uint64_t*)data_; i<((v8_uint64_t*)data_)+get_v8_uint64_count(size_); ++i)
409 *i = x;
411}
412
414 v8_uint64_t x = {0};
415 for(v8_uint64_t*i = (v8_uint64_t*)data_; i<((v8_uint64_t*)data_)+get_v8_uint64_count(size_); ++i)
416 *i = x;
417 assert(are_all_padding_bits_zero(*this));
418}
419
420void BitVector::set_all(bool value){
421 v8_uint64_t x = {0};
422 if(value)
423 x = ~x;
424
425 for(v8_uint64_t*i = (v8_uint64_t*)data_; i<((v8_uint64_t*)data_)+get_v8_uint64_count(size_); ++i)
426 *i = x;
427
428 if(value)
430 assert(are_all_padding_bits_zero(*this));
431}
432
434 assert(are_all_padding_bits_zero(*this));
435 if(__builtin_expect(size_ == 0, false))
436 return true;
437
438 v8_uint64_t x = {0};
439 x = ~x;
440
441 uint64_t n = get_v8_uint64_count(size_);
442 --n;
443
444 v8_uint64_t*i;
445 for(i = (v8_uint64_t*)data_; i<((v8_uint64_t*)data_)+n; ++i)
446 x &= *i;
447 x &= *i | ~get_padding_mask(size_);
448 return are_all_bits_set(&x);
449}
450
452 assert(are_all_padding_bits_zero(*this));
453 if(__builtin_expect(size_ == 0, false))
454 return false;
455
456 v8_uint64_t x = {0};
457
458 for(v8_uint64_t*i = (v8_uint64_t*)data_; i<((v8_uint64_t*)data_)+get_v8_uint64_count(size_); ++i)
459 x |= *i;
460
461 return is_any_bit_set(&x);
462}
463
465 assert(are_all_padding_bits_zero(*this));
466 assert(are_all_padding_bits_zero(o));
467 assert(size_ == o.size_ && "can only combine bit vectors of same size");
468 for(v8_uint64_t*i = (v8_uint64_t*)data_, *j=(v8_uint64_t*)o.data_; i<((v8_uint64_t*)data_)+get_v8_uint64_count(size_); ++i, ++j)
469 *i |= *j;
470 assert(are_all_padding_bits_zero(*this));
471 return *this;
472}
473
475 assert(are_all_padding_bits_zero(*this));
476 assert(are_all_padding_bits_zero(o));
477 assert(size_ == o.size_ && "can only combine bit vectors of same size");
478 for(v8_uint64_t*i = (v8_uint64_t*)data_, *j=(v8_uint64_t*)o.data_; i<((v8_uint64_t*)data_)+get_v8_uint64_count(size_); ++i, ++j)
479 *i ^= *j;
480 assert(are_all_padding_bits_zero(*this));
481 return *this;
482}
483
485 assert(are_all_padding_bits_zero(*this));
486 assert(are_all_padding_bits_zero(o));
487 assert(size_ == o.size_ && "can only combine bit vectors of same size");
488 for(v8_uint64_t*i = (v8_uint64_t*)data_, *j=(v8_uint64_t*)o.data_; i<((v8_uint64_t*)data_)+get_v8_uint64_count(size_); ++i, ++j)
489 *i &= *j;
490 assert(are_all_padding_bits_zero(*this));
491 return *this;
492}
493
495 assert(are_all_padding_bits_zero(*this));
496 for(v8_uint64_t*i = (v8_uint64_t*)data_; i<((v8_uint64_t*)data_)+get_v8_uint64_count(size_); ++i)
497 *i = ~*i;
499 assert(are_all_padding_bits_zero(*this));
500}
501
502bool operator==(const BitVector&l, const BitVector&r){
503 assert(are_all_padding_bits_zero(l));
504 assert(are_all_padding_bits_zero(r));
505 if(__builtin_expect(l.size_ != r.size_, false))
506 return false;
507
508 v8_uint64_t x = {0};
509
510 for(v8_uint64_t*i = (v8_uint64_t*)l.data_, *j=(v8_uint64_t*)r.data_; i<((v8_uint64_t*)l.data_)+get_v8_uint64_count(l.size_); ++i, ++j){
511 x |= (*i ^ *j);
512 }
513
514 return !is_any_bit_set(&x);
515}
516
517bool operator<(const BitVector&l, const BitVector&r){
518 assert(are_all_padding_bits_zero(l));
519 assert(are_all_padding_bits_zero(r));
520 if(__builtin_expect(l.size_ != r.size_, false))
521 return l.size_ < r.size_;
522
523 for(uint64_t*i = l.data_, *j = r.data_; i<l.data_+get_uint64_count(l.size_); ++i, ++j)
524 if(*i != *j)
525 return *i < *j;
526 return false;
527}
528
529} // namespace RoutingKit
#define aligned_free(ptr)
bool is_any_set() const
void swap(BitVector &)
static constexpr Uninitialized uninitialized
Definition bit_vector.h:13
BitVector & operator&=(const BitVector &)
BitVector & operator=(BitVector)
bool are_all_set() const
BitVector & operator|=(const BitVector &)
uint64_t size() const
Definition bit_vector.h:26
void resize(uint64_t size, Uninitialized)
BitVector & operator^=(const BitVector &)
uint64_t population_count() const
void make_large_enough_for(uint64_t x, Uninitialized)
BitVector operator^(BitVector &&l, BitVector &&r)
Definition bit_vector.h:142
bool operator==(const BitVector &l, const BitVector &r)
BitVector operator|(BitVector &&l, BitVector &&r)
Definition bit_vector.h:132
bool operator<(const BitVector &l, const BitVector &r)
BitVector operator&(BitVector &&l, BitVector &&r)
Definition bit_vector.h:137