enumerate-balanced-ideals/bitvec.h

214 lines
4.5 KiB
C

/*********************************************************************
* 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>
// 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; 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);
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__ */