/********************************************************************* * Filename: bitvec.h * * Description: Bit vectors implemented as uint64_t arrays, size * fixed at compile time (in weylconfig.h). Supports * efficient set operations: Union, difference, count. * Uses SSE4 64-bit popcount instruction. * * Author: David Dumas * * This program is free software distributed under the MIT license. * See the file LICENSE for details. ********************************************************************/ #ifndef __BITVEC_H__ #define __BITVEC_H__ 1 // #define _GNU_SOURCE /* enable ffsll */ // #include #include #include #include /* For _mm_popcnt_u64 */ #include // FIRSTBITS(n) only yields useful result when 0 <= n < 64 #define FIRSTBITS(n) ((1l << (n)) - 1l) #define ALLBITS ((uint64_t)-1) typedef struct { uint64_t v[BV_QWORD_RANK]; } bitvec_t; /* static inline unsigned long bv_hash(bitvec_t S) { unsigned long h = 5381; int i,j; uint8_t x; for (i = 0; i < BV_QWORD_RANK*4; i++) { x = (S.v[i/8] >> (8*(i % 8))) & 0xff; h = ((h << 5) + h) ^ x; } return h; } static inline int bv_equal(bitvec_t x,bitvec_t y) { int i; for (i=0; i < BV_QWORD_RANK; i++) { if (x.v[i] != y.v[i]) { return 0; } } return 1; // return ((x.v[0] == y.v[0]) && (x.v[1] == y.v[1])); } static inline void bv_difference(bitvec_t *pile, bitvec_t toremove) { int i; for (i=0; i < BV_QWORD_RANK; i++) { pile->v[i] &= ~toremove.v[i]; } } */ /* /\* static inline *\/ int old_popcount64(uint64_t x) */ /* { */ /* int i; */ /* for (i = 0; x; x >>= 1) { */ /* i += x & 1; */ /* } */ /* return i; */ /* } */ /* static inline int popcount64(uint64_t x) { return _mm_popcnt_u64(x); } static inline int bv_popcount(bitvec_t x) { int i; int accum=0; for (i=0; iv[k/64] &= ~((uint64_t)1 << (k % 64)); } static inline void bv_set_bit(bitvec_t *x, int k) { x->v[k/64] |= ((uint64_t)1 << (k % 64)); } static inline int bv_get_bit(const bitvec_t *x, int k) { return (x->v[k/64] >> (k % 64)) & 0x1; } static inline void bv_clear(bitvec_t *x) { int i; for (i=0;iv[i] = 0; } static inline int bv_is_zero(const bitvec_t *x) { int i; for (i=0;iv[i]) return 0; return 1; } static inline void bv_print(FILE *f, const bitvec_t *x, int len) { for(int i = 0; i < len; i++) { fputc(bv_get_bit(x, i) ? '1' : '0', f); if(i % 64 == 63) fputc('-',f); } } static inline void bv_union(const bitvec_t *x, const bitvec_t *y, bitvec_t *result) { int i; for (i=0; i < BV_QWORD_RANK; i++) { result->v[i] = x->v[i] | y->v[i]; } } static inline void bv_intersection(const bitvec_t *x, const bitvec_t *y, bitvec_t *result) { int i; for (i=0; i < BV_QWORD_RANK; i++) { result->v[i] = x->v[i] & y->v[i]; } } static inline int bv_disjoint(const bitvec_t *x, const bitvec_t *y) { for(int i = 0; i < BV_QWORD_RANK; i++) if(x->v[i] & y->v[i]) return 0; return 1; } static inline int bv_full(const bitvec_t *x, int len) { int i; for(i = 0; i < len/64; i++) if(x->v[i] != ALLBITS) return 0; return (x->v[i] & FIRSTBITS(len%64)) == FIRSTBITS(len%64); } // set bits in range start...end (including start and excluding end) static inline void bv_set_range(bitvec_t *x, int start, int end) { if(start/64 == end/64) x->v[start/64] |= ~FIRSTBITS(start % 64) & FIRSTBITS(end % 64); else { x->v[start/64] |= ~FIRSTBITS(start % 64); for(int i = start/64 + 1; i < end/64; i++) x->v[i] = ALLBITS; x->v[end/64] |= FIRSTBITS(end % 64); } } // find least significant 0 bit starting from position start (included) static inline int bv_next_zero(const bitvec_t *x, int start) { int position; position = ffsll(~(x->v[start/64] | FIRSTBITS(start % 64))); if(position) return (start/64)*64 + position - 1; // found zero in same chunk for(int i = start/64 + 1; i < BV_QWORD_RANK; i++) { position = ffsll(~x->v[i]); if(position) // found a 0 return i*64 + position - 1; } return BV_QWORD_RANK; // found nothing } static inline void bv_copy(const bitvec_t *from, bitvec_t *to) { for(int i = 0; i < BV_QWORD_RANK; i++) to->v[i] = from->v[i]; } #endif /* __BITVEC_H__ */