implemented bounded_bitset::find_first(...)

This commit is contained in:
Francisco 2021-04-16 09:23:12 +01:00 committed by Francisco Paisana
parent db9dd85783
commit 3f15fc2811
2 changed files with 94 additions and 2 deletions

View File

@ -26,6 +26,31 @@ constexpr uint32_t ceil_div(uint32_t x, uint32_t y)
return (x + y - 1) / y; return (x + y - 1) / y;
} }
template <typename Integer>
Integer mask_trailing_ones(size_t N)
{
static_assert(std::is_unsigned<Integer>::value, "T must be unsigned integer");
return N == 0 ? 0 : (static_cast<Integer>(-1) >> (sizeof(Integer) * 8U - N));
}
template <typename Integer>
Integer mask_leading_ones(size_t N)
{
return ~mask_trailing_ones<Integer>(8U * sizeof(Integer) - N);
}
template <typename Integer>
Integer mask_trailing_zeros(size_t N)
{
return mask_leading_ones<Integer>(8U * sizeof(Integer) - N);
}
template <typename Integer>
Integer mask_leading_zeros(size_t N)
{
return mask_trailing_ones<Integer>(8U * sizeof(Integer) - N);
}
template <size_t N, bool reversed = false> template <size_t N, bool reversed = false>
class bounded_bitset class bounded_bitset
{ {
@ -100,8 +125,7 @@ public:
bounded_bitset<N, reversed>& fill(size_t startpos, size_t endpos, bool value = true) bounded_bitset<N, reversed>& fill(size_t startpos, size_t endpos, bool value = true)
{ {
assert_within_bounds_(startpos, false); assert_range_bounds_(startpos, endpos);
assert_within_bounds_(endpos, false);
// NOTE: can be optimized // NOTE: can be optimized
if (value) { if (value) {
for (size_t i = startpos; i < endpos; ++i) { for (size_t i = startpos; i < endpos; ++i) {
@ -115,6 +139,37 @@ public:
return *this; return *this;
} }
int find_first(size_t startpos, size_t endpos, bool value = true) const noexcept
{
assert_range_bounds_(startpos, endpos);
if (startpos == endpos) {
return -1;
}
size_t startword = startpos / bits_per_word;
size_t lastword = (endpos - 1) / bits_per_word;
for (size_t i = startword; i <= lastword; ++i) {
word_t w = buffer[i];
if (not value) {
w = ~w;
}
if (i == startword) {
size_t offset = startpos % bits_per_word;
w &= mask_trailing_zeros<word_t>(offset);
}
if (i == lastword) {
size_t offset = (endpos - 1) % bits_per_word;
w &= mask_trailing_ones<word_t>(offset + 1);
}
if (w != 0) {
return static_cast<int>(i * bits_per_word + (bits_per_word - __builtin_clzl(w) - 1));
}
}
return -1;
}
bool all() const noexcept bool all() const noexcept
{ {
const size_t nw = nof_words_(); const size_t nw = nof_words_();
@ -307,6 +362,15 @@ private:
size()); size());
} }
void assert_range_bounds_(size_t startpos, size_t endpos) const
{
srsran_assert(startpos <= endpos and endpos <= size(),
"ERROR: range [%zd, %zd) out-of-bounds for bitsize of size=%zd",
startpos,
endpos,
size());
}
static word_t maskbit(size_t pos) { return (static_cast<word_t>(1)) << (pos % bits_per_word); } static word_t maskbit(size_t pos) { return (static_cast<word_t>(1)) << (pos % bits_per_word); }
static size_t max_nof_words_() { return (N - 1) / bits_per_word + 1; } static size_t max_nof_words_() { return (N - 1) / bits_per_word + 1; }

View File

@ -13,6 +13,14 @@
#include "srsran/adt/bounded_bitset.h" #include "srsran/adt/bounded_bitset.h"
#include "srsran/common/test_common.h" #include "srsran/common/test_common.h"
void test_bit_operations()
{
TESTASSERT(0 == srsran::mask_trailing_ones<uint32_t>(0));
TESTASSERT(0b11 == srsran::mask_trailing_ones<uint32_t>(2));
TESTASSERT(0b11111111 == srsran::mask_trailing_ones<uint8_t>(8));
TESTASSERT(0b1111 == srsran::mask_trailing_ones<uint8_t>(4));
}
int test_zero_bitset() int test_zero_bitset()
{ {
srsran::bounded_bitset<25> mask; srsran::bounded_bitset<25> mask;
@ -176,14 +184,34 @@ int test_bitset_resize()
return SRSRAN_SUCCESS; return SRSRAN_SUCCESS;
} }
void test_bitset_find()
{
{
srsran::bounded_bitset<25> bitset(6);
bitset.set(2);
TESTASSERT(bitset.find_first(0, 6) == 2);
TESTASSERT(bitset.find_first(3, 6) == -1);
bitset.set(5);
TESTASSERT(bitset.find_first(3, 6) == 5);
}
{
srsran::bounded_bitset<100> bitset(95);
bitset.set(94);
TESTASSERT(bitset.find_first(0, 93) == -1);
TESTASSERT(bitset.find_first(0, bitset.size()) == 94);
}
}
int main() int main()
{ {
test_bit_operations();
TESTASSERT(test_zero_bitset() == SRSRAN_SUCCESS); TESTASSERT(test_zero_bitset() == SRSRAN_SUCCESS);
TESTASSERT(test_ones_bitset() == SRSRAN_SUCCESS); TESTASSERT(test_ones_bitset() == SRSRAN_SUCCESS);
TESTASSERT(test_bitset_set() == SRSRAN_SUCCESS); TESTASSERT(test_bitset_set() == SRSRAN_SUCCESS);
TESTASSERT(test_bitset_bitwise_oper() == SRSRAN_SUCCESS); TESTASSERT(test_bitset_bitwise_oper() == SRSRAN_SUCCESS);
TESTASSERT(test_bitset_print() == SRSRAN_SUCCESS); TESTASSERT(test_bitset_print() == SRSRAN_SUCCESS);
TESTASSERT(test_bitset_resize() == SRSRAN_SUCCESS); TESTASSERT(test_bitset_resize() == SRSRAN_SUCCESS);
test_bitset_find();
printf("Success\n"); printf("Success\n");
return 0; return 0;
} }