17#include <simd/integer.h>
39 std::span<std::uint64_t const> checkpoints,
40 std::uint64_t virtual_count)
43 template <
class Words>
requires std::is_same_v<Words, word_view>
45 std::uint64_t virtual_count)
48 group_count_(virtual_count / 15 + (virtual_count % 15 != 0)) {
50 if (classes.size() != ((groups + 15) >> 4) ||
51 checkpoints.size() != ((groups + 127) >> 7))
52 error_detail::raise<std::invalid_argument>(
"invalid rank15 spans");
58 template <simd::architecture Arch = simd::scalar>
64 error_detail::raise<std::invalid_argument>(
"invalid rank15 final population");
72 if (group >=
group_count()) error_detail::raise<std::out_of_range>(
"rank15 class");
73 return unsigned((
classes_[group >> 4] >> (4 * (group & 15))) & 15);
78 template <simd::architecture Arch = simd::scalar>
79 std::uint64_t
rank(std::uint64_t group)
const {
80 if (group >=
group_count()) error_detail::raise<std::out_of_range>(
"rank15 group");
83 if ((group & 127) == 0)
return add_prefix(result, 0, limit);
84 auto word = (group >> 7) << 3;
85 if constexpr (!std::same_as<Arch, simd::scalar> && std::endian::native == std::endian::little)
87 return add_prefix(result,
unsigned(reduce_add_widened(prefix_vectors<Arch>(
88 classes_.
bytes().data() + word * 8,
unsigned(group & 127)))), limit);
91 std::uint64_t pairs = 0;
93 auto tail = unsigned(group & 15);
100 static std::uint64_t
add_prefix(std::uint64_t checkpoint,
unsigned prefix, std::uint64_t limit) {
101 if (checkpoint > limit || prefix > limit - checkpoint)
102 error_detail::raise<std::invalid_argument>(
"invalid rank15 checkpoint or prefix");
103 return checkpoint + prefix;
105 template <simd::architecture Arch,
unsigned Vector = 0>
107 constexpr auto width = backend_detail::register_bytes<Arch>;
108 using V = simd::vec<std::uint8_t, width, Arch>;
109 constexpr auto positions = [=] {
110 std::array<std::uint8_t, width> result{};
111 for (
unsigned i = 0; i < result.size(); ++i) result[i] = 2 * (Vector * width + i);
114 auto packed = V::loadu(
reinterpret_cast<std::uint8_t
const *
>(words) + Vector * width);
115 auto low = packed & V(15);
116 auto high = packed.template right<4>();
117 auto boundary = V(
count);
118 auto pairs = select(V(positions) < boundary, low, V(0)) +
119 select(V(positions) + V(1) < boundary, high, V(0));
122 if constexpr ((Vector + 1) * width == 64)
return pairs;
123 else return pairs + prefix_vectors<Arch, Vector + 1>(words,
count);
127 return (value & 0x0f0f0f0f0f0f0f0full) + ((value >> 4) & 0x0f0f0f0f0f0f0f0full);
130 static unsigned sum_bytes(std::uint64_t value)
noexcept {
133 value = (value & 0x00ff00ff00ff00ffull) + ((value >> 8) & 0x00ff00ff00ff00ffull);
134 return unsigned((value * 0x0001000100010001ull) >> 48);
145 auto groups = count / 15 + (count % 15 != 0);
146 if (source.size() != groups) error_detail::raise<std::invalid_argument>(
"rank15 class length");
149 result.
classes.resize((groups + 15) >> 4);
150 std::uint64_t total = 0;
151 for (std::uint64_t i = 0; i < groups; ++i) {
152 auto limit = i + 1 == groups && count % 15 ? count % 15 : 15;
153 if (source[i] > limit) error_detail::raise<std::invalid_argument>(
"rank15 class population");
154 if ((i & 127) == 0) result.
checkpoints.push_back(total);
155 result.
classes[i >> 4] |= std::uint64_t(source[i]) << (4 * (i & 15));
Shares explicit SIMD architecture traits with Everett's kernels.
Outlines exceptional check failures while preserving their types and messages.
Definition active_engine.h:18
static rank15_index build(std::span< std::uint8_t const > source, std::uint64_t count)
Definition rank15.h:144
std::vector< std::uint64_t > classes
Definition rank15.h:165
rank15_view view() const &
Definition rank15.h:161
rank15_view view() const &&=delete
std::uint64_t virtual_count
Definition rank15.h:167
std::vector< std::uint64_t > checkpoints
Definition rank15.h:166
std::uint64_t rank(std::uint64_t group) const
Definition rank15.h:79
unsigned class_at(std::uint64_t group) const
Definition rank15.h:71
std::uint64_t group_count_
Definition rank15.h:140
word_view checkpoints_
Definition rank15.h:138
static auto prefix_vectors(std::byte const *words, unsigned count) noexcept
Definition rank15.h:106
rank15_view(std::span< std::uint64_t const > classes, std::span< std::uint64_t const > checkpoints, std::uint64_t virtual_count)
Definition rank15.h:38
word_view class_words() const noexcept
Definition rank15.h:68
std::uint64_t group_count() const noexcept
Definition rank15.h:56
std::uint64_t size() const noexcept
Definition rank15.h:55
word_view classes_
Definition rank15.h:137
std::uint64_t virtual_count_
Definition rank15.h:139
std::uint64_t count() const
Definition rank15.h:59
static std::uint64_t pair_nibbles(std::uint64_t value) noexcept
Definition rank15.h:126
rank15_view(Words classes, Words checkpoints, std::uint64_t virtual_count)
Definition rank15.h:44
static unsigned sum_bytes(std::uint64_t value) noexcept
Definition rank15.h:130
word_view checkpoint_words() const noexcept
Definition rank15.h:69
static std::uint64_t add_prefix(std::uint64_t checkpoint, unsigned prefix, std::uint64_t limit)
Definition rank15.h:100
Definition word_view.h:31
std::size_t size() const noexcept
Definition word_view.h:41
std::span< std::byte const > bytes() const noexcept
Definition word_view.h:43
Borrows native or little-endian directory words and select samples.