Commit 03ae07ab authored by Andreas Schmidt's avatar Andreas Schmidt

Improve bitmap efficiency and tests

parent f10b2e3e
Pipeline #3130 passed with stages
in 1 minute and 49 seconds
......@@ -28,31 +28,70 @@ Bitmap *Bitmap_create(bool initialValue, uint32_t elementCount)
void Bitmap_set_range_0(Bitmap *bitmap, uint32_t start, uint32_t length)
{
uint32_t i = 0;
// TODO: highly inefficient - optimize
for(i = 0; i < length; i++) {
Bitmap_set_0(bitmap, start + i);
}
uint32_t start_byte = start / 32;
uint32_t start_bit = start % 32;
uint32_t end_byte = (start + length) / 32;
uint32_t end_bit = (start + length) % 32;
uint32_t full_mask = ~0u;
if (start_byte == end_byte) {
uint32_t mask = (full_mask << end_bit) ^ (full_mask << start_bit);
bitmap->data[start_byte] ^= (bitmap->data[start_byte] & mask);
} else {
uint32_t start_mask = full_mask << start_bit;
bitmap->data[start_byte] ^= (bitmap->data[start_byte] & start_mask);
for (uint32_t current_byte = start_byte + 1; current_byte < end_byte; ++current_byte) {
bitmap->data[current_byte] = 0;
}
uint32_t end_mask = ~(full_mask << end_bit);
bitmap->data[end_byte] ^= (bitmap->data[end_byte] & end_mask);
}
}
void Bitmap_set_range_1(Bitmap *bitmap, uint32_t start, uint32_t length)
{
uint32_t i = 0;
// TODO: highly inefficient - optimize
for(i = 0; i < length; i++) {
Bitmap_set_1(bitmap, start + i);
}
uint32_t start_byte = start / 32;
uint32_t start_bit = start % 32;
uint32_t end_byte = (start + length) / 32;
uint32_t end_bit = (start + length) % 32;
uint32_t full_mask = ~0u;
if (start_byte == end_byte) {
uint32_t mask = (full_mask << end_bit) ^ (full_mask << start_bit);
bitmap->data[start_byte] |= mask;
} else {
uint32_t start_mask = full_mask << start_bit;
bitmap->data[start_byte] |= start_mask;
for (uint32_t current_byte = start_byte + 1; current_byte < end_byte; ++current_byte) {
bitmap->data[current_byte] = full_mask;
}
uint32_t end_mask = ~(full_mask << end_bit);
bitmap->data[end_byte] |= end_mask;
}
}
uint32_t Bitmap_sum_ones(Bitmap *bitmap, uint32_t start, uint32_t length)
{
uint32_t sum = 0;
uint32_t i = 0;
// TODO: highly inefficient - optimize
for(i = 0; i < length; i++) {
sum += (Bitmap_get(bitmap, start + i) == true);
uint32_t start_byte = start / 32;
uint32_t start_bit = start % 32;
uint32_t end_byte = (start + length) / 32;
uint32_t end_bit = (start + length) % 32;
uint32_t full_mask = ~0u;
if (start_byte == end_byte) {
uint32_t mask = (full_mask << end_bit) ^ (full_mask << start_bit);
return __builtin_popcount(bitmap->data[start_byte] & mask);
} else {
uint32_t start_mask = full_mask << start_bit;
uint32_t sum = __builtin_popcount(bitmap->data[start_byte] & start_mask);
for (uint32_t current_byte = start_byte + 1; current_byte < end_byte; ++current_byte) {
sum += __builtin_popcount(bitmap->data[current_byte]);
}
uint32_t end_mask = ~(full_mask << end_bit);
sum += __builtin_popcount(bitmap->data[end_byte] & end_mask);
return sum;
}
return sum;
}
uint32_t Bitmap_sum_zeros(Bitmap *bitmap, uint32_t start, uint32_t length)
......
......@@ -54,12 +54,22 @@ TEST_F(BitmapTest, GetRange)
TEST_F(BitmapTest, SetRange)
{
ASSERT_EQ(5, Bitmap_sum_ones(bitmap, 1, 5));
ASSERT_EQ(0, Bitmap_sum_zeros(bitmap, 1, 5));
Bitmap_set_range(bitmap, 2, 2, false);
ASSERT_FALSE(Bitmap_get(bitmap, 2));
ASSERT_FALSE(Bitmap_get(bitmap, 3));
ASSERT_TRUE(Bitmap_get(bitmap, 4));
ASSERT_EQ(3, Bitmap_sum_ones(bitmap, 1, 5));
ASSERT_EQ(2, Bitmap_sum_zeros(bitmap, 1, 5));
ASSERT_EQ(500, Bitmap_sum_ones(bitmap, 17, 500));
ASSERT_EQ(0, Bitmap_sum_zeros(bitmap, 17, 500));
Bitmap_set_range(bitmap, 2, 300, false);
ASSERT_TRUE(Bitmap_get(bitmap, 1));
for (int i = 2; i < 302; ++i) {
ASSERT_FALSE(Bitmap_get(bitmap, i));
}
ASSERT_TRUE(Bitmap_get(bitmap, 302));
Bitmap_set_range(bitmap, 150, 100, true);
ASSERT_FALSE(Bitmap_get(bitmap, 149));
for (int i = 150; i < 250; ++i) {
ASSERT_TRUE(Bitmap_get(bitmap, i));
}
ASSERT_FALSE(Bitmap_get(bitmap, 250));
ASSERT_EQ(300, Bitmap_sum_ones(bitmap, 1, 500));
ASSERT_EQ(200, Bitmap_sum_zeros(bitmap, 1, 500));
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment