Packages
rocksdb
3.1.1
3.1.1
3.1.0
3.0.0
2.6.2
2.6.1
retired
2.6.0
retired
2.5.0
2.4.1
2.4.0
2.3.0
2.2.0
2.1.0
2.0.0
1.9.0
1.8.0
1.7.0
1.6.0
1.5.1
1.5.0
1.4.0
1.3.2
1.3.1
1.3.0
1.2.0
1.1.1
1.1.0
1.0.0
0.26.2
0.26.1
0.26.0
0.25.0
0.24.0
0.23.3
0.23.2
0.23.1
0.23.0
0.22.0
0.21.0
0.20.1
0.20.0
0.19.0
0.18.0
0.17.0
0.16.0
0.15.0
0.14.0
0.13.1
0.13.0
0.12.0
0.11.0
0.10.0
0.9.1
0.9.0
0.8.2
0.8.1
0.8.0
0.7.1
0.7.0
0.6.4
0.6.3
0.6.2
0.6.1
0.6.0
RocksDB for Erlang
Current section
Files
Jump to
Current section
Files
deps/CRoaring/src/bitset.c
#include <limits.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <roaring/bitset/bitset.h>
#include <roaring/memory.h>
#include <roaring/portability.h>
#ifdef __cplusplus
extern "C" {
namespace roaring {
namespace internal {
#endif
extern inline void bitset_print(const bitset_t *b);
extern inline bool bitset_for_each(const bitset_t *b, bitset_iterator iterator,
void *ptr);
extern inline size_t bitset_next_set_bits(const bitset_t *bitset,
size_t *buffer, size_t capacity,
size_t *startfrom);
extern inline void bitset_set_to_value(bitset_t *bitset, size_t i, bool flag);
extern inline bool bitset_next_set_bit(const bitset_t *bitset, size_t *i);
extern inline void bitset_set(bitset_t *bitset, size_t i);
extern inline bool bitset_get(const bitset_t *bitset, size_t i);
extern inline size_t bitset_size_in_words(const bitset_t *bitset);
extern inline size_t bitset_size_in_bits(const bitset_t *bitset);
extern inline size_t bitset_size_in_bytes(const bitset_t *bitset);
/* Create a new bitset. Return NULL in case of failure. */
bitset_t *bitset_create(void) {
bitset_t *bitset = NULL;
/* Allocate the bitset itself. */
if ((bitset = (bitset_t *)roaring_malloc(sizeof(bitset_t))) == NULL) {
return NULL;
}
bitset->array = NULL;
bitset->arraysize = 0;
bitset->capacity = 0;
return bitset;
}
/* Create a new bitset able to contain size bits. Return NULL in case of
* failure. */
bitset_t *bitset_create_with_capacity(size_t size) {
bitset_t *bitset = NULL;
/* Allocate the bitset itself. */
if ((bitset = (bitset_t *)roaring_malloc(sizeof(bitset_t))) == NULL) {
return NULL;
}
bitset->arraysize =
(size + sizeof(uint64_t) * 8 - 1) / (sizeof(uint64_t) * 8);
bitset->capacity = bitset->arraysize;
if ((bitset->array = (uint64_t *)roaring_calloc(
bitset->arraysize, sizeof(uint64_t))) == NULL) {
roaring_free(bitset);
return NULL;
}
return bitset;
}
/* Create a copy */
bitset_t *bitset_copy(const bitset_t *bitset) {
bitset_t *copy = NULL;
/* Allocate the bitset itself. */
if ((copy = (bitset_t *)roaring_malloc(sizeof(bitset_t))) == NULL) {
return NULL;
}
memcpy(copy, bitset, sizeof(bitset_t));
copy->capacity = copy->arraysize;
if ((copy->array = (uint64_t *)roaring_malloc(sizeof(uint64_t) *
bitset->arraysize)) == NULL) {
roaring_free(copy);
return NULL;
}
memcpy(copy->array, bitset->array, sizeof(uint64_t) * bitset->arraysize);
return copy;
}
void bitset_clear(bitset_t *bitset) {
memset(bitset->array, 0, sizeof(uint64_t) * bitset->arraysize);
}
void bitset_fill(bitset_t *bitset) {
memset(bitset->array, 0xff, sizeof(uint64_t) * bitset->arraysize);
}
void bitset_shift_left(bitset_t *bitset, size_t s) {
size_t extra_words = s / 64;
int inword_shift = s % 64;
size_t as = bitset->arraysize;
if (inword_shift == 0) {
bitset_resize(bitset, as + extra_words, false);
// could be done with a memmove
for (size_t i = as + extra_words; i > extra_words; i--) {
bitset->array[i - 1] = bitset->array[i - 1 - extra_words];
}
} else {
bitset_resize(bitset, as + extra_words + 1, true);
bitset->array[as + extra_words] =
bitset->array[as - 1] >> (64 - inword_shift);
for (size_t i = as + extra_words; i >= extra_words + 2; i--) {
bitset->array[i - 1] =
(bitset->array[i - 1 - extra_words] << inword_shift) |
(bitset->array[i - 2 - extra_words] >> (64 - inword_shift));
}
bitset->array[extra_words] = bitset->array[0] << inword_shift;
}
for (size_t i = 0; i < extra_words; i++) {
bitset->array[i] = 0;
}
}
void bitset_shift_right(bitset_t *bitset, size_t s) {
size_t extra_words = s / 64;
int inword_shift = s % 64;
size_t as = bitset->arraysize;
if (inword_shift == 0) {
// could be done with a memmove
for (size_t i = 0; i < as - extra_words; i++) {
bitset->array[i] = bitset->array[i + extra_words];
}
bitset_resize(bitset, as - extra_words, false);
} else {
for (size_t i = 0; i + extra_words + 1 < as; i++) {
bitset->array[i] =
(bitset->array[i + extra_words] >> inword_shift) |
(bitset->array[i + extra_words + 1] << (64 - inword_shift));
}
bitset->array[as - extra_words - 1] =
(bitset->array[as - 1] >> inword_shift);
bitset_resize(bitset, as - extra_words, false);
}
}
/* Free memory. */
void bitset_free(bitset_t *bitset) {
if (bitset == NULL) {
return;
}
roaring_free(bitset->array);
roaring_free(bitset);
}
/* Resize the bitset so that it can support newarraysize * 64 bits. Return true
* in case of success, false for failure. */
bool bitset_resize(bitset_t *bitset, size_t newarraysize, bool padwithzeroes) {
if (newarraysize > SIZE_MAX / 64) {
return false;
}
size_t smallest =
newarraysize < bitset->arraysize ? newarraysize : bitset->arraysize;
if (bitset->capacity < newarraysize) {
uint64_t *newarray;
size_t newcapacity = bitset->capacity;
if (newcapacity == 0) {
newcapacity = 1;
}
while (newcapacity < newarraysize) {
newcapacity *= 2;
}
if ((newarray = (uint64_t *)roaring_realloc(
bitset->array, sizeof(uint64_t) * newcapacity)) == NULL) {
return false;
}
bitset->capacity = newcapacity;
bitset->array = newarray;
}
if (padwithzeroes && (newarraysize > smallest))
memset(bitset->array + smallest, 0,
sizeof(uint64_t) * (newarraysize - smallest));
bitset->arraysize = newarraysize;
return true; // success!
}
size_t bitset_count(const bitset_t *bitset) {
size_t card = 0;
size_t k = 0;
for (; k + 7 < bitset->arraysize; k += 8) {
card += roaring_hamming(bitset->array[k]);
card += roaring_hamming(bitset->array[k + 1]);
card += roaring_hamming(bitset->array[k + 2]);
card += roaring_hamming(bitset->array[k + 3]);
card += roaring_hamming(bitset->array[k + 4]);
card += roaring_hamming(bitset->array[k + 5]);
card += roaring_hamming(bitset->array[k + 6]);
card += roaring_hamming(bitset->array[k + 7]);
}
for (; k + 3 < bitset->arraysize; k += 4) {
card += roaring_hamming(bitset->array[k]);
card += roaring_hamming(bitset->array[k + 1]);
card += roaring_hamming(bitset->array[k + 2]);
card += roaring_hamming(bitset->array[k + 3]);
}
for (; k < bitset->arraysize; k++) {
card += roaring_hamming(bitset->array[k]);
}
return card;
}
bool bitset_inplace_union(bitset_t *CROARING_CBITSET_RESTRICT b1,
const bitset_t *CROARING_CBITSET_RESTRICT b2) {
size_t minlength =
b1->arraysize < b2->arraysize ? b1->arraysize : b2->arraysize;
for (size_t k = 0; k < minlength; ++k) {
b1->array[k] |= b2->array[k];
}
if (b2->arraysize > b1->arraysize) {
size_t oldsize = b1->arraysize;
if (!bitset_resize(b1, b2->arraysize, false)) return false;
memcpy(b1->array + oldsize, b2->array + oldsize,
(b2->arraysize - oldsize) * sizeof(uint64_t));
}
return true;
}
bool bitset_empty(const bitset_t *bitset) {
for (size_t k = 0; k < bitset->arraysize; k++) {
if (bitset->array[k] != 0) {
return false;
}
}
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 roaring_trailing_zeroes(w) + k * 64;
}
}
return SIZE_MAX;
}
bool bitset_grow(bitset_t *bitset, size_t newarraysize) {
if (newarraysize < bitset->arraysize) {
return false;
}
if (newarraysize > SIZE_MAX / 64) {
return false;
}
if (bitset->capacity < newarraysize) {
uint64_t *newarray;
size_t newcapacity = (UINT64_C(0xFFFFFFFFFFFFFFFF) >>
roaring_leading_zeroes(newarraysize)) +
1;
while (newcapacity < newarraysize) {
newcapacity *= 2;
}
if ((newarray = (uint64_t *)roaring_realloc(
bitset->array, sizeof(uint64_t) * newcapacity)) == NULL) {
return false;
}
bitset->capacity = newcapacity;
bitset->array = newarray;
}
memset(bitset->array + bitset->arraysize, 0,
sizeof(uint64_t) * (newarraysize - bitset->arraysize));
bitset->arraysize = newarraysize;
return true; // success!
}
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 - roaring_leading_zeroes(w) + (k - 1) * 64;
}
}
return 0;
}
/* Returns true if bitsets share no common elements, false otherwise.
*
* Performs early-out if common element found. */
bool bitsets_disjoint(const bitset_t *CROARING_CBITSET_RESTRICT b1,
const bitset_t *CROARING_CBITSET_RESTRICT b2) {
size_t minlength =
b1->arraysize < b2->arraysize ? b1->arraysize : b2->arraysize;
for (size_t k = 0; k < minlength; k++) {
if ((b1->array[k] & b2->array[k]) != 0) return false;
}
return true;
}
/* Returns true if bitsets contain at least 1 common element, false if they are
* disjoint.
*
* Performs early-out if common element found. */
bool bitsets_intersect(const bitset_t *CROARING_CBITSET_RESTRICT b1,
const bitset_t *CROARING_CBITSET_RESTRICT b2) {
size_t minlength =
b1->arraysize < b2->arraysize ? b1->arraysize : b2->arraysize;
for (size_t k = 0; k < minlength; k++) {
if ((b1->array[k] & b2->array[k]) != 0) return true;
}
return false;
}
/* Returns true if b has any bits set in or after b->array[starting_loc]. */
static bool any_bits_set(const bitset_t *b, size_t starting_loc) {
if (starting_loc >= b->arraysize) {
return false;
}
for (size_t k = starting_loc; k < b->arraysize; k++) {
if (b->array[k] != 0) return true;
}
return false;
}
/* Returns true if b1 has all of b2's bits set.
*
* Performs early out if a bit is found in b2 that is not found in b1. */
bool bitset_contains_all(const bitset_t *CROARING_CBITSET_RESTRICT b1,
const bitset_t *CROARING_CBITSET_RESTRICT b2) {
size_t min_size = b1->arraysize;
if (b1->arraysize > b2->arraysize) {
min_size = b2->arraysize;
}
for (size_t k = 0; k < min_size; k++) {
if ((b1->array[k] & b2->array[k]) != b2->array[k]) {
return false;
}
}
if (b2->arraysize > b1->arraysize) {
/* Need to check if b2 has any bits set beyond b1's array */
return !any_bits_set(b2, b1->arraysize);
}
return true;
}
size_t bitset_union_count(const bitset_t *CROARING_CBITSET_RESTRICT b1,
const bitset_t *CROARING_CBITSET_RESTRICT 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 += roaring_hamming(b1->array[k] | b2->array[k]);
answer += roaring_hamming(b1->array[k + 1] | b2->array[k + 1]);
answer += roaring_hamming(b1->array[k + 2] | b2->array[k + 2]);
answer += roaring_hamming(b1->array[k + 3] | b2->array[k + 3]);
}
for (; k < minlength; ++k) {
answer += roaring_hamming(b1->array[k] | b2->array[k]);
}
if (b2->arraysize > b1->arraysize) {
// k is equal to b1->arraysize
for (; k + 3 < b2->arraysize; k += 4) {
answer += roaring_hamming(b2->array[k]);
answer += roaring_hamming(b2->array[k + 1]);
answer += roaring_hamming(b2->array[k + 2]);
answer += roaring_hamming(b2->array[k + 3]);
}
for (; k < b2->arraysize; ++k) {
answer += roaring_hamming(b2->array[k]);
}
} else {
// k is equal to b2->arraysize
for (; k + 3 < b1->arraysize; k += 4) {
answer += roaring_hamming(b1->array[k]);
answer += roaring_hamming(b1->array[k + 1]);
answer += roaring_hamming(b1->array[k + 2]);
answer += roaring_hamming(b1->array[k + 3]);
}
for (; k < b1->arraysize; ++k) {
answer += roaring_hamming(b1->array[k]);
}
}
return answer;
}
void bitset_inplace_intersection(bitset_t *CROARING_CBITSET_RESTRICT b1,
const bitset_t *CROARING_CBITSET_RESTRICT b2) {
size_t minlength =
b1->arraysize < b2->arraysize ? b1->arraysize : b2->arraysize;
size_t k = 0;
for (; k < minlength; ++k) {
b1->array[k] &= b2->array[k];
}
for (; k < b1->arraysize; ++k) {
b1->array[k] = 0; // memset could, maybe, be a tiny bit faster
}
}
size_t bitset_intersection_count(const bitset_t *CROARING_CBITSET_RESTRICT b1,
const bitset_t *CROARING_CBITSET_RESTRICT 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 += roaring_hamming(b1->array[k] & b2->array[k]);
}
return answer;
}
void bitset_inplace_difference(bitset_t *CROARING_CBITSET_RESTRICT b1,
const bitset_t *CROARING_CBITSET_RESTRICT b2) {
size_t minlength =
b1->arraysize < b2->arraysize ? b1->arraysize : b2->arraysize;
size_t k = 0;
for (; k < minlength; ++k) {
b1->array[k] &= ~(b2->array[k]);
}
}
size_t bitset_difference_count(const bitset_t *CROARING_CBITSET_RESTRICT b1,
const bitset_t *CROARING_CBITSET_RESTRICT b2) {
size_t minlength =
b1->arraysize < b2->arraysize ? b1->arraysize : b2->arraysize;
size_t k = 0;
size_t answer = 0;
for (; k < minlength; ++k) {
answer += roaring_hamming(b1->array[k] & ~(b2->array[k]));
}
for (; k < b1->arraysize; ++k) {
answer += roaring_hamming(b1->array[k]);
}
return answer;
}
bool bitset_inplace_symmetric_difference(
bitset_t *CROARING_CBITSET_RESTRICT b1,
const bitset_t *CROARING_CBITSET_RESTRICT b2) {
size_t minlength =
b1->arraysize < b2->arraysize ? b1->arraysize : b2->arraysize;
size_t k = 0;
for (; k < minlength; ++k) {
b1->array[k] ^= b2->array[k];
}
if (b2->arraysize > b1->arraysize) {
size_t oldsize = b1->arraysize;
if (!bitset_resize(b1, b2->arraysize, false)) return false;
memcpy(b1->array + oldsize, b2->array + oldsize,
(b2->arraysize - oldsize) * sizeof(uint64_t));
}
return true;
}
size_t bitset_symmetric_difference_count(
const bitset_t *CROARING_CBITSET_RESTRICT b1,
const bitset_t *CROARING_CBITSET_RESTRICT b2) {
size_t minlength =
b1->arraysize < b2->arraysize ? b1->arraysize : b2->arraysize;
size_t k = 0;
size_t answer = 0;
for (; k < minlength; ++k) {
answer += roaring_hamming(b1->array[k] ^ b2->array[k]);
}
if (b2->arraysize > b1->arraysize) {
for (; k < b2->arraysize; ++k) {
answer += roaring_hamming(b2->array[k]);
}
} else {
for (; k < b1->arraysize; ++k) {
answer += roaring_hamming(b1->array[k]);
}
}
return answer;
}
bool bitset_trim(bitset_t *bitset) {
size_t newsize = bitset->arraysize;
while (newsize > 0) {
if (bitset->array[newsize - 1] == 0)
newsize -= 1;
else
break;
}
if (bitset->capacity == newsize) return true; // nothing to do
uint64_t *newarray;
if ((newarray = (uint64_t *)roaring_realloc(
bitset->array, sizeof(uint64_t) * newsize)) == NULL) {
return false;
}
bitset->array = newarray;
bitset->capacity = newsize;
bitset->arraysize = newsize;
return true;
}
#ifdef __cplusplus
}
}
} // extern "C" { namespace roaring { namespace internal {
#endif