49 constexpr sip_hash(uint64_t k0, uint64_t k1) noexcept :
50 _v0(k0 ^ 0x736f6d6570736575),
51 _v1(k1 ^ 0x646f72616e646f6d),
52 _v2(k0 ^ 0x6c7967656e657261),
53 _v3(k1 ^ 0x7465646279746573),
58 _debug_state = debug_state_type::idle;
62 [[nodiscard]] uint64_t finish()
noexcept
65 hi_assert(_debug_state < debug_state_type::finalized);
66 _debug_state = debug_state_type::finalized;
77 m |=
static_cast<uint64_t
>(b) << 56;
78 _compress(v0,
v1, v2, v3, m);
79 _finalize(v0,
v1, v2, v3);
81 return v0 ^
v1 ^ v2 ^ v3;
84 void add(
void const *data,
size_t size)
noexcept
87 hi_assert(_debug_state <= debug_state_type::partial);
88 _debug_state = debug_state_type::partial;
91 auto *src =
static_cast<char const *
>(data);
92 hi_axiom_not_null(src);
101 if (
auto const offset = _b & 7) {
102 auto const num_bytes =
std::min(8_uz - offset, size);
105 for (
auto i = offset; i != offset + num_bytes; ++i) {
106 m |= char_cast<uint64_t>(src[i]) << (i * CHAR_BIT);
109 if (offset + num_bytes == 8) {
110 _compress(v0,
v1, v2, v3, std::exchange(m, 0));
119 m = load_le<uint64_t>(src);
122 _compress(v0,
v1, v2, v3, std::exchange(m, 0));
126 for (
auto i = 0_uz; i != todo; ++i) {
127 m |= char_cast<uint64_t>(src[i]) << (i * CHAR_BIT);
135 _b = truncate<uint8_t>(_b + size);
149 auto *src =
static_cast<char const *
>(data);
150 hi_axiom_not_null(src);
153 hi_assert(_debug_state == debug_state_type::idle);
162 for (
auto block_count = size / 8; block_count > 0; --block_count, src += 8) {
163 m = load_le<uint64_t>(src);
164 _compress(v0,
v1, v2, v3, m);
168 m = wide_cast<uint64_t>(size & 0xff) << 56;
170 for (
auto i = 0_uz; i != (size & 7); ++i) {
171 m |= char_cast<uint64_t>(src[i]) << (i * CHAR_BIT);
173 _compress(v0,
v1, v2, v3, m);
174 _finalize(v0,
v1, v2, v3);
176 return v0 ^
v1 ^ v2 ^ v3;
183 [[nodiscard]] uint64_t
operator()(
void const *data,
size_t size)
const noexcept
185 return complete_message(data, size);
197 enum class debug_state_type : uint8_t { idle, full, partial, finalized };
198 debug_state_type _debug_state;
201 hi_force_inline
constexpr static void _round(uint64_t& v0, uint64_t&
v1, uint64_t& v2, uint64_t& v3)
noexcept
205 v1 = std::rotl(
v1, 13);
206 v3 = std::rotl(v3, 16);
209 v0 = std::rotl(v0, 32);
213 v1 = std::rotl(
v1, 17);
214 v3 = std::rotl(v3, 21);
217 v2 = std::rotl(v2, 32);
220 constexpr static void _compress(uint64_t& v0, uint64_t&
v1, uint64_t& v2, uint64_t& v3, uint64_t m)
noexcept
225 for (
auto i = 0_uz; i != C; ++i) {
226 _round(v0,
v1, v2, v3);
231 constexpr static void _finalize(uint64_t& v0, uint64_t&
v1, uint64_t& v2, uint64_t& v3)
noexcept
234 for (
auto i = 0_uz; i != D; ++i) {
235 _round(v0,
v1, v2, v3);