4646template <typename T>
4747inline std::enable_if_t <std::is_integral_v<T>, T>
4848bfe_slow (const T source, const uint32_t bit_start, const uint32_t num_bits) {
49- const uint32_t msb = CHAR_BIT * sizeof (T) - 1 ;
49+ const uint32_t msb =
50+ std::numeric_limits<unsigned char >::digits * sizeof (T) - 1 ;
5051 const uint32_t pos = bit_start;
5152 const uint32_t len = num_bits;
5253
@@ -55,7 +56,8 @@ bfe_slow(const T source, const uint32_t bit_start, const uint32_t num_bits) {
5556 return 0ULL ;
5657
5758 T sbit;
58- std::bitset<CHAR_BIT * sizeof (T)> source_bitset (source);
59+ std::bitset<std::numeric_limits<unsigned char >::digits * sizeof (T)>
60+ source_bitset (source);
5961 if (std::is_unsigned_v<T> || len == 0 )
6062 sbit = 0 ;
6163 else
@@ -67,16 +69,17 @@ bfe_slow(const T source, const uint32_t bit_start, const uint32_t num_bits) {
6769 if (bit_start > msb)
6870 return -sbit;
6971
70- std::bitset<CHAR_BIT * sizeof (T)> result_bitset;
72+ std::bitset<std::numeric_limits<unsigned char >::digits * sizeof (T)>
73+ result_bitset;
7174 for (uint8_t i = 0 ; i <= msb; ++i)
7275 result_bitset[i] =
7376 (i < len && pos + i <= msb) ? source_bitset[pos + i] : sbit;
7477 return result_bitset.to_ullong ();
7578}
7679
7780template <typename T> bool test (const char *Msg, int N) {
78- uint32_t bit_width = CHAR_BIT * sizeof (T);
79- T min_value = std::numeric_limits<T>::min ();
81+ uint32_t bit_width = std::numeric_limits< unsigned char >::digits * sizeof (T);
82+ T min_value = std::numeric_limits<T>::lowest ();
8083 T max_value = std::numeric_limits<T>::max ();
8184 std::random_device rd;
8285 std::mt19937::result_type seed =
@@ -91,7 +94,9 @@ template <typename T> bool test(const char *Msg, int N) {
9194 .count ());
9295
9396 std::mt19937 gen (seed);
94- std::uniform_int_distribution<T> rd_source (min_value, max_value);
97+ // Support for char type with uniform_int_distribution isn't universal
98+ using RandomDataT = std::conditional_t <sizeof (T) == 1 , int , T>;
99+ std::uniform_int_distribution<RandomDataT> rd_source (min_value, max_value);
95100
96101 // Define a small overshoot so that we adequately test out-of-range cases
97102 // without sacrificing depth of testing of valid start+length combinations
@@ -105,7 +110,7 @@ template <typename T> bool test(const char *Msg, int N) {
105110 std::vector<uint32_t > starts (N, 0 );
106111 std::vector<uint32_t > lengths (N, 0 );
107112 for (int i = 0 ; i < N; ++i) {
108- sources[i] = rd_source (gen);
113+ sources[i] = static_cast <T>( rd_source (gen) );
109114 starts[i] = rd_start (gen);
110115 lengths[i] = rd_length (gen);
111116 }
@@ -172,6 +177,8 @@ template <typename T> bool test(const char *Msg, int N) {
172177
173178int main () {
174179 const int N = 1000 ;
180+ assert (test<int8_t >(" int8" , N));
181+ assert (test<uint8_t >(" uint8" , N));
175182 assert (test<int16_t >(" int16" , N));
176183 assert (test<uint16_t >(" uint16" , N));
177184 assert (test<int32_t >(" int32" , N));
0 commit comments