Skip to content

Commit

Permalink
Adding max, min, intersection count and union count
Browse files Browse the repository at this point in the history
  • Loading branch information
lemire committed Mar 17, 2017
1 parent afa3cdd commit 61c56e2
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 1 deletion.
14 changes: 14 additions & 0 deletions include/bitset.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,12 +91,26 @@ static inline bool bitset_get(const bitset_t *bitset, size_t i ) {
/* Count number of bit sets. */
size_t bitset_count(const bitset_t *bitset);

/* Find the index of the first bit set. */
size_t bitset_minimum(const bitset_t *bitset);

/* Find the index of the last bit set. */
size_t bitset_maximum(const bitset_t *bitset);


/* compute the union in-place (to b1), returns true if successful, to generate a new bitset first call bitset_copy */
bool bitset_inplace_union(bitset_t *b1, const bitset_t *b2);

/* report the size of the union (without materializing it) */
size_t bitset_union_count(const bitset_t *b1, const bitset_t *b2);

/* compute the intersection in-place (to b1), to generate a new bitset first call bitset_copy */
void bitset_inplace_intersection(bitset_t *b1, const bitset_t *b2);

/* report the size of the intersection (without materializing it) */
size_t bitset_intersection_count(const bitset_t *b1, const bitset_t *b2);


/* compute the difference in-place (to b1), to generate a new bitset first call bitset_copy */
void bitset_inplace_difference(bitset_t *b1, const bitset_t *b2);

Expand Down
68 changes: 68 additions & 0 deletions src/bitset.c
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,65 @@ bool bitset_inplace_union(bitset_t *b1, const bitset_t *b2) {
return true;
}

size_t bitset_minimum(const bitset_t *bitset) {
for(size_t k = 0; k < bitset->arraysize; k++) {
uint64_t w = bitset->array[k];
if ( w != 0 ) {
return __builtin_ctzll(w) + k * 64;
}
}
return 0;
}

size_t bitset_maximum(const bitset_t *bitset) {
for(size_t k = bitset->arraysize ; k > 0 ; k--) {
uint64_t w = bitset->array[k - 1];
if ( w != 0 ) {
return 63 - __builtin_clzll(w) + (k - 1) * 64;
}
}
return 0;
}

size_t bitset_union_count(const bitset_t *b1, const bitset_t *b2) {
size_t answer = 0;
size_t minlength = b1->arraysize < b2->arraysize ? b1->arraysize : b2->arraysize;
size_t k = 0;
for( ; k + 3 < minlength; k += 4) {
answer += __builtin_popcountll ( b1->array[k] | b2->array[k]);
answer += __builtin_popcountll ( b1->array[k+1] | b2->array[k+1]);
answer += __builtin_popcountll ( b1->array[k+2] | b2->array[k+2]);
answer += __builtin_popcountll ( b1->array[k+3] | b2->array[k+3]);
}
for( ; k < minlength; ++k) {
answer += __builtin_popcountll ( b1->array[k] | b2->array[k]);
}
if(b2->arraysize > b1->arraysize) {
//k = b1->arraysize;
for(; k + 3 < b2->arraysize; k+=4) {
answer += __builtin_popcountll (b2->array[k]);
answer += __builtin_popcountll (b2->array[k+1]);
answer += __builtin_popcountll (b2->array[k+2]);
answer += __builtin_popcountll (b2->array[k+3]);
}
for(; k < b2->arraysize; ++k) {
answer += __builtin_popcountll (b2->array[k]);
}
} else {
//k = b2->arraysize;
for(; k + 3 < b1->arraysize; k+=4) {
answer += __builtin_popcountll (b1->array[k]);
answer += __builtin_popcountll (b1->array[k+1]);
answer += __builtin_popcountll (b1->array[k+2]);
answer += __builtin_popcountll (b1->array[k+3]);
}
for(; k < b1->arraysize; ++k) {
answer += __builtin_popcountll (b1->array[k]);
}
}
return answer;
}

void bitset_inplace_intersection(bitset_t *b1, const bitset_t *b2) {
size_t minlength = b1->arraysize < b2->arraysize ? b1->arraysize : b2->arraysize;
size_t k = 0;
Expand All @@ -133,6 +192,15 @@ void bitset_inplace_intersection(bitset_t *b1, const bitset_t *b2) {
}
}

size_t bitset_intersection_count(const bitset_t *b1, const bitset_t *b2) {
size_t answer = 0;
size_t minlength = b1->arraysize < b2->arraysize ? b1->arraysize : b2->arraysize;
for(size_t k = 0 ; k < minlength; ++k) {
answer += __builtin_popcountll ( b1->array[k] & b2->array[k]);
}
return answer;
}

void bitset_inplace_difference(bitset_t *b1, const bitset_t *b2) {
size_t minlength = b1->arraysize < b2->arraysize ? b1->arraysize : b2->arraysize;
size_t k = 0;
Expand Down
32 changes: 31 additions & 1 deletion tests/unit.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ void test_iterate() {
bitset_set(b,3*k);
assert(bitset_count(b) == 1000);
size_t k = 0;

for(size_t i = 0; nextSetBit(b,&i) ; i++) {
assert(i == k);
k += 3;
}
assert(k == 3000);
bitset_free(b);
}

void test_construct() {
Expand All @@ -24,8 +24,20 @@ void test_construct() {
assert(bitset_count(b) == 1000);
for(int k = 0; k < 3*1000; ++k)
assert(bitset_get(b,k) == (k/3*3 == k));
bitset_free(b);
}

void test_max_min() {
bitset_t * b = bitset_create();
for(size_t k = 100; k < 1000; ++k) {
bitset_set(b,3*k);
assert(bitset_minimum(b) == 3 * 100);
assert(bitset_maximum(b) == 3 * k);
}
bitset_free(b);
}


void test_union_intersection() {
bitset_t * b1 = bitset_create();
bitset_t * b2 = bitset_create();
Expand All @@ -50,12 +62,30 @@ void test_union_intersection() {
bitset_inplace_union(b1,b2);
bitset_inplace_difference(b2,b1);
assert(bitset_count(b2) == 0);
bitset_free(b1);
bitset_free(b2);
}

void test_counts() {
bitset_t * b1 = bitset_create();
bitset_t * b2 = bitset_create();

for(int k = 0; k < 1000; ++k) {
bitset_set(b1,2*k);
bitset_set(b2,3*k);
}
assert(bitset_intersection_count(b1,b2) == 334);
assert(bitset_union_count(b1,b2) == 1666);
bitset_free(b1);
bitset_free(b2);
}


int main() {
test_construct();
test_union_intersection();
test_iterate();
test_max_min();
test_counts();
printf("All asserts passed. Code is probably ok.\n");
}

0 comments on commit 61c56e2

Please sign in to comment.