static size_t add_empty_word(struct ewah_bitmap *self, int v) { int no_literal = (rlw_get_literal_words(self->rlw) == 0); eword_t run_len = rlw_get_running_len(self->rlw); if (no_literal && run_len == 0) { rlw_set_run_bit(self->rlw, v); assert(rlw_get_run_bit(self->rlw) == v); } if (no_literal && rlw_get_run_bit(self->rlw) == v && run_len < RLW_LARGEST_RUNNING_COUNT) { rlw_set_running_len(self->rlw, run_len + 1); assert(rlw_get_running_len(self->rlw) == run_len + 1); return 0; } else { buffer_push_rlw(self, 0); assert(rlw_get_running_len(self->rlw) == 0); assert(rlw_get_run_bit(self->rlw) == 0); assert(rlw_get_literal_words(self->rlw) == 0); rlw_set_run_bit(self->rlw, v); assert(rlw_get_run_bit(self->rlw) == v); rlw_set_running_len(self->rlw, 1); assert(rlw_get_running_len(self->rlw) == 1); assert(rlw_get_literal_words(self->rlw) == 0); return 1; } }
static inline bool next_word(struct rlw_iterator *it) { if (it->pointer >= it->size) return false; it->rlw.word = &it->buffer[it->pointer]; it->pointer += rlw_get_literal_words(it->rlw.word) + 1; it->rlw.literal_words = rlw_get_literal_words(it->rlw.word); it->rlw.running_len = rlw_get_running_len(it->rlw.word); it->rlw.running_bit = rlw_get_run_bit(it->rlw.word); it->rlw.literal_word_offset = 0; return true; }
static void read_new_rlw(struct ewah_iterator *it) { const eword_t *word = NULL; it->literals = 0; it->compressed = 0; while (1) { word = &it->buffer[it->pointer]; it->rl = rlw_get_running_len(word); it->lw = rlw_get_literal_words(word); it->b = rlw_get_run_bit(word); if (it->rl || it->lw) return; if (it->pointer < it->buffer_size - 1) { it->pointer++; } else { it->pointer = it->buffer_size; return; } } }
void ewah_each_bit(struct ewah_bitmap *self, void (*callback)(size_t, void*), void *payload) { size_t pos = 0; size_t pointer = 0; size_t k; while (pointer < self->buffer_size) { eword_t *word = &self->buffer[pointer]; if (rlw_get_run_bit(word)) { size_t len = rlw_get_running_len(word) * BITS_IN_EWORD; for (k = 0; k < len; ++k, ++pos) callback(pos, payload); } else { pos += rlw_get_running_len(word) * BITS_IN_EWORD; } ++pointer; for (k = 0; k < rlw_get_literal_words(word); ++k) { int c; /* todo: zero count optimization */ for (c = 0; c < BITS_IN_EWORD; ++c, ++pos) { if ((self->buffer[pointer] & ((eword_t)1 << c)) != 0) callback(pos, payload); } ++pointer; } } }
void ewah_add_dirty_words( struct ewah_bitmap *self, const eword_t *buffer, size_t number, int negate) { size_t literals, can_add; while (1) { literals = rlw_get_literal_words(self->rlw); can_add = min_size(number, RLW_LARGEST_LITERAL_COUNT - literals); rlw_set_literal_words(self->rlw, literals + can_add); if (self->buffer_size + can_add >= self->alloc_size) buffer_grow(self, (self->buffer_size + can_add) * 3 / 2); if (negate) { size_t i; for (i = 0; i < can_add; ++i) self->buffer[self->buffer_size++] = ~buffer[i]; } else { memcpy(self->buffer + self->buffer_size, buffer, can_add * sizeof(eword_t)); self->buffer_size += can_add; } self->bit_size += can_add * BITS_IN_EWORD; if (number - can_add == 0) break; buffer_push_rlw(self, 0); buffer += can_add; number -= can_add; } }
static size_t add_literal(struct ewah_bitmap *self, eword_t new_data) { eword_t current_num = rlw_get_literal_words(self->rlw); if (current_num >= RLW_LARGEST_LITERAL_COUNT) { buffer_push_rlw(self, 0); rlw_set_literal_words(self->rlw, 1); buffer_push(self, new_data); return 2; } rlw_set_literal_words(self->rlw, current_num + 1); /* sanity check */ assert(rlw_get_literal_words(self->rlw) == current_num + 1); buffer_push(self, new_data); return 1; }
void ewah_set(struct ewah_bitmap *self, size_t i) { const size_t dist = (i + BITS_IN_EWORD) / BITS_IN_EWORD - (self->bit_size + BITS_IN_EWORD - 1) / BITS_IN_EWORD; assert(i >= self->bit_size); self->bit_size = i + 1; if (dist > 0) { if (dist > 1) add_empty_words(self, 0, dist - 1); add_literal(self, (eword_t)1 << (i % BITS_IN_EWORD)); return; } if (rlw_get_literal_words(self->rlw) == 0) { rlw_set_running_len(self->rlw, rlw_get_running_len(self->rlw) - 1); add_literal(self, (eword_t)1 << (i % BITS_IN_EWORD)); return; } self->buffer[self->buffer_size - 1] |= ((eword_t)1 << (i % BITS_IN_EWORD)); /* check if we just completed a stream of 1s */ if (self->buffer[self->buffer_size - 1] == (eword_t)(~0)) { self->buffer[--self->buffer_size] = 0; rlw_set_literal_words(self->rlw, rlw_get_literal_words(self->rlw) - 1); add_empty_word(self, 1); } }
void ewah_not(struct ewah_bitmap *self) { size_t pointer = 0; while (pointer < self->buffer_size) { eword_t *word = &self->buffer[pointer]; size_t literals, k; rlw_xor_run_bit(word); ++pointer; literals = rlw_get_literal_words(word); for (k = 0; k < literals; ++k) { self->buffer[pointer] = ~self->buffer[pointer]; ++pointer; } } }
static size_t add_empty_words(struct ewah_bitmap *self, int v, size_t number) { size_t added = 0; eword_t runlen, can_add; if (rlw_get_run_bit(self->rlw) != v && rlw_size(self->rlw) == 0) { rlw_set_run_bit(self->rlw, v); } else if (rlw_get_literal_words(self->rlw) != 0 || rlw_get_run_bit(self->rlw) != v) { buffer_push_rlw(self, 0); if (v) rlw_set_run_bit(self->rlw, v); added++; } runlen = rlw_get_running_len(self->rlw); can_add = min_size(number, RLW_LARGEST_RUNNING_COUNT - runlen); rlw_set_running_len(self->rlw, runlen + can_add); number -= can_add; while (number >= RLW_LARGEST_RUNNING_COUNT) { buffer_push_rlw(self, 0); added++; if (v) rlw_set_run_bit(self->rlw, v); rlw_set_running_len(self->rlw, RLW_LARGEST_RUNNING_COUNT); number -= RLW_LARGEST_RUNNING_COUNT; } if (number > 0) { buffer_push_rlw(self, 0); added++; if (v) rlw_set_run_bit(self->rlw, v); rlw_set_running_len(self->rlw, number); } return added; }