File tree Expand file tree Collapse file tree 2 files changed +28
-6
lines changed Expand file tree Collapse file tree 2 files changed +28
-6
lines changed Original file line number Diff line number Diff line change @@ -971,10 +971,15 @@ bit_cast(const UInt<Bits> &from) {
971
971
template <typename T>
972
972
[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t <cpp::is_big_int_v<T>, bool >
973
973
has_single_bit (T value) {
974
- for (auto word : value.val )
975
- if (cpp::has_single_bit (word))
976
- return true ;
977
- return false ;
974
+ int bits = 0 ;
975
+ for (auto word : value.val ) {
976
+ if (word == 0 )
977
+ continue ;
978
+ bits += count_ones (word);
979
+ if (bits > 1 )
980
+ return false ;
981
+ }
982
+ return bits == 1 ;
978
983
}
979
984
980
985
// Specialization of cpp::countr_zero ('bit.h') for BigInt.
Original file line number Diff line number Diff line change 12
12
13
13
#include < stdint.h>
14
14
15
+ #include < iostream>
16
+
15
17
namespace LIBC_NAMESPACE ::cpp {
16
18
17
19
using UnsignedTypes =
@@ -23,10 +25,25 @@ using UnsignedTypes =
23
25
cpp::UInt<128 >>;
24
26
25
27
TYPED_TEST (LlvmLibcBitTest, HasSingleBit, UnsignedTypes) {
26
- EXPECT_FALSE (has_single_bit<T>(T (0 )));
27
- EXPECT_FALSE (has_single_bit<T>(~T (0 )));
28
+ constexpr auto ZERO = T (0 );
29
+ constexpr auto ALL_ONES = T (~ZERO);
30
+ EXPECT_FALSE (has_single_bit<T>(ZERO));
31
+ EXPECT_FALSE (has_single_bit<T>(ALL_ONES));
32
+
28
33
for (T value = 1 ; value; value <<= 1 )
29
34
EXPECT_TRUE (has_single_bit<T>(value));
35
+
36
+ // We test that if two bits are set has_single_bit returns false.
37
+ // We do this by setting the highest or lowest bit depending or where the
38
+ // current bit is. This is a bit convoluted but it helps catch a bug on BigInt
39
+ // where we have to work on an element-by-element basis.
40
+ constexpr auto MIDPOINT = T (ALL_ONES / 2 );
41
+ constexpr auto LSB = T (1 );
42
+ constexpr auto MSB = T (~(ALL_ONES >> 1 ));
43
+ for (T value = 1 ; value; value <<= 1 ) {
44
+ auto two_bits_value = value | ((value <= MIDPOINT) ? MSB : LSB);
45
+ EXPECT_FALSE (has_single_bit<T>(two_bits_value));
46
+ }
30
47
}
31
48
32
49
TYPED_TEST (LlvmLibcBitTest, CountLZero, UnsignedTypes) {
You can’t perform that action at this time.
0 commit comments