26 namespace seqan3::detail
31 template <simd::simd_concept simd_t,
size_t... I>
34 return simd_t{((void)I, scalar)...};
39 template <simd::simd_concept simd_t,
typename scalar_t, scalar_t... I>
42 return simd_t{
static_cast<scalar_t
>(offset + I)...};
59 template <
size_t divisor, simd_concept simd_t>
60 constexpr simd_t extract_impl(simd_t
const & src, uint8_t
const mask)
63 constexpr
size_t chunk = simd_traits<simd_t>::length / divisor;
64 size_t offset = chunk * mask;
65 for (
size_t i = 0; i < chunk; ++i)
66 dst[i] = src[i + offset];
79 template <simd::simd_concept target_simd_t, simd::simd_concept source_simd_t>
80 constexpr target_simd_t upcast_signed(source_simd_t
const & src)
82 static_assert(simd_traits<target_simd_t>::max_length == simd_traits<source_simd_t>::max_length,
83 "Target vector has different byte size.");
85 if constexpr (simd_traits<source_simd_t>::max_length == 16)
86 return upcast_signed_sse4<target_simd_t>(src);
87 else if constexpr (simd_traits<source_simd_t>::max_length == 32)
88 return upcast_signed_avx2<target_simd_t>(src);
89 else if constexpr (simd_traits<source_simd_t>::max_length == 64)
90 return upcast_signed_avx512<target_simd_t>(src);
92 static_assert(simd_traits<source_simd_t>::max_length <= 32, "simd type is not supported.");
103 template <simd::simd_concept target_simd_t, simd::simd_concept source_simd_t>
104 constexpr target_simd_t upcast_unsigned(source_simd_t const & src)
106 static_assert(simd_traits<target_simd_t>::max_length == simd_traits<source_simd_t>::max_length,
107 "Target vector has different byte size.");
109 if constexpr (simd_traits<source_simd_t>::max_length == 16)
110 return upcast_unsigned_sse4<target_simd_t>(src);
111 else if constexpr (simd_traits<source_simd_t>::max_length == 32)
112 return upcast_unsigned_avx2<target_simd_t>(src);
113 else if constexpr (simd_traits<source_simd_t>::max_length == 64)
114 return upcast_unsigned_avx512<target_simd_t>(src);
116 static_assert(simd_traits<source_simd_t>::max_length <= 32, "simd type is not supported.");
141 template <uint8_t index, simd::simd_concept simd_t>
142 constexpr simd_t extract_half(simd_t const & src)
144 static_assert(index < 2,
"The index must be in the range of [0, 1]");
146 return detail::extract_impl<2>(src, index);
150 template <u
int8_t index, simd::simd_concept simd_t>
151 requires detail::is_builtin_simd_v<simd_t> &&
152 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);
164 return detail::extract_impl<2>(src, index);
190 template <uint8_t index, simd::simd_concept simd_t>
191 constexpr simd_t extract_quarter(simd_t const & src)
193 static_assert(index < 4,
"The index must be in the range of [0, 1, 2, 3]");
195 return detail::extract_impl<4>(src, index);
199 template <u
int8_t index, simd::simd_concept simd_t>
200 requires detail::is_builtin_simd_v<simd_t> &&
201 detail::is_native_builtin_simd_v<simd_t>
202 constexpr simd_t extract_quarter(simd_t
const & src)
204 static_assert(index < 4,
"The index must be in the range of [0, 1, 2, 3]");
206 if constexpr (simd_traits<simd_t>::length < 4)
208 else if constexpr (simd_traits<simd_t>::max_length == 16)
209 return detail::extract_quarter_sse4<index>(src);
210 else if constexpr (simd_traits<simd_t>::max_length == 32)
211 return detail::extract_quarter_avx2<index>(src);
213 return detail::extract_impl<4>(src, index);
239 template <uint8_t index, simd::simd_concept simd_t>
240 constexpr simd_t extract_eighth(simd_t const & src)
242 return detail::extract_impl<8>(src, index);
246 template <u
int8_t index, simd::simd_concept simd_t>
247 requires detail::is_builtin_simd_v<simd_t> &&
248 detail::is_native_builtin_simd_v<simd_t>
249 constexpr simd_t extract_eighth(simd_t
const & src)
251 static_assert(index < 8,
"The index must be in the range of [0, 1, 2, 3, 4, 5, 6, 7]");
253 if constexpr (simd_traits<simd_t>::length < 8)
255 else if constexpr (simd_traits<simd_t>::max_length == 16)
256 return detail::extract_eighth_sse4<index>(src);
257 else if constexpr (simd_traits<simd_t>::max_length == 32)
258 return detail::extract_eighth_avx2<index>(src);
260 return detail::extract_impl<8>(src, index);
269 inline namespace simd
281 template <simd::simd_concept simd_t>
282 constexpr simd_t
fill(
typename simd_traits<simd_t>::scalar_type
const scalar) noexcept
284 constexpr
size_t length = simd_traits<simd_t>::length;
297 template <simd::simd_concept simd_t>
298 constexpr simd_t
iota(
typename simd_traits<simd_t>::scalar_type
const offset)
300 constexpr
size_t length = simd_traits<simd_t>::length;
301 using scalar_type =
typename simd_traits<simd_t>::scalar_type;
314 template <simd::simd_concept simd_t>
315 constexpr simd_t load(
void const * mem_addr)
317 assert(mem_addr !=
nullptr);
320 for (
size_t i = 0; i < simd_traits<simd_t>::length; ++i)
321 tmp[i] = *(
static_cast<typename simd_traits<simd_t>::scalar_type
const *
>(mem_addr) + i);
327 template <simd::simd_concept simd_t>
328 requires detail::is_builtin_simd_v<simd_t> &&
329 detail::is_native_builtin_simd_v<simd_t>
330 constexpr simd_t load(
void const * mem_addr)
332 assert(mem_addr !=
nullptr);
334 if constexpr (simd_traits<simd_t>::max_length == 16)
335 return detail::load_sse4<simd_t>(mem_addr);
336 else if constexpr (simd_traits<simd_t>::max_length == 32)
337 return detail::load_avx2<simd_t>(mem_addr);
338 else if constexpr (simd_traits<simd_t>::max_length == 64)
339 return detail::load_avx512<simd_t>(mem_addr);
341 static_assert(simd_traits<simd_t>::max_length >= 16 && simd_traits<simd_t>::max_length <= 64,
342 "Unsupported simd type.");
363 template <simd::simd_concept simd_t>
364 constexpr
void transpose(
std::array<simd_t, simd_traits<simd_t>::length> & matrix)
368 for (
size_t i = 0; i < matrix.size(); ++i)
369 for (
size_t j = 0; j < matrix.size(); ++j)
370 tmp[j][i] = matrix[i][j];
377 template <simd::simd_concept simd_t>
378 requires detail::is_builtin_simd_v<simd_t> &&
379 detail::is_native_builtin_simd_v<simd_t> &&
380 (simd_traits<simd_t>::max_length == simd_traits<simd_t>::length)
381 constexpr
void transpose(
std::array<simd_t, simd_traits<simd_t>::length> & matrix)
383 if constexpr (simd_traits<simd_t>::length == 16)
384 detail::transpose_matrix_sse4(matrix);
385 else if constexpr (simd_traits<simd_t>::length == 32)
386 detail::transpose_matrix_avx2(matrix);
400 template <simd::simd_concept target_simd_t, simd::simd_concept source_simd_t>
401 constexpr target_simd_t upcast(source_simd_t const & src)
403 static_assert(simd_traits<target_simd_t>::length <= simd_traits<source_simd_t>::length,
404 "The length of the target simd type must be greater or equal than the length of the source simd type.");
407 for (
unsigned i = 0; i < simd_traits<target_simd_t>::length; ++i)
408 tmp[i] =
static_cast<typename simd_traits<target_simd_t>::scalar_type
>(src[i]);
414 template <simd::simd_concept target_simd_t, simd::simd_concept source_simd_t>
415 requires detail::is_builtin_simd_v<target_simd_t> &&
416 detail::is_builtin_simd_v<source_simd_t> &&
417 detail::is_native_builtin_simd_v<source_simd_t>
418 constexpr target_simd_t upcast(source_simd_t
const & src)
420 static_assert(simd_traits<target_simd_t>::length <= simd_traits<source_simd_t>::length,
421 "The length of the target simd type must be greater or equal than the length of the source simd type.");
423 if constexpr (simd_traits<source_simd_t>::length == simd_traits<target_simd_t>::length)
425 static_assert(simd_traits<target_simd_t>::max_length == simd_traits<source_simd_t>::max_length,
426 "Target vector has a different byte size.");
427 return reinterpret_cast<target_simd_t
>(src);
429 else if constexpr (std::signed_integral<
typename simd_traits<source_simd_t>::scalar_type>)
431 return detail::upcast_signed<target_simd_t>(src);
435 static_assert(std::unsigned_integral<
typename simd_traits<source_simd_t>::scalar_type>,
436 "Expected unsigned scalar type.");
437 return detail::upcast_unsigned<target_simd_t>(src);