Skip to content

Commit d48848b

Browse files
authored
Merge pull request #1619 from evoskuil/master
Add ones_count and zeros_count bitwise utilities, comments, point tests.
2 parents fc8ac0e + d17871f commit d48848b

6 files changed

Lines changed: 77 additions & 4 deletions

File tree

include/bitcoin/system/impl/hash/functions.ipp

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -236,10 +236,32 @@ INLINE constexpr size_t djb2_hash(const data_slice& data) NOEXCEPT
236236
return hash;
237237
}
238238

239-
// Combine hash values, such as a pair of djb2_hash outputs.
239+
// Combine hash values, such as djb2_hash or unique_hash outputs.
240240
INLINE constexpr size_t hash_combine(size_t left, size_t right) NOEXCEPT
241241
{
242-
return left ^ shift_left(right, one);
242+
//// This leads to mixing null points (850k identical) with other buckets.
243+
////constexpr auto prime1 = possible_narrow_cast<size_t>(0x9e3779b97f4a7c15_u64);
244+
////constexpr auto prime2 = possible_narrow_cast<size_t>(0x517cc1b727220a95_u64);
245+
////
246+
////auto first = left;
247+
////first ^= shift_right(first, 23);
248+
////first *= prime1;
249+
////first ^= shift_right(first, 19);
250+
////
251+
////auto second = right;
252+
////second ^= shift_right(second, 13);
253+
////second *= prime2;
254+
////second ^= shift_right(second, 31);
255+
////
256+
////// seed parameter, defaults to zero.
257+
////first ^= second;
258+
////first += seed;
259+
////first ^= shift_right(first, 17);
260+
////first *= prime1;
261+
////first ^= shift_right(first, 29);
262+
263+
////return first;
264+
return bit_xor(left, shift_left(right));
243265
}
244266

245267
} // namespace system

include/bitcoin/system/impl/math/bits.ipp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,18 @@ constexpr size_t right_ones(Value value) NOEXCEPT
7373
return to_unsigned(std::countr_one<Value>(value));
7474
}
7575

76+
template <typename Value, if_unsigned_integer<Value>>
77+
constexpr size_t ones_count(Value value) NOEXCEPT
78+
{
79+
return to_unsigned(std::popcount<Value>(value));
80+
}
81+
82+
template <typename Value, if_unsigned_integer<Value>>
83+
constexpr size_t zeros_count(Value value) NOEXCEPT
84+
{
85+
return to_unsigned(std::popcount<Value>(bit_not(value)));
86+
}
87+
7688
// Bitwise logical operations.
7789
// ----------------------------------------------------------------------------
7890

include/bitcoin/system/math/bits.hpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,12 @@ constexpr size_t left_ones(Value value) NOEXCEPT;
5151
template <typename Value, if_unsigned_integer<Value> = true>
5252
constexpr size_t right_ones(Value value) NOEXCEPT;
5353

54+
// Because std::popcount (C++20) function returns int.
55+
template <typename Value, if_unsigned_integer<Value> = true>
56+
constexpr size_t ones_count(Value value) NOEXCEPT;
57+
template <typename Value, if_unsigned_integer<Value> = true>
58+
constexpr size_t zeros_count(Value value) NOEXCEPT;
59+
5460
/// Bitwise logical operations.
5561
/// ---------------------------------------------------------------------------
5662

test/chain/point.cpp

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -162,8 +162,21 @@ BOOST_AUTO_TEST_CASE(point__to_data__writer__expected)
162162
// properties
163163
// ----------------------------------------------------------------------------
164164

165-
// is_null
166-
// serialized_size
165+
BOOST_AUTO_TEST_CASE(point__is_null__not_null__false)
166+
{
167+
BOOST_REQUIRE(!expected_point.is_null());
168+
}
169+
170+
BOOST_AUTO_TEST_CASE(point__is_null__default_null__true)
171+
{
172+
BOOST_REQUIRE(point{}.is_null());
173+
}
174+
175+
BOOST_AUTO_TEST_CASE(point__serialized_size__always__expected)
176+
{
177+
static_assert(point::serialized_size() == hash_size + sizeof(uint32_t));
178+
BOOST_REQUIRE_EQUAL(point::serialized_size(), hash_size + sizeof(uint32_t));
179+
}
167180

168181
// json
169182
// ----------------------------------------------------------------------------

test/hash/functions.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,16 @@ BOOST_AUTO_TEST_CASE(functions__hash_combine__same_values__expected)
427427
{
428428
BOOST_REQUIRE_EQUAL(hash, 4893418499_u64);
429429
}
430+
431+
// Complex hash.
432+
////if constexpr (sizeof(size_t) == sizeof(uint32_t))
433+
////{
434+
//// BOOST_REQUIRE_EQUAL(hash, 3172851131_u32);
435+
////}
436+
////else
437+
////{
438+
//// BOOST_REQUIRE_EQUAL(hash, 6326001304333978798_u64);
439+
////}
430440
}
431441

432442
BOOST_AUTO_TEST_SUITE_END()

test/math/bits.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,11 @@ static_assert(right_zeros(uint8_t{ 0b11111111 }) == 0);
123123
static_assert(right_zeros(uint8_t{ 0b00011100 }) == 2);
124124
static_assert(right_zeros(uint8_t{ 0b00011101 }) == 0);
125125

126+
static_assert(zeros_count(uint8_t{ 0b00000000 }) == 8);
127+
static_assert(zeros_count(uint8_t{ 0b11111111 }) == 0);
128+
static_assert(zeros_count(uint8_t{ 0b01111111 }) == 1);
129+
static_assert(zeros_count(uint8_t{ 0b11100011 }) == 3);
130+
126131
// ones
127132

128133
static_assert(left_ones(uint8_t{ 0b00000000 }) == 0);
@@ -135,6 +140,11 @@ static_assert(right_ones(uint8_t{ 0b11111111 }) == 8);
135140
static_assert(right_ones(uint8_t{ 0b11111110 }) == 0);
136141
static_assert(right_ones(uint8_t{ 0b11100011 }) == 2);
137142

143+
static_assert(ones_count(uint8_t{ 0b00000000 }) == 0);
144+
static_assert(ones_count(uint8_t{ 0b11111111 }) == 8);
145+
static_assert(ones_count(uint8_t{ 0b11110000 }) == 4);
146+
static_assert(ones_count(uint8_t{ 0b00011110 }) == 4);
147+
138148
// ones_complement (NOT)
139149
// inverts all bits (~n, !bool)
140150
static_assert(bit_not(-4) == 3);

0 commit comments

Comments
 (0)