27 namespace seqan3::detail
32 template <simd::simd_concept simd_t,
size_t... I>
35 return simd_t{((void)I, scalar)...};
40 template <simd::simd_concept simd_t,
typename scalar_t, scalar_t... I>
43 return simd_t{
static_cast<scalar_t
>(
offset + I)...};
60 template <
size_t divisor, simd_concept simd_t>
61 constexpr simd_t extract_impl(simd_t
const & src, uint8_t
const mask)
64 constexpr
size_t chunk = simd_traits<simd_t>::length / divisor;
66 for (
size_t i = 0; i <
chunk; ++i)
67 dst[i] = src[i + offset];
80 template <simd::simd_concept target_simd_t, simd::simd_concept source_simd_t>
81 constexpr target_simd_t upcast_signed(source_simd_t
const & src)
83 static_assert(simd_traits<target_simd_t>::max_length == simd_traits<source_simd_t>::max_length,
84 "Target vector has different byte size.");
86 if constexpr (simd_traits<source_simd_t>::max_length == 16)
87 return upcast_signed_sse4<target_simd_t>(src);
88 else if constexpr (simd_traits<source_simd_t>::max_length == 32)
89 return upcast_signed_avx2<target_simd_t>(src);
90 else if constexpr (simd_traits<source_simd_t>::max_length == 64)
91 return upcast_signed_avx512<target_simd_t>(src);
93 static_assert(simd_traits<source_simd_t>::max_length <= 32, "simd type is not supported.");
104 template <simd::simd_concept target_simd_t, simd::simd_concept source_simd_t>
105 constexpr target_simd_t upcast_unsigned(source_simd_t const & src)
107 static_assert(simd_traits<target_simd_t>::max_length == simd_traits<source_simd_t>::max_length,
108 "Target vector has different byte size.");
110 if constexpr (simd_traits<source_simd_t>::max_length == 16)
111 return upcast_unsigned_sse4<target_simd_t>(src);
112 else if constexpr (simd_traits<source_simd_t>::max_length == 32)
113 return upcast_unsigned_avx2<target_simd_t>(src);
114 else if constexpr (simd_traits<source_simd_t>::max_length == 64)
115 return upcast_unsigned_avx512<target_simd_t>(src);
117 static_assert(simd_traits<source_simd_t>::max_length <= 32, "simd type is not supported.");
142 template <uint8_t index, simd::simd_concept simd_t>
143 constexpr simd_t extract_half(simd_t const & src)
145 static_assert(index < 2,
"The index must be in the range of [0, 1]");
147 return detail::extract_impl<2>(src, index);
151 template <u
int8_t index, simd::simd_concept simd_t>
152 requires detail::is_builtin_simd_v<simd_t> && detail::is_native_builtin_simd_v<simd_t>
153 constexpr simd_t extract_half(simd_t
const & src)
155 static_assert(index < 2,
"The index must be in the range of [0, 1]");
157 if constexpr (simd_traits<simd_t>::length < 2)
159 else if constexpr (simd_traits<simd_t>::max_length == 16)
160 return detail::extract_half_sse4<index>(src);
161 else if constexpr (simd_traits<simd_t>::max_length == 32)
162 return detail::extract_half_avx2<index>(src);
163 else if constexpr (simd_traits<simd_t>::max_length == 64)
164 return detail::extract_half_avx512<index>(src);
166 return detail::extract_impl<2>(src, index);
192 template <uint8_t index, simd::simd_concept simd_t>
193 constexpr simd_t extract_quarter(simd_t const & src)
195 static_assert(index < 4,
"The index must be in the range of [0, 1, 2, 3]");
197 return detail::extract_impl<4>(src, index);
201 template <u
int8_t index, simd::simd_concept simd_t>
202 requires detail::is_builtin_simd_v<simd_t> && detail::is_native_builtin_simd_v<simd_t>
203 constexpr simd_t extract_quarter(simd_t
const & src)
205 static_assert(index < 4,
"The index must be in the range of [0, 1, 2, 3]");
207 if constexpr (simd_traits<simd_t>::length < 4)
209 else if constexpr (simd_traits<simd_t>::max_length == 16)
210 return detail::extract_quarter_sse4<index>(src);
211 else if constexpr (simd_traits<simd_t>::max_length == 32)
212 return detail::extract_quarter_avx2<index>(src);
213 #if defined(__AVX512DQ__)
214 else if constexpr (simd_traits<simd_t>::max_length == 64)
215 return detail::extract_quarter_avx512<index>(src);
218 return detail::extract_impl<4>(src, index);
244 template <u
int8_t index, simd::simd_concept simd_t>
245 constexpr simd_t extract_eighth(simd_t
const & src)
247 return detail::extract_impl<8>(src, index);
251 template <u
int8_t index, simd::simd_concept simd_t>
252 requires detail::is_builtin_simd_v<simd_t> && detail::is_native_builtin_simd_v<simd_t>
253 constexpr simd_t extract_eighth(simd_t
const & src)
255 static_assert(index < 8,
"The index must be in the range of [0, 1, 2, 3, 4, 5, 6, 7]");
257 if constexpr (simd_traits<simd_t>::length < 8)
259 else if constexpr (simd_traits<simd_t>::max_length == 16)
260 return detail::extract_eighth_sse4<index>(src);
261 else if constexpr (simd_traits<simd_t>::max_length == 32)
262 return detail::extract_eighth_avx2<index>(src);
263 #if defined(__AVX512DQ__)
264 else if constexpr (simd_traits<simd_t>::max_length == 64)
265 return detail::extract_eighth_avx512<index>(src);
268 return detail::extract_impl<8>(src, index);
273 template <simd::simd_concept simd_t>
274 constexpr
void transpose(
std::array<simd_t, simd_traits<simd_t>::length> & matrix)
278 for (
size_t i = 0; i < matrix.size(); ++i)
279 for (
size_t j = 0; j < matrix.size(); ++j)
280 tmp[j][i] = matrix[i][j];
290 inline namespace simd
302 template <simd::simd_concept simd_t>
303 constexpr simd_t
fill(
typename simd_traits<simd_t>::scalar_type
const scalar) noexcept
305 constexpr
size_t length = simd_traits<simd_t>::length;
318 template <simd::simd_concept simd_t>
319 constexpr simd_t
iota(
typename simd_traits<simd_t>::scalar_type
const offset)
321 constexpr
size_t length = simd_traits<simd_t>::length;
322 using scalar_type =
typename simd_traits<simd_t>::scalar_type;
335 template <simd::simd_concept simd_t>
336 constexpr simd_t load(
void const * mem_addr)
338 assert(mem_addr !=
nullptr);
341 for (
size_t i = 0; i < simd_traits<simd_t>::length; ++i)
342 tmp[i] = *(
static_cast<typename simd_traits<simd_t>::scalar_type
const *
>(mem_addr) + i);
348 template <simd::simd_concept simd_t>
349 requires detail::is_builtin_simd_v<simd_t> && detail::is_native_builtin_simd_v<simd_t>
350 constexpr simd_t load(
void const * mem_addr)
352 assert(mem_addr !=
nullptr);
354 if constexpr (simd_traits<simd_t>::max_length == 16)
355 return detail::load_sse4<simd_t>(mem_addr);
356 else if constexpr (simd_traits<simd_t>::max_length == 32)
357 return detail::load_avx2<simd_t>(mem_addr);
358 else if constexpr (simd_traits<simd_t>::max_length == 64)
359 return detail::load_avx512<simd_t>(mem_addr);
361 static_assert(simd_traits<simd_t>::max_length >= 16 && simd_traits<simd_t>::max_length <= 64,
362 "Unsupported simd type.");
376 template <simd::simd_concept simd_t>
377 constexpr
void store(
void * mem_addr, simd_t const & simd_vec)
379 assert(mem_addr !=
nullptr);
380 using scalar_t =
typename simd_traits<simd_t>::scalar_type;
382 for (
size_t i = 0; i < simd_traits<simd_t>::length; ++i)
383 *(
static_cast<scalar_t *
>(mem_addr) + i) = simd_vec[i];
387 template <simd::simd_concept simd_t>
388 requires detail::is_builtin_simd_v<simd_t> && detail::is_native_builtin_simd_v<simd_t>
389 constexpr
void store(
void * mem_addr, simd_t
const & simd_vec)
391 assert(mem_addr !=
nullptr);
393 if constexpr (simd_traits<simd_t>::max_length == 16)
394 detail::store_sse4<simd_t>(mem_addr, simd_vec);
395 else if constexpr (simd_traits<simd_t>::max_length == 32)
396 detail::store_avx2<simd_t>(mem_addr, simd_vec);
397 else if constexpr (simd_traits<simd_t>::max_length == 64)
398 detail::store_avx512<simd_t>(mem_addr, simd_vec);
400 static_assert(simd_traits<simd_t>::max_length >= 16 && simd_traits<simd_t>::max_length <= 64,
401 "Unsupported simd type.");
422 template <simd::simd_concept simd_t>
423 constexpr
void transpose(
std::array<simd_t, simd_traits<simd_t>::length> & matrix)
425 detail::transpose(matrix);
430 template <simd::simd_concept simd_t>
431 requires detail::is_builtin_simd_v<simd_t> && detail::is_native_builtin_simd_v<simd_t>
432 && (simd_traits<simd_t>::max_length == simd_traits<simd_t>::length)
433 constexpr
void transpose(
std::array<simd_t, simd_traits<simd_t>::length> & matrix)
435 if constexpr (simd_traits<simd_t>::length == 16)
436 detail::transpose_matrix_sse4(matrix);
437 else if constexpr (simd_traits<simd_t>::length == 32)
438 detail::transpose_matrix_avx2(matrix);
439 #if defined(__AVX512BW__)
440 else if constexpr (simd_traits<simd_t>::length == 64)
441 detail::transpose_matrix_avx512(matrix);
444 detail::transpose(matrix);
456 template <simd::simd_concept target_simd_t, simd::simd_concept source_simd_t>
457 constexpr target_simd_t upcast(source_simd_t
const & src)
460 simd_traits<target_simd_t>::length <= simd_traits<source_simd_t>::length,
461 "The length of the target simd type must be greater or equal than the length of the source simd type.");
464 for (
unsigned i = 0; i < simd_traits<target_simd_t>::length; ++i)
465 tmp[i] =
static_cast<typename simd_traits<target_simd_t>::scalar_type
>(src[i]);
471 template <simd::simd_concept target_simd_t, simd::simd_concept source_simd_t>
472 requires detail::is_builtin_simd_v<target_simd_t> && detail::is_builtin_simd_v<source_simd_t>
473 && detail::is_native_builtin_simd_v<source_simd_t>
474 constexpr target_simd_t upcast(source_simd_t
const & src)
477 simd_traits<target_simd_t>::length <= simd_traits<source_simd_t>::length,
478 "The length of the target simd type must be greater or equal than the length of the source simd type.");
480 if constexpr (simd_traits<source_simd_t>::length == simd_traits<target_simd_t>::length)
482 static_assert(simd_traits<target_simd_t>::max_length == simd_traits<source_simd_t>::max_length,
483 "Target vector has a different byte size.");
484 return reinterpret_cast<target_simd_t
>(src);
486 else if constexpr (std::signed_integral<
typename simd_traits<source_simd_t>::scalar_type>)
488 return detail::upcast_signed<target_simd_t>(src);
492 static_assert(std::unsigned_integral<
typename simd_traits<source_simd_t>::scalar_type>,
493 "Expected unsigned scalar type.");
494 return detail::upcast_unsigned<target_simd_t>(src);
Provides seqan3::detail::builtin_simd, seqan3::detail::is_builtin_simd and seqan3::simd::simd_traits<...
The <concepts> header from C++20's standard library.
requires requires
The rank_type of the semi-alphabet; defined as the return type of seqan3::to_rank....
Definition: alphabet/concept.hpp:164
@ offset
Sequence (seqan3::field::seq) relative start position (0-based), unsigned value.
constexpr auto chunk
Divide a range in chunks.
Definition: chunk.hpp:835
The main SeqAn3 namespace.
Definition: aligned_sequence_concept.hpp:29
SeqAn specific customisations in the standard namespace.
Provides specific algorithm implementations for AVX2 instruction set.
Provides specific algorithm implementations for AVX512 instruction set.
Provides specific algorithm implementations for SSE4 instruction set.
Provides seqan3::simd::simd_traits.
Provides seqan3::simd::simd_concept.