Bitset updates

This commit is contained in:
John Wellbelove 2022-01-22 16:16:44 +00:00
parent 1f7ebe3ee8
commit e98270ca60
2 changed files with 175 additions and 81 deletions

View File

@ -275,7 +275,8 @@ namespace etl
size_t index; size_t index;
element_t mask; element_t mask;
if (SIZE == 0) { if (SIZE == 0)
{
return false; return false;
} }
else if (SIZE == 1) else if (SIZE == 1)
@ -433,6 +434,11 @@ namespace etl
typename etl::enable_if<etl::is_integral<T>::value, T>::type typename etl::enable_if<etl::is_integral<T>::value, T>::type
value() const value() const
{ {
for (size_t i = sizeof(long long) / sizeof(element_t); i < SIZE; ++i)
{
ETL_ASSERT_AND_RETURN_VALUE(!(pdata[i]), ETL_ERROR(etl::bitset_overflow), T(0));
}
T v = T(0); T v = T(0);
const bool OK = (sizeof(T) * CHAR_BIT) >= (SIZE * BITS_PER_ELEMENT); const bool OK = (sizeof(T) * CHAR_BIT) >= (SIZE * BITS_PER_ELEMENT);
@ -453,6 +459,22 @@ namespace etl
return v; return v;
} }
//*************************************************************************
/// Put to a unsigned long.
//*************************************************************************
unsigned long to_ulong() const
{
return value<unsigned long>();
}
//*************************************************************************
/// Put to a unsigned long long.
//*************************************************************************
unsigned long long to_ullong() const
{
return value<unsigned long long>();
}
//************************************************************************* //*************************************************************************
/// Resets the bitset. /// Resets the bitset.
//************************************************************************* //*************************************************************************
@ -518,7 +540,6 @@ namespace etl
{ {
size_t index; size_t index;
element_t bit; element_t bit;
if (SIZE == 0) if (SIZE == 0)
{ {
@ -546,6 +567,11 @@ namespace etl
//************************************************************************* //*************************************************************************
bool all() const bool all() const
{ {
if (SIZE == 0UL)
{
return true;
}
// All but the last. // All but the last.
for (size_t i = 0UL; i < (SIZE - 1); ++i) for (size_t i = 0UL; i < (SIZE - 1); ++i)
{ {
@ -726,26 +752,37 @@ namespace etl
//************************************************************************* //*************************************************************************
ibitset& operator<<=(size_t shift) ibitset& operator<<=(size_t shift)
{ {
if (SIZE == 0) { if (SIZE != 0UL)
return *this;
}
else if (SIZE == 1)
{ {
pdata[0] <<= shift; // Just one element?
} if (SIZE == 1UL)
else
{
size_t source = NBITS - shift - 1;
size_t destination = NBITS - 1;
for (size_t i = 0UL; i < (NBITS - shift); ++i)
{ {
set(destination--, test(source--)); pdata[0] <<= shift;
} }
else if (shift == BITS_PER_ELEMENT)
for (size_t i = 0UL; i < shift; ++i)
{ {
reset(destination--); for (size_t i = (SIZE - 1); i > 0U; --i)
{
pdata[i] = pdata[i - 1];
}
pdata[0] = 0;
}
else
{
// TODO Optimise.
size_t source = NBITS - shift - 1;
size_t destination = NBITS - 1;
for (size_t i = 0UL; i < (NBITS - shift); ++i)
{
set(destination--, test(source--));
}
for (size_t i = 0UL; i < shift; ++i)
{
reset(destination--);
}
} }
} }
@ -757,26 +794,38 @@ namespace etl
//************************************************************************* //*************************************************************************
ibitset& operator>>=(size_t shift) ibitset& operator>>=(size_t shift)
{ {
if (SIZE == 0) { if (SIZE != 0UL)
return *this;
}
else if (SIZE == 1)
{ {
pdata[0] >>= shift; // Just one element?
} if (SIZE == 1UL)
else
{
size_t source = shift;
size_t destination = 0;
for (size_t i = 0UL; i < (NBITS - shift); ++i)
{ {
set(destination++, test(source++)); pdata[0] >>= shift;
} }
// Shift is the size of an element?
for (size_t i = 0UL; i < shift; ++i) else if (shift == BITS_PER_ELEMENT)
{ {
reset(destination++); for (size_t i = 0UL; i < (SIZE - 1); ++i)
{
pdata[i] = pdata[i + 1];
}
pdata[SIZE - 1] = 0;
}
else
{
// TODO Optimise.
size_t source = shift;
size_t destination = 0UL;
for (size_t i = 0UL; i < (NBITS - shift); ++i)
{
set(destination++, test(source++));
}
for (size_t i = 0UL; i < shift; ++i)
{
reset(destination++);
}
} }
} }
@ -824,46 +873,6 @@ namespace etl
} }
#endif #endif
//*************************************************************************
/// to_ulong
/// Returns an unsigned long represented by the bitset data.
//*************************************************************************
unsigned long to_ulong() const
{
for (size_t i = sizeof(long) / sizeof(element_t); i < SIZE; ++i)
ETL_ASSERT(!(pdata[i]), ETL_ERROR(etl::bitset_overflow));
unsigned long out = 0;
for (size_t i = 0UL; i < SIZE; i++)
{
out += static_cast<unsigned long>(pdata[i] & ((i < SIZE - 1) ? ALL_SET : TOP_MASK)) << (BITS_PER_ELEMENT * i);
}
return out;
}
#if ETL_CPP11_SUPPORTED
//*************************************************************************
/// to_ullong
/// Returns an unsigned long long represented by the bitset data.
//*************************************************************************
unsigned long long to_ullong() const
{
for (size_t i = sizeof(long long) / sizeof(element_t); i < SIZE; ++i)
ETL_ASSERT(!(pdata[i]), ETL_ERROR(etl::bitset_overflow));
unsigned long long out = 0;
for (size_t i = 0ULL; i < SIZE; i++)
{
out += static_cast<unsigned long long>(pdata[i] & ((i < SIZE - 1) ? ALL_SET : TOP_MASK)) << (BITS_PER_ELEMENT * i);
}
return out;
}
#endif
protected: protected:
//************************************************************************* //*************************************************************************
@ -903,8 +912,10 @@ namespace etl
{ {
for (size_t i = 0UL; i < SIZE; ++i) for (size_t i = 0UL; i < SIZE; ++i)
{ {
pdata[i] = ~pdata[i] & (i == SIZE - 1 ? TOP_MASK : ALL_SET); pdata[i] = ~pdata[i];
} }
pdata[SIZE - 1] &= TOP_MASK;
} }
//************************************************************************* //*************************************************************************
@ -1138,13 +1149,21 @@ namespace etl
//************************************************************************* //*************************************************************************
/// Returns a string representing the bitset. /// Returns a string representing the bitset.
//************************************************************************* //*************************************************************************
template<class STRINGT = etl::string<MAXN> > #if ETL_CPP11_SUPPORTED
STRINGT to_string(typename STRINGT::value_type zero = typename STRINGT::value_type('0'), typename STRINGT::value_type one = typename STRINGT::value_type('1')) const template <typename TString = etl::string<MAXN>>
#else
template <typename TString>
#endif
TString to_string(typename TString::value_type zero = typename TString::value_type('0'), typename TString::value_type one = typename TString::value_type('1')) const
{ {
STRINGT result; TString result;
result.assign(MAXN, '\0'); result.resize(MAXN, '\0');
for (size_t i = MAXN; i > 0; --i) {
ETL_ASSERT_AND_RETURN_VALUE((result.size() == MAXN), ETL_ERROR(etl::bitset_overflow), result);
for (size_t i = MAXN; i > 0; --i)
{
result[MAXN - i] = test(i - 1) ? one : zero; result[MAXN - i] = test(i - 1) ? one : zero;
} }
@ -1255,7 +1274,7 @@ namespace etl
private: private:
element_t data[ARRAY_SIZE]; element_t data[ARRAY_SIZE > 0U ? ARRAY_SIZE : 1U];
}; };
//*************************************************************************** //***************************************************************************

View File

@ -749,6 +749,26 @@ namespace
CHECK(data2 == shift11); CHECK(data2 == shift11);
} }
//*************************************************************************
TEST(test_shift_left_operator_shift_element_size)
{
etl::bitset<60> data(0x12345678UL);
etl::bitset<60> shift(0x1234567800UL);
data <<= 8U;
CHECK_EQUAL(shift.value<uint64_t>(), data.value<uint64_t>());
}
//*************************************************************************
TEST(test_shift_left_operator_overflow)
{
etl::bitset<31> data(0x7FFFFFFFUL);
etl::bitset<31> shifted(0x7FFFFFFEUL);
data <<= 1U;
CHECK(data == shifted);
}
//************************************************************************* //*************************************************************************
TEST(test_shift_left_copy_operator) TEST(test_shift_left_copy_operator)
{ {
@ -790,6 +810,16 @@ namespace
CHECK(data2 == shift11); CHECK(data2 == shift11);
} }
//*************************************************************************
TEST(test_shift_right_operator_shift_element_size)
{
etl::bitset<60> data(0x12345678UL);
etl::bitset<60> shift(0x123456UL);
data >>= 8U;
CHECK_EQUAL(shift.value<uint64_t>(), data.value<uint64_t>());
}
//************************************************************************* //*************************************************************************
TEST(test_shift_right_copy_operator) TEST(test_shift_right_copy_operator)
{ {
@ -1091,5 +1121,50 @@ namespace
CHECK_EQUAL(0x34U, s[2]); CHECK_EQUAL(0x34U, s[2]);
CHECK_EQUAL(0x12U, s[3]); CHECK_EQUAL(0x12U, s[3]);
} }
//*************************************************************************
TEST(test_to_string)
{
etl::bitset<32> b(0x12345678UL);
etl::string<32> text = b.to_string('.', '*');
std::string stdtext = b.to_string<std::string>('.', '*');
CHECK_THROW(etl::string<32> text1 = b.to_string<etl::string<30>>('.', '*'), etl::bitset_overflow);
CHECK_EQUAL("...*..*...**.*...*.*.**..****...", text.c_str());
CHECK_EQUAL("...*..*...**.*...*.*.**..****...", stdtext.c_str());
}
//*************************************************************************
TEST(test_issue_497_count_inverted_bits)
{
etl::bitset<5U> bits;
std::bitset<5U> stdbits;
etl::bitset<5U> negbits = ~bits;
std::bitset<5U> stdnegbits = ~stdbits;
CHECK_EQUAL(stdbits.count(), bits.count());
CHECK_EQUAL(stdbits.all(), bits.all());
CHECK_EQUAL(stdnegbits.count(), negbits.count());
CHECK_EQUAL(stdnegbits.all(), negbits.all());
}
//*************************************************************************
TEST(test_issue_497_shifted_zero_sized_bitset)
{
etl::bitset<0> bits;
std::bitset<0> stdbits;
CHECK_EQUAL(stdbits.size(), bits.size());
CHECK_EQUAL(stdbits.none(), bits.none());
CHECK_EQUAL(stdbits.all(), bits.all());
CHECK_EQUAL(stdbits.any(), bits.any());
CHECK_EQUAL(stdbits.count(), bits.count());
CHECK_EQUAL(stdbits.to_ulong(), bits.to_ulong());
CHECK_EQUAL(stdbits.to_ullong(), bits.to_ullong());
etl::bitset<0> shiftbits = bits << 1; // No exception.
}
}; };
} }