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)
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_halve(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 simd_traits<simd_t>::max_length == 16
154 constexpr simd_t extract_halve(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)
161 return detail::extract_halve_sse4<index>(src);
187 template <uint8_t index, simd::simd_concept simd_t>
188 constexpr simd_t extract_quarter(simd_t const & src)
190 static_assert(index < 4,
"The index must be in the range of [0, 1, 2, 3]");
192 return detail::extract_impl<4>(src, index);
196 template <u
int8_t index, simd::simd_concept simd_t>
197 requires detail::is_builtin_simd_v<simd_t> &&
198 detail::is_native_builtin_simd_v<simd_t> &&
199 simd_traits<simd_t>::max_length == 16
200 constexpr simd_t extract_quarter(simd_t
const & src)
202 static_assert(index < 4,
"The index must be in the range of [0, 1, 2, 3]");
204 if constexpr (simd_traits<simd_t>::length < 4)
207 return detail::extract_quarter_sse4<index>(src);
233 template <uint8_t index, simd::simd_concept simd_t>
234 constexpr simd_t extract_eighth(simd_t const & src)
236 return detail::extract_impl<8>(src, index);
240 template <u
int8_t index, simd::simd_concept simd_t>
241 requires detail::is_builtin_simd_v<simd_t> &&
242 detail::is_native_builtin_simd_v<simd_t> &&
243 simd_traits<simd_t>::max_length == 16
244 constexpr simd_t extract_eighth(simd_t
const & src)
246 static_assert(index < 8,
"The index must be in the range of [0, 1, 2, 3, 4, 5, 6, 7]");
248 if constexpr (simd_traits<simd_t>::length < 8)
251 return detail::extract_eighth_sse4<index>(src);
260 inline namespace simd
272 template <simd::simd_concept simd_t>
273 constexpr simd_t
fill(
typename simd_traits<simd_t>::scalar_type
const scalar) noexcept
275 constexpr
size_t length = simd_traits<simd_t>::length;
288 template <simd::simd_concept simd_t>
289 constexpr simd_t
iota(
typename simd_traits<simd_t>::scalar_type
const offset)
291 constexpr
size_t length = simd_traits<simd_t>::length;
292 using scalar_type =
typename simd_traits<simd_t>::scalar_type;
305 template <simd::simd_concept simd_t>
306 constexpr simd_t load(
void const * mem_addr)
308 assert(mem_addr !=
nullptr);
311 for (
size_t i = 0; i < simd_traits<simd_t>::length; ++i)
312 tmp[i] = *(
static_cast<typename simd_traits<simd_t>::scalar_type
const *
>(mem_addr) + i);
318 template <simd::simd_concept simd_t>
319 requires detail::is_builtin_simd_v<simd_t> &&
320 detail::is_native_builtin_simd_v<simd_t>
321 constexpr simd_t load(
void const * mem_addr)
323 assert(mem_addr !=
nullptr);
325 if constexpr (simd_traits<simd_t>::max_length == 16)
326 return detail::load_sse4<simd_t>(mem_addr);
327 else if constexpr (simd_traits<simd_t>::max_length == 32)
328 return detail::load_avx2<simd_t>(mem_addr);
329 else if constexpr (simd_traits<simd_t>::max_length == 64)
330 return detail::load_avx512<simd_t>(mem_addr);
332 static_assert(simd_traits<simd_t>::max_length >= 16 && simd_traits<simd_t>::max_length <= 64,
333 "Unsupported simd type.");
354 template <simd::simd_concept simd_t>
355 constexpr
void transpose(
std::array<simd_t, simd_traits<simd_t>::length> & matrix)
359 for (
size_t i = 0; i < matrix.size(); ++i)
360 for (
size_t j = 0; j < matrix.size(); ++j)
361 tmp[j][i] = matrix[i][j];
367 template <simd::simd_concept simd_t>
368 requires detail::is_builtin_simd_v<simd_t> &&
369 detail::is_native_builtin_simd_v<simd_t> &&
370 simd_traits<simd_t>::max_length == 16 &&
371 simd_traits<simd_t>::length == 16
372 constexpr
void transpose(
std::array<simd_t, simd_traits<simd_t>::length> & matrix)
374 detail::transpose_matrix_sse4(matrix);
386 template <simd::simd_concept target_simd_t, simd::simd_concept source_simd_t>
387 constexpr target_simd_t upcast(source_simd_t
const & src)
389 static_assert(simd_traits<target_simd_t>::length <= simd_traits<source_simd_t>::length,
390 "The length of the target simd type must be greater or equal than the length of the source simd type.");
393 for (
unsigned i = 0; i < simd_traits<target_simd_t>::length; ++i)
394 tmp[i] =
static_cast<typename simd_traits<target_simd_t>::scalar_type
>(src[i]);
400 template <simd::simd_concept target_simd_t, simd::simd_concept source_simd_t>
401 requires detail::is_builtin_simd_v<target_simd_t> &&
402 detail::is_builtin_simd_v<source_simd_t> &&
403 detail::is_native_builtin_simd_v<source_simd_t>
404 constexpr target_simd_t upcast(source_simd_t
const & src)
406 static_assert(simd_traits<target_simd_t>::length <= simd_traits<source_simd_t>::length,
407 "The length of the target simd type must be greater or equal than the length of the source simd type.");
409 if constexpr (simd_traits<source_simd_t>::length == simd_traits<target_simd_t>::length)
411 static_assert(simd_traits<target_simd_t>::max_length == simd_traits<source_simd_t>::max_length,
412 "Target vector has a different byte size.");
413 return reinterpret_cast<target_simd_t>(src);
417 return detail::upcast_signed<target_simd_t>(src);
422 "Expected unsigned scalar type.");
423 return detail::upcast_unsigned<target_simd_t>(src);