1/**
2* Copyright 2013, GitHub, Inc
3* Copyright 2009-2013, Daniel Lemire, Cliff Moon,
4* David McIntosh, Robert Becho, Google Inc. and Veronika Zenz
5*
6* This program is free software; you can redistribute it and/or
7* modify it under the terms of the GNU General Public License
8* as published by the Free Software Foundation; either version 2
9* of the License, or (at your option) any later version.
10*
11* This program is distributed in the hope that it will be useful,
12* but WITHOUT ANY WARRANTY; without even the implied warranty of
13* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14* GNU General Public License for more details.
15*
16* You should have received a copy of the GNU General Public License
17* along with this program; if not, see <http://www.gnu.org/licenses/>.
18*/
19#include "cache.h"
20#include "ewok.h"
2122
#define EWAH_MASK(x) ((eword_t)1 << (x % BITS_IN_EWORD))
23#define EWAH_BLOCK(x) (x / BITS_IN_EWORD)
2425
struct bitmap *bitmap_new(void)
26{
27struct bitmap *bitmap = xmalloc(sizeof(struct bitmap));
28bitmap->words = xcalloc(32, sizeof(eword_t));
29bitmap->word_alloc = 32;
30return bitmap;
31}
3233
void bitmap_set(struct bitmap *self, size_t pos)
34{
35size_t block = EWAH_BLOCK(pos);
3637
if (block >= self->word_alloc) {
38size_t old_size = self->word_alloc;
39self->word_alloc = block * 2;
40REALLOC_ARRAY(self->words, self->word_alloc);
41memset(self->words + old_size, 0x0,
42(self->word_alloc - old_size) * sizeof(eword_t));
43}
4445
self->words[block] |= EWAH_MASK(pos);
46}
4748
int bitmap_get(struct bitmap *self, size_t pos)
49{
50size_t block = EWAH_BLOCK(pos);
51return block < self->word_alloc &&
52(self->words[block] & EWAH_MASK(pos)) != 0;
53}
5455
struct ewah_bitmap *bitmap_to_ewah(struct bitmap *bitmap)
56{
57struct ewah_bitmap *ewah = ewah_new();
58size_t i, running_empty_words = 0;
59eword_t last_word = 0;
6061
for (i = 0; i < bitmap->word_alloc; ++i) {
62if (bitmap->words[i] == 0) {
63running_empty_words++;
64continue;
65}
6667
if (last_word != 0)
68ewah_add(ewah, last_word);
6970
if (running_empty_words > 0) {
71ewah_add_empty_words(ewah, 0, running_empty_words);
72running_empty_words = 0;
73}
7475
last_word = bitmap->words[i];
76}
7778
ewah_add(ewah, last_word);
79return ewah;
80}
8182
struct bitmap *ewah_to_bitmap(struct ewah_bitmap *ewah)
83{
84struct bitmap *bitmap = bitmap_new();
85struct ewah_iterator it;
86eword_t blowup;
87size_t i = 0;
8889
ewah_iterator_init(&it, ewah);
9091
while (ewah_iterator_next(&blowup, &it)) {
92ALLOC_GROW(bitmap->words, i + 1, bitmap->word_alloc);
93bitmap->words[i++] = blowup;
94}
9596
bitmap->word_alloc = i;
97return bitmap;
98}
99100
void bitmap_and_not(struct bitmap *self, struct bitmap *other)
101{
102const size_t count = (self->word_alloc < other->word_alloc) ?
103self->word_alloc : other->word_alloc;
104105
size_t i;
106107
for (i = 0; i < count; ++i)
108self->words[i] &= ~other->words[i];
109}
110111
void bitmap_or_ewah(struct bitmap *self, struct ewah_bitmap *other)
112{
113size_t original_size = self->word_alloc;
114size_t other_final = (other->bit_size / BITS_IN_EWORD) + 1;
115size_t i = 0;
116struct ewah_iterator it;
117eword_t word;
118119
if (self->word_alloc < other_final) {
120self->word_alloc = other_final;
121REALLOC_ARRAY(self->words, self->word_alloc);
122memset(self->words + original_size, 0x0,
123(self->word_alloc - original_size) * sizeof(eword_t));
124}
125126
ewah_iterator_init(&it, other);
127128
while (ewah_iterator_next(&word, &it))
129self->words[i++] |= word;
130}
131132
void bitmap_each_bit(struct bitmap *self, ewah_callback callback, void *data)
133{
134size_t pos = 0, i;
135136
for (i = 0; i < self->word_alloc; ++i) {
137eword_t word = self->words[i];
138uint32_t offset;
139140
if (word == (eword_t)~0) {
141for (offset = 0; offset < BITS_IN_EWORD; ++offset)
142callback(pos++, data);
143} else {
144for (offset = 0; offset < BITS_IN_EWORD; ++offset) {
145if ((word >> offset) == 0)
146break;
147148
offset += ewah_bit_ctz64(word >> offset);
149callback(pos + offset, data);
150}
151pos += BITS_IN_EWORD;
152}
153}
154}
155156
size_t bitmap_popcount(struct bitmap *self)
157{
158size_t i, count = 0;
159160
for (i = 0; i < self->word_alloc; ++i)
161count += ewah_bit_popcount64(self->words[i]);
162163
return count;
164}
165166
int bitmap_equals(struct bitmap *self, struct bitmap *other)
167{
168struct bitmap *big, *small;
169size_t i;
170171
if (self->word_alloc < other->word_alloc) {
172small = self;
173big = other;
174} else {
175small = other;
176big = self;
177}
178179
for (i = 0; i < small->word_alloc; ++i) {
180if (small->words[i] != big->words[i])
181return 0;
182}
183184
for (; i < big->word_alloc; ++i) {
185if (big->words[i] != 0)
186return 0;
187}
188189
return 1;
190}
191192
void bitmap_reset(struct bitmap *bitmap)
193{
194memset(bitmap->words, 0x0, bitmap->word_alloc * sizeof(eword_t));
195}
196197
void bitmap_free(struct bitmap *bitmap)
198{
199if (bitmap == NULL)
200return;
201202
free(bitmap->words);
203free(bitmap);
204}