23#include <hibf/contrib/aligned_allocator.hpp>
25#include <hibf/misc/divide_and_ceil.hpp>
26#include <hibf/misc/next_multiple_of_64.hpp>
30# include <simde/x86/avx512/add.h>
31# include <simde/x86/avx512/load.h>
32# include <simde/x86/avx512/mov.h>
33# include <simde/x86/avx512/set1.h>
34# include <simde/x86/avx512/store.h>
35# include <simde/x86/avx512/sub.h>
36# include <simde/x86/avx512/types.h>
45template <std::
integral
integral_t>
50template <
typename derived_t, std::
integral
integral_t>
52struct simd_mapping_crtp
56 static inline constexpr size_t bits_per_iterations = 512u / (
sizeof(integral_t) * CHAR_BIT);
69 static inline constexpr auto expand_bits(bits_type
const *
const bits)
71 return derived_t::mm512_maskz_mov_epi(*bits, derived_t::mm512_set1_epi(1));
76template <std::
integral
integral_t>
77 requires (
sizeof(integral_t) == 1)
78struct simd_mapping<integral_t> : simd_mapping_crtp<simd_mapping<integral_t>, integral_t>
80 static inline constexpr auto mm512_maskz_mov_epi = simde_mm512_maskz_mov_epi8;
81 static inline constexpr auto mm512_set1_epi = simde_mm512_set1_epi8;
82 static inline constexpr auto mm512_add_epi = simde_mm512_add_epi8;
83 static inline constexpr auto mm512_sub_epi = simde_mm512_sub_epi8;
87template <std::
integral
integral_t>
88 requires (
sizeof(integral_t) == 2)
89struct simd_mapping<integral_t> : simd_mapping_crtp<simd_mapping<integral_t>, integral_t>
91 static inline constexpr auto mm512_maskz_mov_epi = simde_mm512_maskz_mov_epi16;
92 static inline constexpr auto mm512_set1_epi = simde_mm512_set1_epi16;
93 static inline constexpr auto mm512_add_epi = simde_mm512_add_epi16;
94 static inline constexpr auto mm512_sub_epi = simde_mm512_sub_epi16;
98template <std::
integral
integral_t>
99 requires (
sizeof(integral_t) == 4)
100struct simd_mapping<integral_t> : simd_mapping_crtp<simd_mapping<integral_t>, integral_t>
102 static inline constexpr auto mm512_maskz_mov_epi = simde_mm512_maskz_mov_epi32;
103 static inline constexpr auto mm512_set1_epi = simde_mm512_set1_epi32;
104 static inline constexpr auto mm512_add_epi = simde_mm512_add_epi32;
105 static inline constexpr auto mm512_sub_epi = simde_mm512_sub_epi32;
109template <std::
integral
integral_t>
110 requires (
sizeof(integral_t) == 8)
111struct simd_mapping<integral_t> : simd_mapping_crtp<simd_mapping<integral_t>, integral_t>
113 static inline constexpr auto mm512_maskz_mov_epi = simde_mm512_maskz_mov_epi64;
114 static inline constexpr auto mm512_set1_epi = simde_mm512_set1_epi64;
115 static inline constexpr auto mm512_add_epi = simde_mm512_add_epi64;
116 static inline constexpr auto mm512_sub_epi = simde_mm512_sub_epi64;
144template <std::
integral value_t>
162 using base_t::base_t;
225 enum class operation : uint8_t
232 template <operation op>
233 inline void impl(bit_vector
const & bit_vector)
235 assert(this->
size() >= bit_vector.size());
239 using simd = simd_mapping<value_t>;
240 using bits_type =
typename simd::bits_type;
242 bits_type
const * bit_vector_ptr =
reinterpret_cast<bits_type
const *
>(bit_vector.data());
247 size_t const iterations = bits / simd::bits_per_iterations;
249 for (
size_t iteration = 0; iteration < iterations;
250 ++iteration, ++bit_vector_ptr, counting_vector_ptr += simd::bits_per_iterations)
252 simde__m512i load = simde_mm512_load_si512(counting_vector_ptr);
253 if constexpr (op == operation::add)
255 load = simd::mm512_add_epi(load, simd::expand_bits(bit_vector_ptr));
259 load = simd::mm512_sub_epi(load, simd::expand_bits(bit_vector_ptr));
261 simde_mm512_store_si512(counting_vector_ptr, load);
265 uint64_t
const *
const bit_vector_ptr = bit_vector.data();
268 auto jump_to_next_1bit = [](uint64_t & value)
276 for (
size_t iteration = 0; iteration < words; ++iteration)
278 uint64_t current_word = bit_vector_ptr[iteration];
281 for (
size_t bin = iteration * 64u; current_word != 0u; ++bin, current_word >>= 1)
284 bin += jump_to_next_1bit(current_word);
286 if constexpr (op == operation::add)
Provides seqan::hibf::bit_vector.
An bit vector.
Definition bit_vector.hpp:68
A data structure that behaves like a std::vector and can be used to consolidate the results of multip...
Definition counting_vector.hpp:146
counting_vector & operator+=(counting_vector const &rhs)
Bin-wise addition of two seqan::hibf::counting_vectors.
Definition counting_vector.hpp:201
counting_vector & operator+=(bit_vector const &bit_vector)
Bin-wise adds the bits of a seqan::hibf::bit_vector.
Definition counting_vector.hpp:172
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:188
counting_vector & operator-=(counting_vector const &rhs)
Bin-wise subtraction of two seqan::hibf::counting_vectors.
Definition counting_vector.hpp:214
~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 next_multiple_of_64(size_t const value) noexcept
Returns the smallest integer that is greater or equal to value and a multiple of 64....
Definition next_multiple_of_64.hpp:18
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