46 constexpr sip_hash(uint64_t k0, uint64_t k1) noexcept :
47 _v0(k0 ^ 0x736f6d6570736575),
48 _v1(k1 ^ 0x646f72616e646f6d),
49 _v2(k0 ^ 0x6c7967656e657261),
50 _v3(k1 ^ 0x7465646279746573),
55 _debug_state = debug_state_type::idle;
59 [[nodiscard]] uint64_t finish()
noexcept
62 hi_assert(_debug_state < debug_state_type::finalized);
63 _debug_state = debug_state_type::finalized;
74 m |=
static_cast<uint64_t
>(b) << 56;
75 _compress(v0,
v1, v2, v3, m);
76 _finalize(v0,
v1, v2, v3);
78 return v0 ^
v1 ^ v2 ^ v3;
81 void add(
void const *data,
size_t size)
noexcept
84 hi_assert(_debug_state <= debug_state_type::partial);
85 _debug_state = debug_state_type::partial;
88 auto *src =
static_cast<char const *
>(data);
89 hi_axiom_not_null(src);
98 if (hilet offset = _b & 7) {
99 hilet num_bytes =
std::min(8_uz - offset, size);
102 for (
auto i = offset; i != offset + num_bytes; ++i) {
103 m |= char_cast<uint64_t>(src[i]) << (i * CHAR_BIT);
106 if (offset + num_bytes == 8) {
107 _compress(v0,
v1, v2, v3, std::exchange(m, 0));
116 m = load_le<uint64_t>(src);
119 _compress(v0,
v1, v2, v3, std::exchange(m, 0));
123 for (
auto i = 0_uz; i != todo; ++i) {
124 m |= char_cast<uint64_t>(src[i]) << (i * CHAR_BIT);
132 _b = truncate<uint8_t>(_b + size);
146 auto *src =
static_cast<char const *
>(data);
147 hi_axiom_not_null(src);
150 hi_assert(_debug_state == debug_state_type::idle);
159 for (
auto block_count = size / 8; block_count > 0; --block_count, src += 8) {
160 m = load_le<uint64_t>(src);
161 _compress(v0,
v1, v2, v3, m);
165 m = wide_cast<uint64_t>(size & 0xff) << 56;
167 for (
auto i = 0_uz; i != (size & 7); ++i) {
168 m |= char_cast<uint64_t>(src[i]) << (i * CHAR_BIT);
170 _compress(v0,
v1, v2, v3, m);
171 _finalize(v0,
v1, v2, v3);
173 return v0 ^
v1 ^ v2 ^ v3;
180 [[nodiscard]] uint64_t
operator()(
void const *data,
size_t size)
const noexcept
182 return complete_message(data, size);
194 enum class debug_state_type : uint8_t { idle, full, partial, finalized };
195 debug_state_type _debug_state;
198 hi_force_inline
constexpr static void _round(uint64_t& v0, uint64_t&
v1, uint64_t& v2, uint64_t& v3)
noexcept
202 v1 = std::rotl(
v1, 13);
203 v3 = std::rotl(v3, 16);
206 v0 = std::rotl(v0, 32);
210 v1 = std::rotl(
v1, 17);
211 v3 = std::rotl(v3, 21);
214 v2 = std::rotl(v2, 32);
217 constexpr static void _compress(uint64_t& v0, uint64_t&
v1, uint64_t& v2, uint64_t& v3, uint64_t m)
noexcept
222 for (
auto i = 0_uz; i != C; ++i) {
223 _round(v0,
v1, v2, v3);
228 constexpr static void _finalize(uint64_t& v0, uint64_t&
v1, uint64_t& v2, uint64_t& v3)
noexcept
231 for (
auto i = 0_uz; i != D; ++i) {
232 _round(v0,
v1, v2, v3);