1
0
mirror of https://github.com/TomHarte/CLK.git synced 2026-04-24 05:18:36 +00:00

Test, improve BitStream.

This commit is contained in:
Thomas Harte
2025-02-20 22:42:02 -05:00
parent 88ffcbc62b
commit 9162c86e21
7 changed files with 35 additions and 21 deletions
+10 -6
View File
@@ -10,6 +10,8 @@
#include "BitReverse.hpp"
#include "Sizes.hpp"
#include <cstdint>
#include <functional>
namespace Numeric {
@@ -23,7 +25,7 @@ namespace Numeric {
template <int max_bits, bool lsb_first>
class BitStream {
public:
using IntT = min_int_size_t<max_bits + 8>;
using IntT = min_int_for_bits_t<max_bits>;
BitStream(std::function<uint8_t(void)> next_byte) : next_byte_(next_byte) {}
@@ -33,6 +35,9 @@ public:
/// `rbits` is ignored if `bits` is non-zero.
template <size_t bits = 0>
IntT next([[maybe_unused]] const size_t rbits = 0) {
static_assert(bits <= max_bits);
static constexpr size_t ShiftBitSize = sizeof(ShiftIntT) * 8;
const size_t required = bits ? bits : rbits;
while(enqueued_ < required) {
uint8_t next = next_byte_();
@@ -40,11 +45,11 @@ public:
next = bit_reverse(next);
}
input_ |= IntT(next) << (BitSize - 8 - enqueued_);
input_ |= ShiftIntT(next) << (ShiftBitSize - 8 - enqueued_);
enqueued_ += 8;
}
const auto result = IntT(input_ >> (BitSize - required));
const auto result = IntT(input_ >> (ShiftBitSize - required));
input_ <<= required;
enqueued_ -= required;
return result;
@@ -53,10 +58,9 @@ public:
private:
std::function<uint8_t(void)> next_byte_;
using ShiftIntT = min_int_for_bits_t<max_bits + 7>;
ShiftIntT input_{};
size_t enqueued_{};
IntT input_{};
static constexpr size_t BitSize = sizeof(IntT) * 8;
};
}
+1 -1
View File
@@ -77,6 +77,6 @@ private:
IntType value_ = 0;
};
template <uint64_t polynomial> class LFSRv: public LFSR<typename MinIntTypeValue<polynomial>::type, polynomial> {};
template <uint64_t polynomial> class LFSRv: public LFSR<min_int_for_value_t<polynomial>, polynomial> {};
}
+15 -9
View File
@@ -30,7 +30,7 @@ template <int size> using uint_t = typename uint_t_impl<size>::type;
* uint64_t.
*/
template <uint64_t max_value>
struct MinIntTypeValue {
struct MinIntForValue {
using type =
std::conditional_t<
max_value <= std::numeric_limits<uint8_t>::max(), uint8_t,
@@ -43,7 +43,7 @@ struct MinIntTypeValue {
>
>;
};
template <uint64_t max_value> using min_int_value_t = typename MinIntTypeValue<max_value>::type;
template <uint64_t max_value> using min_int_for_value_t = typename MinIntForValue<max_value>::type;
/*!
Maps to the smallest integral type that can hold at least `max_bits` bits, from the following options:
@@ -53,19 +53,25 @@ template <uint64_t max_value> using min_int_value_t = typename MinIntTypeValue<m
* uint32_t; or
* uint64_t.
*/
template <int max_bits>
struct MinIntTypeSize {
static_assert(max_bits <= 64, "Only integers up to 64 bits are supported");
template <int min_bits>
struct MinIntForBits {
static_assert(min_bits <= 64, "Only integers up to 64 bits are supported");
using type =
std::conditional_t<
max_bits <= 8, uint8_t,
min_bits <= 8, uint8_t,
std::conditional_t<
max_bits <= 16, uint16_t,
min_bits <= 16, uint16_t,
std::conditional_t<
max_bits <= 32, uint32_t,
min_bits <= 32, uint32_t,
uint64_t
>
>
>;
};
template <uint64_t max_value> using min_int_size_t = typename MinIntTypeValue<max_value>::type;
template <int min_bits> using min_int_for_bits_t = typename MinIntForBits<min_bits>::type;
static_assert(std::is_same_v<min_int_for_bits_t<7>, uint8_t>);
static_assert(std::is_same_v<min_int_for_bits_t<8>, uint8_t>);
static_assert(std::is_same_v<min_int_for_bits_t<9>, uint16_t>);
static_assert(std::is_same_v<min_int_for_bits_t<16>, uint16_t>);
static_assert(std::is_same_v<min_int_for_bits_t<17>, uint32_t>);