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; } } }
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 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; } } }
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 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; }
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); } }