14 void add_no_padding(std::span<uint64_t> dst, std::span<uint64_t const> src, uint64_t mask_group1, uint64_t mask_group2);
16 void sub_no_padding(std::span<uint64_t> dst, std::span<uint64_t const> src, uint64_t mask_group1, uint64_t mask_group2);
23 static constexpr size_t min_buffer_align =
alignof(uint64_t);
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);
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)};
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");
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;
44 detail::add_no_padding(dst64, src64, mask_group_1, mask_group_2);
46 detail::add_with_padding(dst64, src64, Bits::data_mask);
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);
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)};
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");
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;
69 detail::sub_no_padding(dst64, src64, mask_group_1, mask_group_2);
71 detail::sub_with_padding(dst64, src64, Bits::data_mask);
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);
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);
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);
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);