22#include <hibf/contrib/aligned_allocator.hpp>
24#include <hibf/misc/divide_and_ceil.hpp>
29# include <simde/x86/avx512/add.h>
30# include <simde/x86/avx512/load.h>
31# include <simde/x86/avx512/mov.h>
32# include <simde/x86/avx512/set1.h>
33# include <simde/x86/avx512/store.h>
34# include <simde/x86/avx512/sub.h>
35# include <simde/x86/avx512/types.h>
44template <std::
integral
integral_t>
49template <
typename derived_t, std::
integral
integral_t>
51struct simd_mapping_crtp
55 static inline constexpr size_t bits_per_iterations = 512u / (
sizeof(integral_t) * CHAR_BIT);
68 static inline constexpr auto expand_bits(bits_type
const *
const bits)
70 return derived_t::mm512_maskz_mov_epi(*bits, derived_t::mm512_set1_epi(1));
75template <std::
integral
integral_t>
76 requires (
sizeof(integral_t) == 1)
77struct simd_mapping<integral_t> : simd_mapping_crtp<simd_mapping<integral_t>, integral_t>
79 static inline constexpr auto mm512_maskz_mov_epi = simde_mm512_maskz_mov_epi8;
80 static inline constexpr auto mm512_set1_epi = simde_mm512_set1_epi8;
81 static inline constexpr auto mm512_add_epi = simde_mm512_add_epi8;
82 static inline constexpr auto mm512_sub_epi = simde_mm512_sub_epi8;
86template <std::
integral
integral_t>
87 requires (
sizeof(integral_t) == 2)
88struct simd_mapping<integral_t> : simd_mapping_crtp<simd_mapping<integral_t>, integral_t>
90 static inline constexpr auto mm512_maskz_mov_epi = simde_mm512_maskz_mov_epi16;
91 static inline constexpr auto mm512_set1_epi = simde_mm512_set1_epi16;
92 static inline constexpr auto mm512_add_epi = simde_mm512_add_epi16;
93 static inline constexpr auto mm512_sub_epi = simde_mm512_sub_epi16;
97template <std::
integral
integral_t>
98 requires (
sizeof(integral_t) == 4)
99struct simd_mapping<integral_t> : simd_mapping_crtp<simd_mapping<integral_t>, integral_t>
101 static inline constexpr auto mm512_maskz_mov_epi = simde_mm512_maskz_mov_epi32;
102 static inline constexpr auto mm512_set1_epi = simde_mm512_set1_epi32;
103 static inline constexpr auto mm512_add_epi = simde_mm512_add_epi32;
104 static inline constexpr auto mm512_sub_epi = simde_mm512_sub_epi32;
108template <std::
integral
integral_t>
109 requires (
sizeof(integral_t) == 8)
110struct simd_mapping<integral_t> : simd_mapping_crtp<simd_mapping<integral_t>, integral_t>
112 static inline constexpr auto mm512_maskz_mov_epi = simde_mm512_maskz_mov_epi64;
113 static inline constexpr auto mm512_set1_epi = simde_mm512_set1_epi64;
114 static inline constexpr auto mm512_add_epi = simde_mm512_add_epi64;
115 static inline constexpr auto mm512_sub_epi = simde_mm512_sub_epi64;
143template <std::
integral value_t>
161 using base_t::base_t;
224 enum class operation : uint8_t
230 template <
size_t multiple>
231 inline constexpr size_t next_multiple_of(
size_t const value)
noexcept
233 if constexpr (multiple == 8u)
234 return ((value + 7u) >> 3) << 3;
235 else if constexpr (multiple == 16u)
236 return ((value + 15u) >> 4) << 4;
237 else if constexpr (multiple == 32u)
238 return ((value + 31u) >> 5) << 5;
239 else if constexpr (multiple == 64u)
240 return ((value + 63u) >> 6) << 6;
242 static_assert(
"multiple must be one of 8, 16, 32, 64.");
246 template <operation op>
247 inline void impl(bit_vector
const & bit_vector)
250 if (this->
size() < bit_vector.size())
251 seqan::hibf::unreachable();
255 using simd = simd_mapping<value_t>;
256 using bits_type =
typename simd::bits_type;
258 bits_type
const * bit_vector_ptr =
reinterpret_cast<bits_type
const *
>(bit_vector.data());
261 size_t const bits = next_multiple_of<simd::bits_per_iterations>(bit_vector.size());
263 size_t const iterations = bits / simd::bits_per_iterations;
265 for (
size_t iteration = 0; iteration < iterations;
266 ++iteration, ++bit_vector_ptr, counting_vector_ptr += simd::bits_per_iterations)
268 simde__m512i load = simde_mm512_load_si512(counting_vector_ptr);
269 if constexpr (op == operation::add)
271 load = simd::mm512_add_epi(load, simd::expand_bits(bit_vector_ptr));
275 load = simd::mm512_sub_epi(load, simd::expand_bits(bit_vector_ptr));
277 simde_mm512_store_si512(counting_vector_ptr, load);
281 uint64_t
const *
const bit_vector_ptr = bit_vector.data();
284 auto jump_to_next_1bit = [](uint64_t & value)
292 for (
size_t iteration = 0; iteration < words; ++iteration)
294 uint64_t current_word = bit_vector_ptr[iteration];
297 for (
size_t bin = iteration * 64u; current_word != 0u; ++bin, current_word >>= 1)
300 bin += jump_to_next_1bit(current_word);
302 if constexpr (op == operation::add)
Provides seqan::hibf::bit_vector.
An bit vector.
Definition bit_vector.hpp:66
A data structure that behaves like a std::vector and can be used to consolidate the results of multip...
Definition counting_vector.hpp:145
counting_vector & operator+=(counting_vector const &rhs)
Bin-wise addition of two seqan::hibf::counting_vectors.
Definition counting_vector.hpp:200
counting_vector & operator+=(bit_vector const &bit_vector)
Bin-wise adds the bits of a seqan::hibf::bit_vector.
Definition counting_vector.hpp:171
counting_vector(counting_vector const &)=default
Defaulted.
counting_vector & operator-=(bit_vector const &bit_vector)
Bin-wise subtracts the bits of a seqan::hibf::bit_vector.
Definition counting_vector.hpp:187
counting_vector & operator-=(counting_vector const &rhs)
Bin-wise subtraction of two seqan::hibf::counting_vectors.
Definition counting_vector.hpp:213
~counting_vector()=default
Defaulted.
counting_vector & operator=(counting_vector &&)=default
Defaulted.
counting_vector(counting_vector &&)=default
Defaulted.
counting_vector & operator=(counting_vector const &)=default
Defaulted.
counting_vector()=default
Defaulted.
constexpr size_t divide_and_ceil(t1 const dividend, t2 const divisor) noexcept
Returns, for unsigned integral operands, dividend / divisor ceiled to the next integer value.
Definition divide_and_ceil.hpp:21
Provides seqan::hibf::unreachable.