Pixie
Loading...
Searching...
No Matches
sequence_tree_kernels.h
1#pragma once
2
3#include <bit>
4#include <cstddef>
5#include <cstdint>
6#include <limits>
7#include <span>
8
9#if SIZE_MAX == UINT64_MAX && (defined(__AVX512F__) || defined(__AVX2__))
10#include <immintrin.h>
11#endif
12
14namespace pixie::permutations::detail {
15
30inline std::size_t node_select_scalar(std::span<const std::size_t> ends,
31 std::size_t index) noexcept {
32 std::size_t i = 0;
33 while (i < ends.size() && ends[i] <= index) {
34 ++i;
35 }
36 return i;
37}
38
51inline std::size_t node_select(std::span<const std::size_t> ends,
52 std::size_t index) noexcept {
53 if (ends.empty()) {
54 return 0;
55 }
56#if SIZE_MAX == UINT64_MAX && defined(__AVX512F__)
57 const auto query =
58 _mm512_set1_epi64(std::bit_cast<long long>(std::uint64_t{index}));
59 for (std::size_t i = 0; i < ends.size();) {
60 const auto remaining = ends.size() - i;
61 const auto count = remaining < 8 ? remaining : 8;
62 const auto active = static_cast<__mmask8>((1u << count) - 1);
63 const auto values = _mm512_maskz_loadu_epi64(active, ends.data() + i);
64 const auto greater = static_cast<unsigned>(
65 _mm512_mask_cmp_epu64_mask(active, values, query, _MM_CMPINT_GT));
66 if (greater != 0) {
67 return i + std::countr_zero(greater);
68 }
69 i += count;
70 }
71 return ends.size();
72#elif SIZE_MAX == UINT64_MAX && defined(__AVX2__)
73 const auto sign = _mm256_set1_epi64x(std::numeric_limits<long long>::min());
74 const auto query = _mm256_xor_si256(
75 _mm256_set1_epi64x(std::bit_cast<long long>(std::uint64_t{index})), sign);
76 std::size_t i = 0;
77 for (; ends.size() - i >= 4; i += 4) {
78 const auto values =
79 _mm256_loadu_si256(reinterpret_cast<const __m256i*>(ends.data() + i));
80 const auto greater =
81 static_cast<unsigned>(_mm256_movemask_pd(_mm256_castsi256_pd(
82 _mm256_cmpgt_epi64(_mm256_xor_si256(values, sign), query))));
83 if (greater != 0) {
84 return i + std::countr_zero(greater);
85 }
86 }
87 return i + node_select_scalar(ends.subspan(i), index);
88#else
89 return node_select_scalar(ends, index);
90#endif
91}
92
93} // namespace pixie::permutations::detail