dice-hash
Hash function for stl types and container
Loading...
Searching...
No Matches
MathEngine_Hwy.hpp
1#ifndef DICE_HASH_MATHENGINE_HWY_HPP
2#define DICE_HASH_MATHENGINE_HWY_HPP
3
4#include <algorithm>
5#include <bit>
6#include <cassert>
7#include <cstddef>
8#include <cstdint>
9#include <span>
10
11namespace dice::hash::lthash {
12 namespace detail {
13 void add_with_padding(std::span<uint64_t> dst, std::span<uint64_t const> src, uint64_t data_mask);
14 void add_no_padding(std::span<uint64_t> dst, std::span<uint64_t const> src, uint64_t mask_group1, uint64_t mask_group2);
15 void sub_with_padding(std::span<uint64_t> dst, std::span<uint64_t const> src, uint64_t data_mask);
16 void sub_no_padding(std::span<uint64_t> dst, std::span<uint64_t const> src, uint64_t mask_group1, uint64_t mask_group2);
17 bool check_padding_bits(std::span<uint64_t const> data, uint64_t data_mask);
18 void clear_padding_bits(std::span<uint64_t> data, uint64_t data_mask);
19 }
20
21 template<typename Bits>
23 static constexpr size_t min_buffer_align = alignof(uint64_t);
24
25 template<size_t DstExtent, size_t SrcExtent>
26 static void add(std::span<std::byte, DstExtent> dst, std::span<std::byte const, SrcExtent> src) noexcept {
27 assert(dst.size() == src.size());
28 assert(dst.size() % sizeof(uint64_t) == 0);
29 assert(reinterpret_cast<uintptr_t>(dst.data()) % alignof(uint64_t) == 0);
30 assert(reinterpret_cast<uintptr_t>(src.data()) % alignof(uint64_t) == 0);
31
32 std::span<uint64_t> dst64{reinterpret_cast<uint64_t *>(dst.data()), dst.size() / sizeof(uint64_t)};
33 std::span<uint64_t const> src64{reinterpret_cast<uint64_t const *>(src.data()), src.size() / sizeof(uint64_t)};
34
35 if constexpr (!Bits::needs_padding) {
36 static_assert(Bits::bits_per_element == 16 || Bits::bits_per_element == 32,
37 "Only 16 and 32 bit elements are implemented for non-padded data");
38
39 static constexpr uint64_t mask_group_1 = Bits::bits_per_element == 16
40 ? 0xffff0000ffff0000ull
41 : 0xffffffff00000000ull;
42 static constexpr uint64_t mask_group_2 = ~mask_group_1;
43
44 detail::add_no_padding(dst64, src64, mask_group_1, mask_group_2);
45 } else {
46 detail::add_with_padding(dst64, src64, Bits::data_mask);
47 }
48 }
49
50 template<size_t DstExtent, size_t SrcExtent>
51 static void sub(std::span<std::byte, DstExtent> dst, std::span<std::byte const, SrcExtent> src) noexcept {
52 assert(dst.size() == src.size());
53 assert(dst.size() % sizeof(uint64_t) == 0);
54 assert(reinterpret_cast<uintptr_t>(dst.data()) % alignof(uint64_t) == 0);
55 assert(reinterpret_cast<uintptr_t>(src.data()) % alignof(uint64_t) == 0);
56
57 std::span<uint64_t> dst64{reinterpret_cast<uint64_t *>(dst.data()), dst.size() / sizeof(uint64_t)};
58 std::span<uint64_t const> src64{reinterpret_cast<uint64_t const *>(src.data()), src.size() / sizeof(uint64_t)};
59
60 if constexpr (!Bits::needs_padding) {
61 static_assert(Bits::bits_per_element == 16 || Bits::bits_per_element == 32,
62 "Only 16 and 32 bit elements are implemented for non-padded data");
63
64 static constexpr uint64_t mask_group_1 = Bits::bits_per_element == 16
65 ? 0xffff0000ffff0000ull
66 : 0xffffffff00000000ull;
67 static constexpr uint64_t mask_group_2 = ~mask_group_1;
68
69 detail::sub_no_padding(dst64, src64, mask_group_1, mask_group_2);
70 } else {
71 detail::sub_with_padding(dst64, src64, Bits::data_mask);
72 }
73 }
74
75 template<size_t Extent>
76 requires(Bits::needs_padding)
77 static bool check_padding_bits(std::span<std::byte const, Extent> data) noexcept {
78 assert(data.size() % sizeof(uint64_t) == 0);
79 assert(reinterpret_cast<uintptr_t>(data.data()) % alignof(uint64_t) == 0);
80
81 std::span<uint64_t const> data64{reinterpret_cast<uint64_t const *>(data.data()), data.size() / sizeof(uint64_t)};
82 return detail::check_padding_bits(data64, Bits::data_mask);
83 }
84
85 template<size_t Extent>
86 requires(Bits::needs_padding)
87 static void clear_padding_bits(std::span<std::byte, Extent> data) noexcept {
88 assert(data.size() % sizeof(uint64_t) == 0);
89 assert(reinterpret_cast<uintptr_t>(data.data()) % alignof(uint64_t) == 0);
90
91 std::span<uint64_t> data64{reinterpret_cast<uint64_t *>(data.data()), data.size() / sizeof(uint64_t)};
92 detail::clear_padding_bits(data64, Bits::data_mask);
93 }
94 };
95
96} // namespace dice::hash::lthash
97
98#endif//DICE_HASH_MATHENGINE_HWY_HPP
Definition MathEngine_Hwy.hpp:22