Git fork
at reftables-rust 311 lines 7.0 kB view raw
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 "git-compat-util.h" 20#include "ewok.h" 21 22#define EWAH_MASK(x) ((eword_t)1 << (x % BITS_IN_EWORD)) 23#define EWAH_BLOCK(x) (x / BITS_IN_EWORD) 24 25struct bitmap *bitmap_word_alloc(size_t word_alloc) 26{ 27 struct bitmap *bitmap = xmalloc(sizeof(struct bitmap)); 28 CALLOC_ARRAY(bitmap->words, word_alloc); 29 bitmap->word_alloc = word_alloc; 30 return bitmap; 31} 32 33struct bitmap *bitmap_new(void) 34{ 35 return bitmap_word_alloc(32); 36} 37 38struct bitmap *bitmap_dup(const struct bitmap *src) 39{ 40 struct bitmap *dst = bitmap_word_alloc(src->word_alloc); 41 COPY_ARRAY(dst->words, src->words, src->word_alloc); 42 return dst; 43} 44 45static void bitmap_grow(struct bitmap *self, size_t word_alloc) 46{ 47 size_t old_size = self->word_alloc; 48 ALLOC_GROW(self->words, word_alloc, self->word_alloc); 49 memset(self->words + old_size, 0x0, 50 (self->word_alloc - old_size) * sizeof(eword_t)); 51} 52 53void bitmap_set(struct bitmap *self, size_t pos) 54{ 55 size_t block = EWAH_BLOCK(pos); 56 57 bitmap_grow(self, block + 1); 58 self->words[block] |= EWAH_MASK(pos); 59} 60 61void bitmap_unset(struct bitmap *self, size_t pos) 62{ 63 size_t block = EWAH_BLOCK(pos); 64 65 if (block < self->word_alloc) 66 self->words[block] &= ~EWAH_MASK(pos); 67} 68 69int bitmap_get(struct bitmap *self, size_t pos) 70{ 71 size_t block = EWAH_BLOCK(pos); 72 return block < self->word_alloc && 73 (self->words[block] & EWAH_MASK(pos)) != 0; 74} 75 76struct ewah_bitmap *bitmap_to_ewah(struct bitmap *bitmap) 77{ 78 struct ewah_bitmap *ewah = ewah_new(); 79 size_t i, running_empty_words = 0; 80 eword_t last_word = 0; 81 82 for (i = 0; i < bitmap->word_alloc; ++i) { 83 if (bitmap->words[i] == 0) { 84 running_empty_words++; 85 continue; 86 } 87 88 if (last_word != 0) 89 ewah_add(ewah, last_word); 90 91 if (running_empty_words > 0) { 92 ewah_add_empty_words(ewah, 0, running_empty_words); 93 running_empty_words = 0; 94 } 95 96 last_word = bitmap->words[i]; 97 } 98 99 ewah_add(ewah, last_word); 100 return ewah; 101} 102 103struct bitmap *ewah_to_bitmap(struct ewah_bitmap *ewah) 104{ 105 struct bitmap *bitmap = bitmap_new(); 106 struct ewah_iterator it; 107 eword_t blowup; 108 size_t i = 0; 109 110 ewah_iterator_init(&it, ewah); 111 112 while (ewah_iterator_next(&blowup, &it)) { 113 ALLOC_GROW(bitmap->words, i + 1, bitmap->word_alloc); 114 bitmap->words[i++] = blowup; 115 } 116 117 bitmap->word_alloc = i; 118 return bitmap; 119} 120 121void bitmap_and_not(struct bitmap *self, struct bitmap *other) 122{ 123 const size_t count = (self->word_alloc < other->word_alloc) ? 124 self->word_alloc : other->word_alloc; 125 126 size_t i; 127 128 for (i = 0; i < count; ++i) 129 self->words[i] &= ~other->words[i]; 130} 131 132void bitmap_or(struct bitmap *self, const struct bitmap *other) 133{ 134 size_t i; 135 136 bitmap_grow(self, other->word_alloc); 137 for (i = 0; i < other->word_alloc; i++) 138 self->words[i] |= other->words[i]; 139} 140 141int ewah_bitmap_is_subset(struct ewah_bitmap *self, struct bitmap *other) 142{ 143 struct ewah_iterator it; 144 eword_t word; 145 size_t i; 146 147 ewah_iterator_init(&it, self); 148 149 for (i = 0; i < other->word_alloc; i++) { 150 if (!ewah_iterator_next(&word, &it)) { 151 /* 152 * If we reached the end of `self`, and haven't 153 * rejected `self` as a possible subset of 154 * `other` yet, then we are done and `self` is 155 * indeed a subset of `other`. 156 */ 157 return 1; 158 } 159 if (word & ~other->words[i]) { 160 /* 161 * Otherwise, compare the next two pairs of 162 * words. If the word from `self` has bit(s) not 163 * in the word from `other`, `self` is not a 164 * subset of `other`. 165 */ 166 return 0; 167 } 168 } 169 170 /* 171 * If we got to this point, there may be zero or more words 172 * remaining in `self`, with no remaining words left in `other`. 173 * If there are any bits set in the remaining word(s) in `self`, 174 * then `self` is not a subset of `other`. 175 */ 176 while (ewah_iterator_next(&word, &it)) 177 if (word) 178 return 0; 179 180 /* `self` is definitely a subset of `other` */ 181 return 1; 182} 183 184void bitmap_or_ewah(struct bitmap *self, struct ewah_bitmap *other) 185{ 186 size_t original_size = self->word_alloc; 187 size_t other_final = (other->bit_size / BITS_IN_EWORD) + 1; 188 size_t i = 0; 189 struct ewah_iterator it; 190 eword_t word; 191 192 if (self->word_alloc < other_final) { 193 self->word_alloc = other_final; 194 REALLOC_ARRAY(self->words, self->word_alloc); 195 memset(self->words + original_size, 0x0, 196 (self->word_alloc - original_size) * sizeof(eword_t)); 197 } 198 199 ewah_iterator_init(&it, other); 200 201 while (ewah_iterator_next(&word, &it)) 202 self->words[i++] |= word; 203} 204 205size_t bitmap_popcount(struct bitmap *self) 206{ 207 size_t i, count = 0; 208 209 for (i = 0; i < self->word_alloc; ++i) 210 count += ewah_bit_popcount64(self->words[i]); 211 212 return count; 213} 214 215size_t ewah_bitmap_popcount(struct ewah_bitmap *self) 216{ 217 struct ewah_iterator it; 218 eword_t word; 219 size_t count = 0; 220 221 ewah_iterator_init(&it, self); 222 223 while (ewah_iterator_next(&word, &it)) 224 count += ewah_bit_popcount64(word); 225 226 return count; 227} 228 229int bitmap_is_empty(struct bitmap *self) 230{ 231 size_t i; 232 for (i = 0; i < self->word_alloc; i++) 233 if (self->words[i]) 234 return 0; 235 return 1; 236} 237 238int bitmap_equals(struct bitmap *self, struct bitmap *other) 239{ 240 struct bitmap *big, *small; 241 size_t i; 242 243 if (self->word_alloc < other->word_alloc) { 244 small = self; 245 big = other; 246 } else { 247 small = other; 248 big = self; 249 } 250 251 for (i = 0; i < small->word_alloc; ++i) { 252 if (small->words[i] != big->words[i]) 253 return 0; 254 } 255 256 for (; i < big->word_alloc; ++i) { 257 if (big->words[i] != 0) 258 return 0; 259 } 260 261 return 1; 262} 263 264int bitmap_equals_ewah(struct bitmap *self, struct ewah_bitmap *other) 265{ 266 struct ewah_iterator it; 267 eword_t word; 268 size_t i = 0; 269 270 ewah_iterator_init(&it, other); 271 272 while (ewah_iterator_next(&word, &it)) 273 if (word != (i < self->word_alloc ? self->words[i++] : 0)) 274 return 0; 275 276 for (; i < self->word_alloc; i++) 277 if (self->words[i]) 278 return 0; 279 280 return 1; 281} 282 283int bitmap_is_subset(struct bitmap *self, struct bitmap *other) 284{ 285 size_t common_size, i; 286 287 if (self->word_alloc < other->word_alloc) 288 common_size = self->word_alloc; 289 else { 290 common_size = other->word_alloc; 291 for (i = common_size; i < self->word_alloc; i++) { 292 if (self->words[i]) 293 return 1; 294 } 295 } 296 297 for (i = 0; i < common_size; i++) { 298 if (self->words[i] & ~other->words[i]) 299 return 1; 300 } 301 return 0; 302} 303 304void bitmap_free(struct bitmap *bitmap) 305{ 306 if (!bitmap) 307 return; 308 309 free(bitmap->words); 310 free(bitmap); 311}