mirror of
https://github.com/ETLCPP/etl.git
synced 2026-06-29 22:08:45 +08:00
Work in progress for etl::bitset::extract
This commit is contained in:
parent
3d3f87564d
commit
18a1c76ec6
@ -401,12 +401,62 @@ namespace etl
|
||||
return v;
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Extract an value from multiple elements.
|
||||
//*************************************************************************
|
||||
template <typename T>
|
||||
ETL_CONSTEXPR14
|
||||
typename etl::make_unsigned<T>::type extract_from_multiple_elements(const element_type* pbuffer,
|
||||
int element_index,
|
||||
size_t active_bits_in_msb,
|
||||
size_t length) const ETL_NOEXCEPT
|
||||
{
|
||||
typedef typename etl::make_unsigned<T>::type unsigned_t;
|
||||
|
||||
unsigned_t value(0);
|
||||
|
||||
// Extract the first element, if partially filled.
|
||||
if (active_bits_in_msb < Bits_Per_Element)
|
||||
{
|
||||
element_type mask = ~(~element_type(0) << active_bits_in_msb);
|
||||
value = pbuffer[element_index] & mask;
|
||||
length -= active_bits_in_msb;
|
||||
if (length >= Bits_Per_Element)
|
||||
{
|
||||
value = value << Bits_Per_Element;
|
||||
}
|
||||
--element_index;
|
||||
}
|
||||
|
||||
// Loop through the fully filled elements
|
||||
while (length >= Bits_Per_Element)
|
||||
{
|
||||
value |= pbuffer[element_index];
|
||||
length -= Bits_Per_Element;
|
||||
if (length >= Bits_Per_Element)
|
||||
{
|
||||
value = value << Bits_Per_Element;
|
||||
}
|
||||
--element_index;
|
||||
}
|
||||
|
||||
// Extract the last element, if partially filled.
|
||||
if (length != 0)
|
||||
{
|
||||
value = value << length;
|
||||
element_type mask = ~(~element_type(0) << length);
|
||||
value |= (pbuffer[element_index] >> (Bits_Per_Element - length)) & mask;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Extract an integral value from an arbitary position and length.
|
||||
//*************************************************************************
|
||||
template <typename T>
|
||||
ETL_CONSTEXPR14
|
||||
T extract_from_buffer(const_pointer pbuffer, size_t position, size_t length) const ETL_NOEXCEPT
|
||||
typename etl::make_unsigned<T>::type extract_from_buffer(const_pointer pbuffer, size_t position, size_t length) const ETL_NOEXCEPT
|
||||
{
|
||||
typedef typename etl::make_unsigned<T>::type unsigned_t;
|
||||
|
||||
@ -428,37 +478,13 @@ namespace etl
|
||||
// Get the number of active bits in the msb element
|
||||
size_t active_bits_in_msb = (position + length) - (Msb_Element_Index * Bits_Per_Element);
|
||||
|
||||
// Extract the first element if partially filled.
|
||||
// Start with index of the element containing the msb.
|
||||
int element_index = Msb_Element_Index;
|
||||
|
||||
if (active_bits_in_msb < Bits_Per_Element)
|
||||
{
|
||||
element_type mask = ~(~element_type(0) << active_bits_in_msb);
|
||||
value |= pbuffer[element_index] & mask;
|
||||
length -= active_bits_in_msb;
|
||||
--element_index;
|
||||
}
|
||||
|
||||
// Loop through the fully filled elements
|
||||
while (length >= Bits_Per_Element)
|
||||
{
|
||||
value <<= Bits_Per_Element;
|
||||
value |= pbuffer[element_index];
|
||||
length -= Bits_Per_Element;
|
||||
--element_index;
|
||||
}
|
||||
|
||||
// Check if the last element is partially filled and extract.
|
||||
if (length != 0)
|
||||
{
|
||||
value <<= length;
|
||||
element_type mask = ~(~element_type(0) << length);
|
||||
value |= (pbuffer[element_index] >> (Bits_Per_Element - length)) & mask;
|
||||
}
|
||||
value = extract_from_multiple_elements<T>(pbuffer, element_index, active_bits_in_msb, length);
|
||||
}
|
||||
|
||||
return static_cast<T>(value);
|
||||
return value;
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
@ -466,7 +492,7 @@ namespace etl
|
||||
//*************************************************************************
|
||||
template <typename T, size_t Position, size_t Length>
|
||||
ETL_CONSTEXPR14
|
||||
typename etl::enable_if<value_is_in_one_element<Position, Length, Bits_Per_Element>::value, T>::type
|
||||
typename etl::enable_if<value_is_in_one_element<Position, Length, Bits_Per_Element>::value, typename etl::make_unsigned<T>::type>::type
|
||||
extract_from_buffer(const_pointer pbuffer) const
|
||||
{
|
||||
typedef typename etl::make_unsigned<T>::type unsigned_t;
|
||||
@ -475,9 +501,7 @@ namespace etl
|
||||
const unsigned_t Mask = ~(~0 << Length);
|
||||
const unsigned_t Shift = Position % Bits_Per_Element;
|
||||
|
||||
unsigned_t value = static_cast<unsigned_t>(pbuffer[Element_Index] >> Shift) & Mask;
|
||||
|
||||
return static_cast<T>(value);
|
||||
return static_cast<unsigned_t>(pbuffer[Element_Index] >> Shift) & Mask;
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
@ -485,13 +509,11 @@ namespace etl
|
||||
//*************************************************************************
|
||||
template <typename T, size_t Position, size_t Length>
|
||||
ETL_CONSTEXPR14
|
||||
typename etl::enable_if<!value_is_in_one_element<Position, Length, Bits_Per_Element>::value, T>::type
|
||||
typename etl::enable_if<!value_is_in_one_element<Position, Length, Bits_Per_Element>::value, typename etl::make_unsigned<T>::type>::type
|
||||
extract_from_buffer(const_pointer pbuffer) const
|
||||
{
|
||||
typedef typename etl::make_unsigned<T>::type unsigned_t;
|
||||
|
||||
unsigned_t value(0);
|
||||
|
||||
|
||||
const int Msb_Element_Index = (Position + Length - 1) >> etl::log2<Bits_Per_Element>::value;
|
||||
|
||||
// Start with index of the element containing the msb.
|
||||
@ -501,35 +523,9 @@ namespace etl
|
||||
size_t length = Length;
|
||||
|
||||
// Get the number of active bits in the first element
|
||||
size_t active_bits_in_element = ((Position + Length - 1) % Bits_Per_Element) + 1;
|
||||
size_t active_bits_in_msb = ((Position + Length - 1) % Bits_Per_Element) + 1;
|
||||
|
||||
// Extract the first element if partially filled.
|
||||
if (active_bits_in_element < Bits_Per_Element)
|
||||
{
|
||||
element_type mask = ~(~element_type(0) << active_bits_in_element);
|
||||
value |= pbuffer[element_index] & mask;
|
||||
length -= active_bits_in_element;
|
||||
--element_index;
|
||||
}
|
||||
|
||||
// Loop through the fully filled elements
|
||||
while (length >= Bits_Per_Element)
|
||||
{
|
||||
value <<= Bits_Per_Element;
|
||||
value |= pbuffer[element_index];
|
||||
length -= Bits_Per_Element;
|
||||
--element_index;
|
||||
}
|
||||
|
||||
// Check if the last element is partially filled and extract.
|
||||
if (length != 0)
|
||||
{
|
||||
value <<= length;
|
||||
element_type mask = ~(~element_type(0) << length);
|
||||
value |= (pbuffer[element_index] >> (Bits_Per_Element - length)) & mask;
|
||||
}
|
||||
|
||||
return static_cast<T>(value);
|
||||
return extract_from_multiple_elements<T>(pbuffer, element_index, active_bits_in_msb, length);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
@ -2208,7 +2204,16 @@ namespace etl
|
||||
{
|
||||
ETL_ASSERT_OR_RETURN_VALUE((position + length) <= Active_Bits, ETL_ERROR(bitset_overflow), 0);
|
||||
|
||||
return ibitset.extract_from_buffer<T>(buffer, position, length);
|
||||
typedef typename etl::make_unsigned<T>::type unsigned_t;
|
||||
|
||||
unsigned_t value = ibitset.template extract_from_buffer<T>(buffer, position, length);;
|
||||
|
||||
if ((length != etl::integral_limits<T>::bits) && etl::integral_limits<T>::is_signed)
|
||||
{
|
||||
value = etl::sign_extend<T>(value, length);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
@ -2221,7 +2226,16 @@ namespace etl
|
||||
{
|
||||
ETL_STATIC_ASSERT((Position + Length) <= Active_Bits, "Position/Length overflows bitset");
|
||||
|
||||
return ibitset.extract_from_buffer<T, Position, Length>(buffer);
|
||||
typedef typename etl::make_unsigned<T>::type unsigned_t;
|
||||
|
||||
unsigned_t value = ibitset.template extract_from_buffer<T, Position, Length>(buffer);
|
||||
|
||||
if ETL_IF_CONSTEXPR((Length != etl::integral_limits<T>::bits) && etl::integral_limits<T>::is_signed)
|
||||
{
|
||||
value = etl::sign_extend<T, Length>(value);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
@ -3981,7 +3995,7 @@ namespace etl
|
||||
{
|
||||
ETL_ASSERT_OR_RETURN_VALUE((position + length) <= Active_Bits, ETL_ERROR(bitset_overflow), 0);
|
||||
|
||||
return ibitset.extract_from_buffer<T>(pbuffer, position, length);
|
||||
return ibitset.template extract_from_buffer<T>(pbuffer, position, length);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
@ -3994,7 +4008,7 @@ namespace etl
|
||||
{
|
||||
ETL_STATIC_ASSERT((Position + Length) <= Active_Bits, "Position/Length overflows bitset");
|
||||
|
||||
return ibitset.extract_from_buffer<T, Position, Length>(pbuffer);
|
||||
return ibitset.template extract_from_buffer<T, Position, Length>(pbuffer);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
|
||||
@ -165,7 +165,7 @@ etl_version=$(echo $etl_version_raw | sed -e 's/\r//g') # Remove trailing \r
|
||||
# Get the compiler versions
|
||||
#******************************************************************************
|
||||
gcc_compiler=$(g++ --version | grep g++)
|
||||
clang_compiler=$(clang++ --version | grep clang++)
|
||||
clang_compiler=$(clang++ --version | grep clang)
|
||||
|
||||
#******************************************************************************
|
||||
# GCC
|
||||
|
||||
@ -2172,6 +2172,83 @@ namespace
|
||||
//uint8_t v1 = b.extract<uint8_t, 27, 6>();
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_extract_6_bit_int8_t_with_run_time_parameters)
|
||||
{
|
||||
ETL_CONSTEXPR14 etl::bitset<32> b(0x12345678UL);
|
||||
|
||||
auto v = b.extract<int8_t>(1, 6);
|
||||
|
||||
CHECK_EQUAL_HEX(int8_t(0xF8), (b.extract<int8_t>(0, 6)));
|
||||
CHECK_EQUAL_HEX(int8_t(0xFC), (b.extract<int8_t>(1, 6)));
|
||||
CHECK_EQUAL_HEX(int8_t(0x1E), (b.extract<int8_t>(2, 6)));
|
||||
CHECK_EQUAL_HEX(int8_t(0x0F), (b.extract<int8_t>(3, 6)));
|
||||
CHECK_EQUAL_HEX(int8_t(0xE7), (b.extract<int8_t>(4, 6)));
|
||||
CHECK_EQUAL_HEX(int8_t(0xF3), (b.extract<int8_t>(5, 6)));
|
||||
CHECK_EQUAL_HEX(int8_t(0x19), (b.extract<int8_t>(6, 6)));
|
||||
CHECK_EQUAL_HEX(int8_t(0xEC), (b.extract<int8_t>(7, 6)));
|
||||
CHECK_EQUAL_HEX(int8_t(0x16), (b.extract<int8_t>(8, 6)));
|
||||
CHECK_EQUAL_HEX(int8_t(0xEB), (b.extract<int8_t>(9, 6)));
|
||||
CHECK_EQUAL_HEX(int8_t(0x15), (b.extract<int8_t>(10, 6)));
|
||||
CHECK_EQUAL_HEX(int8_t(0x0A), (b.extract<int8_t>(11, 6)));
|
||||
CHECK_EQUAL_HEX(int8_t(0x05), (b.extract<int8_t>(12, 6)));
|
||||
CHECK_EQUAL_HEX(int8_t(0xE2), (b.extract<int8_t>(13, 6)));
|
||||
CHECK_EQUAL_HEX(int8_t(0x11), (b.extract<int8_t>(14, 6)));
|
||||
CHECK_EQUAL_HEX(int8_t(0xE8), (b.extract<int8_t>(15, 6)));
|
||||
CHECK_EQUAL_HEX(int8_t(0xF4), (b.extract<int8_t>(16, 6)));
|
||||
CHECK_EQUAL_HEX(int8_t(0x1A), (b.extract<int8_t>(17, 6)));
|
||||
CHECK_EQUAL_HEX(int8_t(0x0D), (b.extract<int8_t>(18, 6)));
|
||||
CHECK_EQUAL_HEX(int8_t(0x06), (b.extract<int8_t>(19, 6)));
|
||||
CHECK_EQUAL_HEX(int8_t(0xE3), (b.extract<int8_t>(20, 6)));
|
||||
CHECK_EQUAL_HEX(int8_t(0x11), (b.extract<int8_t>(21, 6)));
|
||||
CHECK_EQUAL_HEX(int8_t(0x08), (b.extract<int8_t>(22, 6)));
|
||||
CHECK_EQUAL_HEX(int8_t(0xE4), (b.extract<int8_t>(23, 6)));
|
||||
CHECK_EQUAL_HEX(int8_t(0x12), (b.extract<int8_t>(24, 6)));
|
||||
CHECK_EQUAL_HEX(int8_t(0x09), (b.extract<int8_t>(25, 6)));
|
||||
CHECK_EQUAL_HEX(int8_t(0x04), (b.extract<int8_t>(26, 6)));
|
||||
|
||||
CHECK_THROW(b.extract<int8_t>(26, 7), etl::bitset_overflow);
|
||||
CHECK_THROW(b.extract<int8_t>(27, 6), etl::bitset_overflow);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_extract_6_bit_int8_t_with_template_parameters)
|
||||
{
|
||||
ETL_CONSTEXPR14 etl::bitset<32> b(0x12345678UL);
|
||||
|
||||
CHECK_EQUAL_HEX(int8_t(0xF8), (b.extract<int8_t, 0, 6>()));
|
||||
CHECK_EQUAL_HEX(int8_t(0xFC), (b.extract<int8_t, 1, 6>()));
|
||||
CHECK_EQUAL_HEX(int8_t(0x1E), (b.extract<int8_t, 2, 6>()));
|
||||
CHECK_EQUAL_HEX(int8_t(0x0F), (b.extract<int8_t, 3, 6>()));
|
||||
CHECK_EQUAL_HEX(int8_t(0xE7), (b.extract<int8_t, 4, 6>()));
|
||||
CHECK_EQUAL_HEX(int8_t(0xF3), (b.extract<int8_t, 5, 6>()));
|
||||
CHECK_EQUAL_HEX(int8_t(0x19), (b.extract<int8_t, 6, 6>()));
|
||||
CHECK_EQUAL_HEX(int8_t(0xEC), (b.extract<int8_t, 7, 6>()));
|
||||
CHECK_EQUAL_HEX(int8_t(0x16), (b.extract<int8_t, 8, 6>()));
|
||||
CHECK_EQUAL_HEX(int8_t(0xEB), (b.extract<int8_t, 9, 6>()));
|
||||
CHECK_EQUAL_HEX(int8_t(0x15), (b.extract<int8_t, 10, 6>()));
|
||||
CHECK_EQUAL_HEX(int8_t(0x0A), (b.extract<int8_t, 11, 6>()));
|
||||
CHECK_EQUAL_HEX(int8_t(0x05), (b.extract<int8_t, 12, 6>()));
|
||||
CHECK_EQUAL_HEX(int8_t(0xE2), (b.extract<int8_t, 13, 6>()));
|
||||
CHECK_EQUAL_HEX(int8_t(0x11), (b.extract<int8_t, 14, 6>()));
|
||||
CHECK_EQUAL_HEX(int8_t(0xE8), (b.extract<int8_t, 15, 6>()));
|
||||
CHECK_EQUAL_HEX(int8_t(0xF4), (b.extract<int8_t, 16, 6>()));
|
||||
CHECK_EQUAL_HEX(int8_t(0x1A), (b.extract<int8_t, 17, 6>()));
|
||||
CHECK_EQUAL_HEX(int8_t(0x0D), (b.extract<int8_t, 18, 6>()));
|
||||
CHECK_EQUAL_HEX(int8_t(0x06), (b.extract<int8_t, 19, 6>()));
|
||||
CHECK_EQUAL_HEX(int8_t(0xE3), (b.extract<int8_t, 20, 6>()));
|
||||
CHECK_EQUAL_HEX(int8_t(0x11), (b.extract<int8_t, 21, 6>()));
|
||||
CHECK_EQUAL_HEX(int8_t(0x08), (b.extract<int8_t, 22, 6>()));
|
||||
CHECK_EQUAL_HEX(int8_t(0xE4), (b.extract<int8_t, 23, 6>()));
|
||||
CHECK_EQUAL_HEX(int8_t(0x12), (b.extract<int8_t, 24, 6>()));
|
||||
CHECK_EQUAL_HEX(int8_t(0x09), (b.extract<int8_t, 25, 6>()));
|
||||
CHECK_EQUAL_HEX(int8_t(0x04), (b.extract<int8_t, 26, 6>()));
|
||||
|
||||
// The lines below should static assert.
|
||||
//int8_t v1 = b.extract<int8_t, 26, 7>();
|
||||
//int8_t v1 = b.extract<int8_t, 27, 6>();
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_extract_uint8_t_with_run_time_parameters)
|
||||
{
|
||||
|
||||
@ -3400,14 +3400,30 @@
|
||||
<None Include="..\..\scripts\update_version.py">
|
||||
<Filter>Tests\Scripts</Filter>
|
||||
</None>
|
||||
<None Include="..\..\.github\workflows\clang-c++11.yml" />
|
||||
<None Include="..\..\.github\workflows\clang-c++14.yml" />
|
||||
<None Include="..\..\.github\workflows\clang-c++17.yml" />
|
||||
<None Include="..\..\.github\workflows\clang-c++20.yml" />
|
||||
<None Include="..\..\.github\workflows\gcc-c++11.yml" />
|
||||
<None Include="..\..\.github\workflows\gcc-c++14.yml" />
|
||||
<None Include="..\..\.github\workflows\gcc-c++17.yml" />
|
||||
<None Include="..\..\.github\workflows\gcc-c++20.yml" />
|
||||
<None Include="..\..\.github\workflows\clang-c++11.yml">
|
||||
<Filter>Resource Files\CI\Github</Filter>
|
||||
</None>
|
||||
<None Include="..\..\.github\workflows\clang-c++14.yml">
|
||||
<Filter>Resource Files\CI\Github</Filter>
|
||||
</None>
|
||||
<None Include="..\..\.github\workflows\clang-c++17.yml">
|
||||
<Filter>Resource Files\CI\Github</Filter>
|
||||
</None>
|
||||
<None Include="..\..\.github\workflows\clang-c++20.yml">
|
||||
<Filter>Resource Files\CI\Github</Filter>
|
||||
</None>
|
||||
<None Include="..\..\.github\workflows\gcc-c++11.yml">
|
||||
<Filter>Resource Files\CI\Github</Filter>
|
||||
</None>
|
||||
<None Include="..\..\.github\workflows\gcc-c++14.yml">
|
||||
<Filter>Resource Files\CI\Github</Filter>
|
||||
</None>
|
||||
<None Include="..\..\.github\workflows\gcc-c++17.yml">
|
||||
<Filter>Resource Files\CI\Github</Filter>
|
||||
</None>
|
||||
<None Include="..\..\.github\workflows\gcc-c++20.yml">
|
||||
<Filter>Resource Files\CI\Github</Filter>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Text Include="..\..\support\Release notes.txt">
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user