Merge branch 'hotfix/bitset' into development

This commit is contained in:
John Wellbelove 2022-01-22 16:17:09 +00:00
commit 4d0682e196
3 changed files with 224 additions and 34 deletions

View File

@ -51,6 +51,7 @@ SOFTWARE.
#include "static_assert.h"
#include "error_handler.h"
#include "span.h"
#include "string.h"
#include "private/minmax_push.h"
@ -120,6 +121,20 @@ namespace etl
}
};
//***************************************************************************
/// Bitset overflow exception.
///\ingroup bitset
//***************************************************************************
class bitset_overflow : public bitset_exception
{
public:
bitset_overflow(string_type file_name_, numeric_type line_number_)
: bitset_exception(ETL_ERROR_TEXT("bitset:overflow", ETL_BITSET_FILE_ID"C"), file_name_, line_number_)
{
}
};
//*************************************************************************
/// The base class for etl::bitset
///\ingroup bitset
@ -260,7 +275,11 @@ namespace etl
size_t index;
element_t mask;
if (SIZE == 1)
if (SIZE == 0)
{
return false;
}
else if (SIZE == 1)
{
index = 0;
mask = element_t(1) << position;
@ -297,7 +316,10 @@ namespace etl
size_t index;
element_t bit;
if (SIZE == 1)
if (SIZE == 0) {
return *this;
}
else if (SIZE == 1)
{
index = 0;
bit = element_t(1) << position;
@ -412,6 +434,11 @@ namespace etl
typename etl::enable_if<etl::is_integral<T>::value, T>::type
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);
const bool OK = (sizeof(T) * CHAR_BIT) >= (SIZE * BITS_PER_ELEMENT);
@ -432,6 +459,22 @@ namespace etl
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.
//*************************************************************************
@ -453,7 +496,11 @@ namespace etl
size_t index;
element_t bit;
if (SIZE == 1)
if (SIZE == 0)
{
return *this;
}
else if (SIZE == 1)
{
index = 0;
bit = element_t(1) << position;
@ -493,8 +540,12 @@ namespace etl
{
size_t index;
element_t bit;
if (SIZE == 1)
if (SIZE == 0)
{
return *this;
}
else if (SIZE == 1)
{
index = 0;
bit = element_t(1) << position;
@ -516,6 +567,11 @@ namespace etl
//*************************************************************************
bool all() const
{
if (SIZE == 0UL)
{
return true;
}
// All but the last.
for (size_t i = 0UL; i < (SIZE - 1); ++i)
{
@ -580,7 +636,11 @@ namespace etl
size_t index;
size_t bit;
if (SIZE == 1)
if (SIZE == 0)
{
return ibitset::npos;
}
else if (SIZE == 1)
{
index = 0;
bit = position;
@ -692,23 +752,37 @@ namespace etl
//*************************************************************************
ibitset& operator<<=(size_t shift)
{
if (SIZE == 1)
if (SIZE != 0UL)
{
pdata[0] <<= shift;
}
else
{
size_t source = NBITS - shift - 1;
size_t destination = NBITS - 1;
for (size_t i = 0UL; i < (NBITS - shift); ++i)
// Just one element?
if (SIZE == 1UL)
{
set(destination--, test(source--));
pdata[0] <<= shift;
}
for (size_t i = 0UL; i < shift; ++i)
else if (shift == BITS_PER_ELEMENT)
{
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--);
}
}
}
@ -720,23 +794,38 @@ namespace etl
//*************************************************************************
ibitset& operator>>=(size_t shift)
{
if (SIZE == 1)
if (SIZE != 0UL)
{
pdata[0] >>= shift;
}
else
{
size_t source = shift;
size_t destination = 0;
for (size_t i = 0UL; i < (NBITS - shift); ++i)
// Just one element?
if (SIZE == 1UL)
{
set(destination++, test(source++));
pdata[0] >>= shift;
}
for (size_t i = 0UL; i < shift; ++i)
// Shift is the size of an element?
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++);
}
}
}
@ -825,6 +914,8 @@ namespace etl
{
pdata[i] = ~pdata[i];
}
pdata[SIZE - 1] &= TOP_MASK;
}
//*************************************************************************
@ -1055,6 +1146,30 @@ namespace etl
return *this;
}
//*************************************************************************
/// Returns a string representing the bitset.
//*************************************************************************
#if ETL_CPP11_SUPPORTED
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
{
TString result;
result.resize(MAXN, '\0');
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;
}
return result;
}
//*************************************************************************
/// operator =
//*************************************************************************
@ -1159,7 +1274,7 @@ namespace etl
private:
element_t data[ARRAY_SIZE];
element_t data[ARRAY_SIZE > 0U ? ARRAY_SIZE : 1U];
};
//***************************************************************************

View File

@ -145,7 +145,7 @@ SOFTWARE.
#endif
// NAN not defined or Rowley CrossWorks
#if !defined(NAN) || defined(__CROSSWORKS_ARM) || defined(ETL_COMPILER_ARM5)
#if !defined(NAN) || defined(__CROSSWORKS_ARM) || defined(ETL_COMPILER_ARM5) || defined(ARDUINO)
#define ETL_NO_CPP_NAN_SUPPORT
#endif

View File

@ -749,6 +749,26 @@ namespace
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)
{
@ -790,6 +810,16 @@ namespace
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)
{
@ -1091,5 +1121,50 @@ namespace
CHECK_EQUAL(0x34U, s[2]);
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.
}
};
}