Added bitset flip and flip_range

This commit is contained in:
Leonardo committed 2020-05-14 16:10:04 -03:00
1 parent bd96dfdc8f
commit 1380d131ea
3 files changed
+186 -15

No files matched your search

+59 -1
View File
@@ -379,7 +379,7 @@ static const char *cmc_string_fmt_bitset = "struct %s "
{ \
_bitset_->buffer[start_index] &= ~start_mask; \
\
for (size_t i = start_index; i < end_index; i++) \
for (size_t i = start_index + 1; i < end_index; i++) \
_bitset_->buffer[i] = 0; \
\
_bitset_->buffer[end_index] &= ~end_mask; \
@@ -395,11 +395,69 @@ static const char *cmc_string_fmt_bitset = "struct %s "
\
bool PFX##_flip(struct SNAME *_bitset_, size_t bit_index) \
{ \
if (!PFX##_impl_resize(_bitset_, bit_index + 1, false)) \
return false; \
\
/* How many bits in a word */ \
const cmc_bitset_word bits = sizeof(cmc_bitset_word) * CHAR_BIT; \
\
size_t i = PFX##_bit_to_index(bit_index); \
\
_bitset_->buffer[i] ^= ((cmc_bitset_word)1) << (bit_index % bits); \
\
_bitset_->flag = cmc_flags.OK; \
\
if (_bitset_->callbacks && _bitset_->callbacks->update) \
_bitset_->callbacks->update(); \
\
return true; \
} \
\
bool PFX##_flip_range(struct SNAME *_bitset_, size_t from, size_t to) \
{ \
if (to < from) \
{ \
_bitset_->flag = cmc_flags.INVALID; \
return false; \
} \
\
if (!PFX##_impl_resize(_bitset_, to + 1, false)) \
return false; \
\
size_t start_index = PFX##_bit_to_index(from); \
size_t end_index = PFX##_bit_to_index(to); \
\
/* How many bits in a word */ \
const cmc_bitset_word bits = sizeof(cmc_bitset_word) * CHAR_BIT; \
\
/* 1111 ... 1111 */ \
const cmc_bitset_word ones = ~((cmc_bitset_word)0); \
\
cmc_bitset_word shift_start = from % bits; \
cmc_bitset_word shift_end = (cmc_bitset_word)(-(to + 1)) % bits; \
\
cmc_bitset_word start_mask = ones << shift_start; \
cmc_bitset_word end_mask = ones >> shift_end; \
\
if (start_index == end_index) \
{ \
_bitset_->buffer[end_index] ^= (start_mask & end_mask); \
} \
else \
{ \
_bitset_->buffer[start_index] ^= start_mask; \
\
for (size_t i = start_index + 1; i < end_index; i++) \
_bitset_->buffer[i] ^= ones; \
\
_bitset_->buffer[end_index] ^= end_mask; \
} \
\
_bitset_->flag = cmc_flags.OK; \
\
if (_bitset_->callbacks && _bitset_->callbacks->update) \
_bitset_->callbacks->update (); \
\
return true; \
} \
\
+38 -1
View File
@@ -197,7 +197,7 @@ _Bool bs_clear_range(struct bitset *_bitset_, size_t from, size_t to)
else
{
_bitset_->buffer[start_index] &= ~start_mask;
for (size_t i = start_index; i < end_index; i++)
for (size_t i = start_index + 1; i < end_index; i++)
_bitset_->buffer[i] = 0;
_bitset_->buffer[end_index] &= ~end_mask;
}
@@ -208,10 +208,47 @@ _Bool bs_clear_range(struct bitset *_bitset_, size_t from, size_t to)
}
_Bool bs_flip(struct bitset *_bitset_, size_t bit_index)
{
if (!bs_impl_resize(_bitset_, bit_index + 1, 0))
return 0;
const cmc_bitset_word bits = sizeof(cmc_bitset_word) * 8;
size_t i = bs_bit_to_index(bit_index);
_bitset_->buffer[i] ^= ((cmc_bitset_word)1) << (bit_index % bits);
_bitset_->flag = cmc_flags.OK;
if (_bitset_->callbacks && _bitset_->callbacks->update)
_bitset_->callbacks->update();
return 1;
}
_Bool bs_flip_range(struct bitset *_bitset_, size_t from, size_t to)
{
if (to < from)
{
_bitset_->flag = cmc_flags.INVALID;
return 0;
}
if (!bs_impl_resize(_bitset_, to + 1, 0))
return 0;
size_t start_index = bs_bit_to_index(from);
size_t end_index = bs_bit_to_index(to);
const cmc_bitset_word bits = sizeof(cmc_bitset_word) * 8;
const cmc_bitset_word ones = ~((cmc_bitset_word)0);
cmc_bitset_word shift_start = from % bits;
cmc_bitset_word shift_end = (cmc_bitset_word)(-(to + 1)) % bits;
cmc_bitset_word start_mask = ones << shift_start;
cmc_bitset_word end_mask = ones >> shift_end;
if (start_index == end_index)
{
_bitset_->buffer[end_index] ^= (start_mask & end_mask);
}
else
{
_bitset_->buffer[start_index] ^= start_mask;
for (size_t i = start_index + 1; i < end_index; i++)
_bitset_->buffer[i] ^= ones;
_bitset_->buffer[end_index] ^= end_mask;
}
_bitset_->flag = cmc_flags.OK;
if (_bitset_->callbacks && _bitset_->callbacks->delete)
_bitset_->callbacks->delete ();
return 1;
}
_Bool bs_put(struct bitset *_bitset_, size_t bit_index)
+89 -13
View File
@@ -13,7 +13,7 @@ CMC_CREATE_UNIT(BitSet, true, {
const size_t word_bits = sizeof(cmc_bitset_word) * CHAR_BIT;
printf("%s", cmc_test_color(5));
printf(" BitSet<"CMC_TO_STRING(CMC_BITSET_WORD_TYPE)">\n");
printf(" BitSet<" CMC_TO_STRING(CMC_BITSET_WORD_TYPE) ">\n");
printf("%s", cmc_test_color(0));
CMC_CREATE_TEST(PFX##_new(), {
@@ -137,14 +137,18 @@ CMC_CREATE_UNIT(BitSet, true, {
bs->buffer[0] = 0;
cmc_assert(bs_set(bs, word_bits - 1));
cmc_assert_equals(CMC_BITSET_WORD_TYPE, ((cmc_bitset_word)1 << (word_bits - 1)), bs->buffer[0]);
cmc_assert_equals(CMC_BITSET_WORD_TYPE,
((cmc_bitset_word)1 << (word_bits - 1)),
bs->buffer[0]);
cmc_assert(bs_set(bs, word_bits * 8 - 1));
cmc_assert_equals(CMC_BITSET_WORD_TYPE, ((cmc_bitset_word)1 << (word_bits - 1)),
cmc_assert_equals(CMC_BITSET_WORD_TYPE,
((cmc_bitset_word)1 << (word_bits - 1)),
bs->buffer[bs_bit_to_index(word_bits * 8 - 1)]);
cmc_assert(bs_set(bs, word_bits * 18 - 2));
cmc_assert_equals(CMC_BITSET_WORD_TYPE, ((cmc_bitset_word)1 << (word_bits - 2)),
cmc_assert_equals(CMC_BITSET_WORD_TYPE,
((cmc_bitset_word)1 << (word_bits - 2)),
bs->buffer[bs_bit_to_index(word_bits * 18 - 2)]);
bs_free(bs);
@@ -161,6 +165,9 @@ CMC_CREATE_UNIT(BitSet, true, {
cmc_assert_equals(uint8_t, 1, bs->buffer[0]);
cmc_assert_equals(int32_t, cmc_flags.OK, bs->flag);
cmc_assert(!bs_set_range(bs, 1, 0));
cmc_assert_equals(int32_t, cmc_flags.INVALID, bs->flag);
bs->buffer[0] = 0;
cmc_assert(bs_set_range(bs, 4, 7)); /* 1111 0000 */
@@ -170,7 +177,8 @@ CMC_CREATE_UNIT(BitSet, true, {
cmc_assert_equals(uint8_t, 244, bs->buffer[0]);
cmc_assert(bs_set_range(bs, word_bits * 6 - 2, word_bits * 6 - 2));
cmc_assert_equals(CMC_BITSET_WORD_TYPE, ((cmc_bitset_word)1 << (word_bits - 2)),
cmc_assert_equals(CMC_BITSET_WORD_TYPE,
((cmc_bitset_word)1 << (word_bits - 2)),
bs->buffer[bs_bit_to_index(word_bits * 6 - 2)]);
// Make sure we have at least word_bits * 40 slots
@@ -180,14 +188,17 @@ CMC_CREATE_UNIT(BitSet, true, {
cmc_assert_equals(CMC_BITSET_WORD_TYPE, (~(cmc_bitset_word)0),
bs->buffer[bs_bit_to_index(word_bits * 20)]);
cmc_assert_equals(CMC_BITSET_WORD_TYPE, 0, bs->buffer[bs_bit_to_index(word_bits * 20 - 1)]);
cmc_assert_equals(CMC_BITSET_WORD_TYPE, 0, bs->buffer[bs_bit_to_index(word_bits * 21 + 1)]);
cmc_assert_equals(CMC_BITSET_WORD_TYPE, 0,
bs->buffer[bs_bit_to_index(word_bits * 20 - 1)]);
cmc_assert_equals(CMC_BITSET_WORD_TYPE, 0,
bs->buffer[bs_bit_to_index(word_bits * 21 + 1)]);
cmc_assert(bs_set_range(bs, 0, word_bits * 100 - 1));
cmc_assert_equals(size_t, 100, bs->capacity);
for (size_t i = 0; i < bs->capacity; i++)
cmc_assert_equals(CMC_BITSET_WORD_TYPE, ~((cmc_bitset_word)0), bs->buffer[i]);
cmc_assert_equals(CMC_BITSET_WORD_TYPE, ~((cmc_bitset_word)0),
bs->buffer[i]);
bs_free(bs);
});
@@ -219,6 +230,9 @@ CMC_CREATE_UNIT(BitSet, true, {
cmc_assert_not_equals(ptr, NULL, bs);
cmc_assert_equals(CMC_BITSET_WORD_TYPE, 0, bs->buffer[0]);
cmc_assert(!bs_clear_range(bs, 1, 0));
cmc_assert_equals(int32_t, cmc_flags.INVALID, bs->flag);
cmc_assert(bs_clear_range(bs, 0, word_bits * 100 - 1));
cmc_assert_equals(size_t, 100, bs->capacity);
@@ -231,13 +245,73 @@ CMC_CREATE_UNIT(BitSet, true, {
for (size_t i = 0; i < bs->capacity; i++)
bs->buffer[i] = ~((cmc_bitset_word)0);
cmc_assert(bs_clear_range(bs, 0, word_bits * 200 - 1));
cmc_assert(bs_set_range(bs, 0, word_bits * 100 - 1));
cmc_assert(bs_clear_range(bs, 0, word_bits * 100 - 1));
cmc_assert_equals(size_t, 200, bs->capacity);
cmc_assert_equals(size_t, 100, bs->capacity);
for (size_t i = 0; i < bs->capacity; i++)
cmc_assert_equals(size_t, 0, bs->buffer[0]);
cmc_assert(bs_clear_range(bs, 0, word_bits * 200 - 1));
cmc_assert_equals(size_t, 200, bs->capacity);
bs_free(bs);
});
CMC_CREATE_TEST(PFX##_flip(), {
struct bitset *bs = bs_new(word_bits * 10 - 1);
cmc_assert_not_equals(ptr, NULL, bs);
cmc_assert_equals(CMC_BITSET_WORD_TYPE, 0, bs->buffer[0]);
cmc_assert(bs_flip(bs, 0));
cmc_assert_equals(CMC_BITSET_WORD_TYPE, 1, bs->buffer[0]);
cmc_assert(bs_flip(bs, 0));
cmc_assert_equals(CMC_BITSET_WORD_TYPE, 0, bs->buffer[0]);
cmc_assert(bs_set_range(bs, 0, 2)); // 0111
cmc_assert_equals(CMC_BITSET_WORD_TYPE, 7, bs->buffer[0]);
cmc_assert(bs_flip(bs, 1)); // 0101
cmc_assert_equals(CMC_BITSET_WORD_TYPE, 5, bs->buffer[0]);
cmc_assert(bs_flip(bs, word_bits * 100 - 1));
cmc_assert_equals(size_t, 100, bs->capacity);
bs_free(bs);
});
CMC_CREATE_TEST(PFX##_flip_range(), {
struct bitset *bs = bs_new(word_bits * 10 - 1);
cmc_assert_not_equals(ptr, NULL, bs);
cmc_assert_equals(CMC_BITSET_WORD_TYPE, 0, bs->buffer[0]);
cmc_assert(bs_flip_range(bs, 0, 0));
cmc_assert_equals(CMC_BITSET_WORD_TYPE, 1, bs->buffer[0]);
cmc_assert(bs_flip_range(bs, 0, 0));
cmc_assert_equals(CMC_BITSET_WORD_TYPE, 0, bs->buffer[0]);
cmc_assert(bs_flip_range(bs, 1, 4)); // 0001 1110
cmc_assert_equals(CMC_BITSET_WORD_TYPE, 30, bs->buffer[0]);
cmc_assert(bs_flip_range(bs, 2, 3)); // 0001 0010
cmc_assert_equals(CMC_BITSET_WORD_TYPE, 18, bs->buffer[0]);
cmc_assert(bs_flip_range(bs, 0, 2)); // 0001 0101
cmc_assert_equals(CMC_BITSET_WORD_TYPE, 21, bs->buffer[0]);
bs->buffer[0] = 0;
cmc_assert(bs_flip_range(bs, 0, word_bits * 100 - 1));
cmc_assert_equals(size_t, 100, bs->capacity);
for (size_t i = 0; i < bs->capacity; i++)
cmc_assert_equals(CMC_BITSET_WORD_TYPE, ~((cmc_bitset_word)0),
bs->buffer[i]);
bs_free(bs);
});
@@ -267,7 +341,7 @@ CMC_CREATE_UNIT(BitSetIter, true, {
const size_t word_bits = sizeof(cmc_bitset_word) * CHAR_BIT;
printf("%s", cmc_test_color(5));
printf(" BitSet<"CMC_TO_STRING(CMC_BITSET_WORD_TYPE)">\n");
printf(" BitSet<" CMC_TO_STRING(CMC_BITSET_WORD_TYPE) ">\n");
printf("%s", cmc_test_color(0));
CMC_CREATE_TEST(PFX##_iter_start(), {
@@ -284,10 +358,12 @@ int main(void)
{
int result = BitSet() + BitSetIter();
printf(" +---------------------------------------------------------------+");
printf(
" +---------------------------------------------------------------+");
printf("\n");
printf(" | BitSet Suit : %-47s |\n", result == 0 ? "PASSED" : "FAILED");
printf(" +---------------------------------------------------------------+");
printf(
" +---------------------------------------------------------------+");
printf("\n\n\n");
return result;