46
46
template <typename T>
47
47
inline std::enable_if_t <std::is_integral_v<T>, T>
48
48
bfe_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 ;
50
51
const uint32_t pos = bit_start;
51
52
const uint32_t len = num_bits;
52
53
@@ -55,7 +56,8 @@ bfe_slow(const T source, const uint32_t bit_start, const uint32_t num_bits) {
55
56
return 0ULL ;
56
57
57
58
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);
59
61
if (std::is_unsigned_v<T> || len == 0 )
60
62
sbit = 0 ;
61
63
else
@@ -67,16 +69,17 @@ bfe_slow(const T source, const uint32_t bit_start, const uint32_t num_bits) {
67
69
if (bit_start > msb)
68
70
return -sbit;
69
71
70
- std::bitset<CHAR_BIT * sizeof (T)> result_bitset;
72
+ std::bitset<std::numeric_limits<unsigned char >::digits * sizeof (T)>
73
+ result_bitset;
71
74
for (uint8_t i = 0 ; i <= msb; ++i)
72
75
result_bitset[i] =
73
76
(i < len && pos + i <= msb) ? source_bitset[pos + i] : sbit;
74
77
return result_bitset.to_ullong ();
75
78
}
76
79
77
80
template <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 ();
80
83
T max_value = std::numeric_limits<T>::max ();
81
84
std::random_device rd;
82
85
std::mt19937::result_type seed =
@@ -91,7 +94,9 @@ template <typename T> bool test(const char *Msg, int N) {
91
94
.count ());
92
95
93
96
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);
95
100
96
101
// Define a small overshoot so that we adequately test out-of-range cases
97
102
// without sacrificing depth of testing of valid start+length combinations
@@ -105,7 +110,7 @@ template <typename T> bool test(const char *Msg, int N) {
105
110
std::vector<uint32_t > starts (N, 0 );
106
111
std::vector<uint32_t > lengths (N, 0 );
107
112
for (int i = 0 ; i < N; ++i) {
108
- sources[i] = rd_source (gen);
113
+ sources[i] = static_cast <T>( rd_source (gen) );
109
114
starts[i] = rd_start (gen);
110
115
lengths[i] = rd_length (gen);
111
116
}
@@ -172,6 +177,8 @@ template <typename T> bool test(const char *Msg, int N) {
172
177
173
178
int main () {
174
179
const int N = 1000 ;
180
+ assert (test<int8_t >(" int8" , N));
181
+ assert (test<uint8_t >(" uint8" , N));
175
182
assert (test<int16_t >(" int16" , N));
176
183
assert (test<uint16_t >(" uint16" , N));
177
184
assert (test<int32_t >(" int32" , N));
0 commit comments