2016-11-15 17:55:30 +00:00
|
|
|
/*********************************************************************
|
|
|
|
* 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 <david@dumas.io>
|
|
|
|
*
|
|
|
|
* 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 <string.h>
|
|
|
|
|
|
|
|
#include <inttypes.h>
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
|
|
|
/* For _mm_popcnt_u64 */
|
|
|
|
#include <x86intrin.h>
|
|
|
|
|
2016-11-16 21:59:35 +00:00
|
|
|
// FIRSTBITS(n) only yields useful result when 0 <= n < 64
|
|
|
|
#define FIRSTBITS(n) ((1l << (n)) - 1l)
|
|
|
|
#define ALLBITS ((uint64_t)-1)
|
|
|
|
|
2016-11-15 17:55:30 +00:00
|
|
|
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; i<BV_QWORD_RANK; i++) {
|
|
|
|
accum += popcount64(x.v[i]);
|
|
|
|
}
|
|
|
|
return accum;
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
|
|
|
|
static inline void bv_clear_bit(bitvec_t *x, int k)
|
|
|
|
{
|
|
|
|
x->v[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;i<BV_QWORD_RANK;i++) {
|
|
|
|
x->v[i] = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline int bv_is_zero(const bitvec_t *x)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
for (i=0;i<BV_QWORD_RANK;i++) {
|
|
|
|
if (x->v[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);
|
2016-11-16 21:59:35 +00:00
|
|
|
if(i % 64 == 63)
|
|
|
|
fputc('-',f);
|
2016-11-15 17:55:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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++)
|
2016-11-16 21:59:35 +00:00
|
|
|
if(x->v[i] != ALLBITS)
|
2016-11-15 17:55:30 +00:00
|
|
|
return 0;
|
|
|
|
|
2016-11-16 21:59:35 +00:00
|
|
|
return (x->v[i] & FIRSTBITS(len%64)) == FIRSTBITS(len%64);
|
2016-11-15 17:55:30 +00:00
|
|
|
}
|
|
|
|
|
2016-11-16 21:59:35 +00:00
|
|
|
// set bits in range start...end (including start and excluding end)
|
|
|
|
static inline void bv_set_range(bitvec_t *x, int start, int end)
|
2016-11-15 17:55:30 +00:00
|
|
|
{
|
2016-11-16 21:59:35 +00:00
|
|
|
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, i;
|
|
|
|
|
|
|
|
position = ffsll(~(x->v[start/64] | FIRSTBITS(start % 64)));
|
|
|
|
|
|
|
|
if(position) // found zero in same chunk?
|
|
|
|
return (start/64)%64 + position - 1;
|
|
|
|
|
|
|
|
for(i = start/64 + 1, position = 0; i < BV_QWORD_RANK && position == 0; i++)
|
|
|
|
position = ffsll(~x->v[i]);
|
2016-11-15 17:55:30 +00:00
|
|
|
|
2016-11-16 21:59:35 +00:00
|
|
|
return position ? (i - 1)*64 + position - 1 : BV_QWORD_RANK;
|
2016-11-15 17:55:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* static inline int bv_lowest_bit_set(bitvec_t x) */
|
|
|
|
/* { */
|
|
|
|
/* int i=0, k; */
|
|
|
|
/* for (i=0;i<BV_QWORD_RANK;i++) { */
|
|
|
|
/* if (k=ffsll((long long)x.v[i])) */
|
|
|
|
/* return 64*i + k - 1; */
|
|
|
|
/* } */
|
|
|
|
/* return -1; */
|
|
|
|
/* } */
|
|
|
|
|
|
|
|
/* static inline int bv_lowest_bit_set(bitvec_t x) */
|
|
|
|
/* { */
|
|
|
|
/* int k; */
|
|
|
|
/* for (k=0;k<BV_BIT_RANK;k++) { */
|
|
|
|
/* if (bv_get_bit(x,k)) */
|
|
|
|
/* return k; */
|
|
|
|
/* } */
|
|
|
|
/* return -1; */
|
|
|
|
/* } */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#endif /* __BITVEC_H__ */
|