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> &&
153 detail::is_native_builtin_simd_v<simd_t>
154 constexpr simd_t extract_half(simd_t
const & src)
156 static_assert(index < 2,
"The index must be in the range of [0, 1]");
158 if constexpr (simd_traits<simd_t>::length < 2)
160 else if constexpr (simd_traits<simd_t>::max_length == 16)
161 return detail::extract_half_sse4<index>(src);
162 else if constexpr (simd_traits<simd_t>::max_length == 32)
163 return detail::extract_half_avx2<index>(src);
165 return detail::extract_impl<2>(src, index);
191 template <uint8_t index, simd::simd_concept simd_t>
192 constexpr simd_t extract_quarter(simd_t const & src)
194 static_assert(index < 4,
"The index must be in the range of [0, 1, 2, 3]");
196 return detail::extract_impl<4>(src, index);
200 template <u
int8_t index, simd::simd_concept simd_t>
201 requires detail::is_builtin_simd_v<simd_t> &&
202 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);
214 return detail::extract_impl<4>(src, index);
240 template <uint8_t index, simd::simd_concept simd_t>
241 constexpr simd_t extract_eighth(simd_t const & src)
243 return detail::extract_impl<8>(src, index);
247 template <u
int8_t index, simd::simd_concept simd_t>
248 requires detail::is_builtin_simd_v<simd_t> &&
249 detail::is_native_builtin_simd_v<simd_t>
250 constexpr simd_t extract_eighth(simd_t
const & src)
252 static_assert(index < 8,
"The index must be in the range of [0, 1, 2, 3, 4, 5, 6, 7]");
254 if constexpr (simd_traits<simd_t>::length < 8)
256 else if constexpr (simd_traits<simd_t>::max_length == 16)
257 return detail::extract_eighth_sse4<index>(src);
258 else if constexpr (simd_traits<simd_t>::max_length == 32)
259 return detail::extract_eighth_avx2<index>(src);
261 return detail::extract_impl<8>(src, index);
270 inline namespace simd
282 template <simd::simd_concept simd_t>
283 constexpr simd_t
fill(
typename simd_traits<simd_t>::scalar_type
const scalar) noexcept
285 constexpr
size_t length = simd_traits<simd_t>::length;
298 template <simd::simd_concept simd_t>
299 constexpr simd_t
iota(
typename simd_traits<simd_t>::scalar_type
const offset)
301 constexpr
size_t length = simd_traits<simd_t>::length;
302 using scalar_type =
typename simd_traits<simd_t>::scalar_type;
315 template <simd::simd_concept simd_t>
316 constexpr simd_t load(
void const * mem_addr)
318 assert(mem_addr !=
nullptr);
321 for (
size_t i = 0; i < simd_traits<simd_t>::length; ++i)
322 tmp[i] = *(
static_cast<typename simd_traits<simd_t>::scalar_type
const *
>(mem_addr) + i);
328 template <simd::simd_concept simd_t>
329 requires detail::is_builtin_simd_v<simd_t> &&
330 detail::is_native_builtin_simd_v<simd_t>
331 constexpr simd_t load(
void const * mem_addr)
333 assert(mem_addr !=
nullptr);
335 if constexpr (simd_traits<simd_t>::max_length == 16)
336 return detail::load_sse4<simd_t>(mem_addr);
337 else if constexpr (simd_traits<simd_t>::max_length == 32)
338 return detail::load_avx2<simd_t>(mem_addr);
339 else if constexpr (simd_traits<simd_t>::max_length == 64)
340 return detail::load_avx512<simd_t>(mem_addr);
342 static_assert(simd_traits<simd_t>::max_length >= 16 && simd_traits<simd_t>::max_length <= 64,
343 "Unsupported simd type.");
357 template <simd::simd_concept simd_t>
358 constexpr
void store(
void * mem_addr, simd_t const & simd_vec)
360 assert(mem_addr !=
nullptr);
361 using scalar_t =
typename simd_traits<simd_t>::scalar_type;
363 for (
size_t i = 0; i < simd_traits<simd_t>::length; ++i)
364 *(
static_cast<scalar_t *
>(mem_addr) + i) = simd_vec[i];
368 template <simd::simd_concept simd_t>
369 requires detail::is_builtin_simd_v<simd_t> &&
370 detail::is_native_builtin_simd_v<simd_t>
371 constexpr
void store(
void * mem_addr, simd_t
const & simd_vec)
373 assert(mem_addr !=
nullptr);
375 if constexpr (simd_traits<simd_t>::max_length == 16)
376 detail::store_sse4<simd_t>(mem_addr, simd_vec);
377 else if constexpr (simd_traits<simd_t>::max_length == 32)
378 detail::store_avx2<simd_t>(mem_addr, simd_vec);
379 else if constexpr (simd_traits<simd_t>::max_length == 64)
380 detail::store_avx512<simd_t>(mem_addr, simd_vec);
382 static_assert(simd_traits<simd_t>::max_length >= 16 && simd_traits<simd_t>::max_length <= 64,
383 "Unsupported simd type.");
404 template <simd::simd_concept simd_t>
405 constexpr
void transpose(
std::array<simd_t, simd_traits<simd_t>::length> & matrix)
409 for (
size_t i = 0; i < matrix.size(); ++i)
410 for (
size_t j = 0; j < matrix.size(); ++j)
411 tmp[j][i] = matrix[i][j];
418 template <simd::simd_concept simd_t>
419 requires detail::is_builtin_simd_v<simd_t> &&
420 detail::is_native_builtin_simd_v<simd_t> &&
421 (simd_traits<simd_t>::max_length == simd_traits<simd_t>::length)
422 constexpr
void transpose(
std::array<simd_t, simd_traits<simd_t>::length> & matrix)
424 if constexpr (simd_traits<simd_t>::length == 16)
425 detail::transpose_matrix_sse4(matrix);
426 else if constexpr (simd_traits<simd_t>::length == 32)
427 detail::transpose_matrix_avx2(matrix);
441 template <simd::simd_concept target_simd_t, simd::simd_concept source_simd_t>
442 constexpr target_simd_t upcast(source_simd_t const & src)
444 static_assert(simd_traits<target_simd_t>::length <= simd_traits<source_simd_t>::length,
445 "The length of the target simd type must be greater or equal than the length of the source simd type.");
448 for (
unsigned i = 0; i < simd_traits<target_simd_t>::length; ++i)
449 tmp[i] =
static_cast<typename simd_traits<target_simd_t>::scalar_type
>(src[i]);
455 template <simd::simd_concept target_simd_t, simd::simd_concept source_simd_t>
456 requires detail::is_builtin_simd_v<target_simd_t> &&
457 detail::is_builtin_simd_v<source_simd_t> &&
458 detail::is_native_builtin_simd_v<source_simd_t>
459 constexpr target_simd_t upcast(source_simd_t
const & src)
461 static_assert(simd_traits<target_simd_t>::length <= simd_traits<source_simd_t>::length,
462 "The length of the target simd type must be greater or equal than the length of the source simd type.");
464 if constexpr (simd_traits<source_simd_t>::length == simd_traits<target_simd_t>::length)
466 static_assert(simd_traits<target_simd_t>::max_length == simd_traits<source_simd_t>::max_length,
467 "Target vector has a different byte size.");
468 return reinterpret_cast<target_simd_t
>(src);
470 else if constexpr (std::signed_integral<
typename simd_traits<source_simd_t>::scalar_type>)
472 return detail::upcast_signed<target_simd_t>(src);
476 static_assert(std::unsigned_integral<
typename simd_traits<source_simd_t>::scalar_type>,
477 "Expected unsigned scalar type.");
478 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.
@ offset
Sequence (seqan3::field::seq) relative start position (0-based), unsigned value.
constexpr auto chunk
A chunk view.
Definition: chunk.hpp:29
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.