SeqAn3 3.2.0-rc.1
The Modern C++ library for sequence analysis.
to_simd.hpp
Go to the documentation of this file.
1// -----------------------------------------------------------------------------------------------------
2// Copyright (c) 2006-2021, Knut Reinert & Freie Universität Berlin
3// Copyright (c) 2016-2021, Knut Reinert & MPI für molekulare Genetik
4// This file may be used, modified and/or redistributed under the terms of the 3-clause BSD-License
5// shipped with this file and also available at: https://github.com/seqan/seqan3/blob/master/LICENSE.md
6// -----------------------------------------------------------------------------------------------------
7
13#pragma once
14
15#include <algorithm>
16#include <iterator>
17#include <seqan3/std/ranges>
18
29
30namespace seqan3::detail
31{
32
58template <std::ranges::view urng_t, simd::simd_concept simd_t>
59class view_to_simd : public std::ranges::view_interface<view_to_simd<urng_t, simd_t>>
60{
61private:
62
63 static_assert(std::ranges::forward_range<urng_t>,
64 "The underlying range must model forward_range.");
65 static_assert(std::ranges::input_range<std::ranges::range_value_t<urng_t>>,
66 "Expects the value type of the underlying range to be an input_range.");
67 static_assert(std::default_initializable<std::ranges::iterator_t<std::ranges::range_value_t<urng_t>>>,
68 "Expects the inner range iterator to be default initializable.");
69 static_assert(std::default_initializable<std::ranges::sentinel_t<std::ranges::range_value_t<urng_t>>>,
70 "Expects the inner range sentinel to be default initializable.");
72 "Expects semi-alphabet as value type of the inner range.");
73
77 using inner_range_type = std::ranges::range_value_t<urng_t>;
83
88 static constexpr bool fast_load = std::ranges::contiguous_range<inner_range_type> &&
89 std::sized_sentinel_for<std::ranges::iterator_t<inner_range_type>,
90 std::ranges::sentinel_t<inner_range_type>> &&
92
94 static constexpr uint8_t chunk_size = simd_traits<simd_t>::length;
98 static constexpr uint8_t total_chunks = fast_load ? (chunks_per_load * chunks_per_load) : 1;
100 static constexpr auto alphabet_size = seqan3::alphabet_size<std::ranges::range_value_t<inner_range_type>>;
102
103 // Forward declare class' iterator type. See definition below.
104 struct iterator_type;
105
106public:
107
111 constexpr view_to_simd() requires std::default_initializable<urng_t> = default;
112 constexpr view_to_simd(view_to_simd const &) = default;
113 constexpr view_to_simd(view_to_simd &&) = default;
114 constexpr view_to_simd & operator=(view_to_simd const &) = default;
115 constexpr view_to_simd & operator=(view_to_simd &&) = default;
116 ~view_to_simd() = default;
117
123 urng{std::move(urng)},
124 padding_simd_vector{simd::fill<simd_t>(padding_value)},
126 {
127 // Check if the size is less or equal the simd size.
128 if (std::ranges::distance(urng) > chunk_size)
129 throw std::invalid_argument{"The size of the underlying range must be less than or equal to the size of "
130 "the given simd type!"};
131 }
132
134 template <typename other_urng_t>
136 requires (!std::same_as<std::remove_cvref_t<other_urng_t>, view_to_simd>) &&
137 (!std::same_as<other_urng_t, urng_t>) &&
138 std::ranges::viewable_range<other_urng_t>
140 constexpr view_to_simd(other_urng_t && urng, scalar_type const padding_value = alphabet_size) :
141 view_to_simd{views::type_reduce(std::forward<other_urng_t>(urng)), padding_value}
142 {}
144
149 constexpr iterator_type begin() noexcept
150 {
151 return {*this};
152 }
153
155 constexpr void begin() const noexcept = delete;
156
158 constexpr std::default_sentinel_t end() noexcept
159 {
160 return std::default_sentinel;
161 }
162
164 constexpr void end() const noexcept = delete;
166
168 constexpr bool empty() const noexcept
170 requires std::ranges::forward_range<inner_range_type>
172 {
173 return std::ranges::all_of(urng, [] (auto & rng)
174 {
175 return std::ranges::empty(rng);
176 });
177 }
178
185 constexpr size_t size() const noexcept
187 requires std::ranges::sized_range<inner_range_type>
189 {
190 auto it = std::ranges::max_element(urng, [] (auto & lhs, auto & rhs)
191 {
192 return std::ranges::size(lhs) < std::ranges::size(rhs);
193 });
194
195 return (it != std::ranges::end(urng)) ? (std::ranges::size(*it) + chunk_size - 1) / chunk_size : 0;
196 }
197
198private:
199
200 urng_t urng{};
204};
205
213template <std::ranges::view urng_t, simd::simd_concept simd_t>
214class view_to_simd<urng_t, simd_t>::iterator_type
215{
216public:
222 using pointer = void;
223 using difference_type = ptrdiff_t;
227
231 constexpr iterator_type() = default;
232 constexpr iterator_type(iterator_type const &) = default;
233 constexpr iterator_type(iterator_type &&) = default;
234 constexpr iterator_type & operator=(iterator_type const &) = default;
235 constexpr iterator_type & operator=(iterator_type &&) = default;
236 ~iterator_type() = default;
237
246 constexpr iterator_type(view_to_simd & this_view) : this_view{&this_view}, current_chunk_pos{0}
247 {
248 // Initialise the iterator of the sub ranges.
249 size_t seq_id = 0;
250 for (auto it = std::ranges::begin(this_view.urng); it != std::ranges::end(this_view.urng); ++it, ++seq_id)
251 {
252 cached_iter[seq_id] = std::ranges::begin(*it);
253 cached_sentinel[seq_id] = std::ranges::end(*it);
254 }
255
256 // The batch is empty and by default the constructed iterator is pointing to the end.
257 if (seq_id == 0)
258 return;
259
260 // The batch is not empty but might not be full either.
261 // If a slot is supposed to be empty, it will be initialised with the iterator of the first sequence set to the
262 // end emulating an empty sequence.
263 auto sentinel_it = std::ranges::next(cached_iter[0], cached_sentinel[0]);
264 for (; seq_id < chunk_size; ++seq_id)
265 {
266 cached_iter[seq_id] = sentinel_it;
267 cached_sentinel[seq_id] = cached_sentinel[0];
268 }
269
270 // Check if this is the final chunk already.
271 final_chunk = all_iterators_reached_sentinel();
272
273 // Fetch the next available input characters from the sequences and transform them into simd vectors.
274 underflow();
275 }
277
282 constexpr reference operator*() const noexcept
283 {
284 assert(this_view != nullptr);
285 return std::span{this_view->cached_simd_chunks[current_chunk_pos].begin(),
286 (current_chunk_pos == final_chunk_pos) ? final_chunk_size : chunk_size};
287 }
289
294 constexpr iterator_type & operator++(/*pre-increment*/)
295 {
296 if constexpr (fast_load)
297 { // Check if cached chunks have been already consumed and we need to fetch the next chunks.
298 if (current_chunk_pos == final_chunk_pos)
299 {
300 underflow();
301 current_chunk_pos = 0;
302 }
303 else
304 {
305 ++current_chunk_pos;
306 }
307 }
308 else // In case fast load is not available only one chunk is filled at a time.
309 {
310 underflow();
311 }
312
313 return *this;
314 }
315
317 constexpr value_type operator++(int /*post-increment*/)
318 {
319 value_type tmp = this->operator*();
320 ++(*this);
321 return tmp;
322 }
324
329 constexpr bool operator==(std::default_sentinel_t const &) const noexcept
330 {
331 return at_end;
332 }
333
335 friend constexpr bool operator==(std::default_sentinel_t const &, iterator_type const & rhs) noexcept
336 {
337 return rhs.at_end;
338 }
339
341 constexpr bool operator!=(std::default_sentinel_t const &) const noexcept
342 {
343 return !at_end;
344 }
345
347 friend constexpr bool operator!=(std::default_sentinel_t const &, iterator_type const & rhs) noexcept
348 {
349 return !rhs.at_end;
350 }
352
353private:
364 auto unpack(max_simd_type const & row) const
365 {
366 if constexpr (chunk_size == simd_traits<max_simd_type>::length / 2) // upcast into 2 vectors.
367 {
368 return std::array{simd::upcast<simd_t>(extract_half<0>(row)), // 1. half
369 simd::upcast<simd_t>(extract_half<1>(row))}; // 2. half
370 }
371 else if constexpr (chunk_size == simd_traits<max_simd_type>::length / 4) // upcast into 4 vectors.
372 {
373 return std::array{simd::upcast<simd_t>(extract_quarter<0>(row)), // 1. quarter
374 simd::upcast<simd_t>(extract_quarter<1>(row)), // 2. quarter
375 simd::upcast<simd_t>(extract_quarter<2>(row)), // 3. quarter
376 simd::upcast<simd_t>(extract_quarter<3>(row))}; // 4. quarter
377 }
378 else if constexpr (chunk_size == simd_traits<max_simd_type>::length / 8) // upcast into 8 vectors.
379 {
380 return std::array{simd::upcast<simd_t>(extract_eighth<0>(row)), // 1. eighth
381 simd::upcast<simd_t>(extract_eighth<1>(row)), // 2. eighth
382 simd::upcast<simd_t>(extract_eighth<2>(row)), // 3. eighth
383 simd::upcast<simd_t>(extract_eighth<3>(row)), // 4. eighth
384 simd::upcast<simd_t>(extract_eighth<4>(row)), // 5. eighth
385 simd::upcast<simd_t>(extract_eighth<5>(row)), // 6. eighth
386 simd::upcast<simd_t>(extract_eighth<6>(row)), // 7. eighth
387 simd::upcast<simd_t>(extract_eighth<7>(row))}; // 8. eighth
388 }
389 else
390 {
391 return std::array{simd::upcast<simd_t>(row)};
392 }
393 }
394
406 {
407 auto apply_padding = [this] (simd_t const vec)
408 {
409 return (vec == simd::fill<simd_t>(static_cast<uint8_t>(~0))) ? this_view->padding_simd_vector : vec;
410 };
411
412 // Iterate over the rows of the matrix
413 for (uint8_t row = 0; row < static_cast<uint8_t>(matrix.size()); ++row)
414 {
415 // split a row into multiple chunks of size `chunk_size`
416 auto chunked_row = unpack(matrix[row]);
417
418 if constexpr (chunked_row.size() == 1)
419 {
420 this_view->cached_simd_chunks[0][row] = apply_padding(std::move(chunked_row[0]));
421 }
422 else // Parse the tuple elements and store them in the cached simd chunks.
423 {
424 static_assert(chunked_row.size() == chunks_per_load, "Expected chunks_per_load many simd vectors.");
425
426 for (uint8_t chunk = 0; chunk < chunks_per_load; ++chunk) // store chunks in respective cached entries.
427 {
428 size_t idx = chunk * chunks_per_load + row / chunk_size;
429 this_view->cached_simd_chunks[idx][row % chunk_size] = apply_padding(std::move(chunked_row[chunk]));
430 }
431 }
432 }
433 }
434
438 constexpr bool all_iterators_reached_sentinel() const noexcept
439 {
440 using std::get;
441
442 return std::ranges::all_of(views::zip(cached_iter, cached_sentinel), [] (auto && iterator_sentinel_pair)
443 {
444 return get<0>(iterator_sentinel_pair) == get<1>(iterator_sentinel_pair);
445 });
446 }
447
458 constexpr simd_t convert_single_column()
459 noexcept
460 {
461 simd_t simd_column{};
462 for (size_t idx = 0u; idx < chunk_size; ++idx)
463 {
464 if (cached_iter[idx] == cached_sentinel[idx])
465 {
466 simd_column[idx] = this_view->padding_value;
467 }
468 else
469 {
470 simd_column[idx] = static_cast<scalar_type>(seqan3::to_rank(*cached_iter[idx]));
471 ++cached_iter[idx];
472 }
473 };
474 return simd_column;
475 }
476
487 template <typename array_t>
488 constexpr void update_final_chunk_position(array_t const & iterators_before_update) noexcept
489 {
490 size_t max_distance = 0;
491 for (auto && [it, sent] : views::zip(iterators_before_update, cached_sentinel))
492 max_distance = std::max<size_t>(std::ranges::distance(it, sent), max_distance);
493
494 assert(max_distance > 0);
495 assert(max_distance <= (total_chunks * chunk_size));
496
497 --max_distance;
498 final_chunk_pos = max_distance / chunk_size;
499 // first we should be able to check the chunk position.
500 final_chunk_size = (max_distance % chunk_size) + 1;
501 }
502
504 constexpr void underflow()
506 requires fast_load
508 {
509 at_end = final_chunk;
510 if (at_end) // reached end of stream.
511 return;
512 // For the efficient load we assume at most one byte sized alphabets.
513 // Hence we can load `simd_traits<simd_t>::max_length` length many elements at once.
514 // Depending on the packing of `simd_t` we can prefetch blocks and store them in the `cached_simd_chunks`.
515 // E.g. assume `simd_t` with length 8 on SSE4 with max length 16.
516 // To fill the 16x16 matrix we need four 8x8 matrices.
517 // Thus, for the 8 sequences we need to load two times 16 consecutive bytes to fill the matrix, i.e. two loads
518 // see figure below.
519 //
520 // 0 1 ... 7 | 8 9 ... 15
521 // 0 [a00, a01, ..., a07]|[a08, a09, ..., a15] // first load of seq a reads 16 characters
522 // 1 [b00, b01, ..., b07]|[b08, b09, ..., b15] // first load of seq b reads 16 characters
523 // ... | ...
524 // 7 [g00, g01, ..., g07]|[g08, g09, ..., g15] // first load of seq g reads 16 characters
525 // ----------------------------------------
526 // 8 [a16, a17, ..., a23]|[a24, a25, ..., a31] // second load of seq a reads next 16 characters
527 // 9 [b16, b17, ..., b23]|[b24, b25, ..., b31] // second load of seq b reads next 16 characters
528 // ... | ...
529 // 15 [g16, g17, ..., g23]|[g24, g25, ..., g31] // second load of seq g reads next 16 characters
530 //
531 // This quadratic byte matrix can be transposed efficiently with simd instructions.
532 // If the target simd scalar type is bigger we can apply the same mechanism but have then 16 4x4 matrices
533 // (32 bit) or 256 2x2 matrices (64 bit).
534
535 constexpr int8_t max_size = simd_traits<simd_t>::max_length;
537 decltype(cached_iter) iterators_before_update{cached_iter}; // Keep track of iterators before the update.
538 // Iterate over each sequence.
539 for (uint8_t sequence_pos = 0; sequence_pos < chunk_size; ++sequence_pos)
540 { // Iterate over each block depending on the packing of the target simd vector.
541 for (uint8_t chunk_pos = 0; chunk_pos < chunks_per_load; ++chunk_pos)
542 {
543 uint8_t pos = chunk_pos * chunk_size + sequence_pos; // matrix entry to fill
544 if (cached_sentinel[sequence_pos] - cached_iter[sequence_pos] >= max_size)
545 { // Not in final block, thus load directly from memory.
546 matrix[pos] = simd::load<max_simd_type>(std::addressof(*cached_iter[sequence_pos]));
547 std::advance(cached_iter[sequence_pos], max_size);
548 }
549 else // Loads the final block byte wise in order to not load from uninitialised memory.
550 {
551 matrix[pos] = simd::fill<max_simd_type>(~0);
552 auto & sequence_it = cached_iter[sequence_pos];
553 for (int8_t idx = 0; sequence_it != cached_sentinel[sequence_pos]; ++sequence_it, ++idx)
554 matrix[pos][idx] = seqan3::to_rank(*sequence_it);
555 }
556 }
557 }
558
559 // Handle final chunk which might not end at an offset which is not a multiple of `chunk_size`.
560 final_chunk = all_iterators_reached_sentinel();
561
562 if (final_chunk)
563 update_final_chunk_position(iterators_before_update);
564
566 split_into_sub_matrices(std::move(matrix));
567 }
568
570 constexpr void underflow()
572 requires (!fast_load)
574 {
575 at_end = final_chunk;
576 if (at_end) // reached end of stream.
577 return;
578
579 decltype(cached_iter) iterators_before_update{cached_iter}; // Keep track of iterators before the update.
580 for (size_t i = 0; i < chunk_size; ++i)
581 this_view->cached_simd_chunks[0][i] = convert_single_column();
582
583 final_chunk = all_iterators_reached_sentinel();
584
585 if (final_chunk)
586 update_final_chunk_position(iterators_before_update);
587 }
588
594 view_to_simd * this_view{nullptr};
596 uint8_t final_chunk_size{chunk_size};
598 uint8_t final_chunk_pos{total_chunks - 1};
600 uint8_t current_chunk_pos{0};
602 bool final_chunk{true};
604 bool at_end{true};
605};
606
607// ============================================================================
608// to_simd_fn (adaptor definition)
609// ============================================================================
610
619template <simd::simd_concept simd_t>
621{
624
628 constexpr auto operator()(padding_t const padding_value) const noexcept
629 {
630 return detail::adaptor_from_functor{*this, padding_value};
631 }
632
634 constexpr auto operator()() const noexcept
635 {
636 return detail::adaptor_from_functor{*this};
637 }
638
644 template <std::ranges::range urng_t>
645 constexpr auto operator()(urng_t && urange, padding_t const padding_value) const noexcept
646 {
647 static_assert(std::ranges::forward_range<urng_t>,
648 "The underlying range in views::to_simd must model std::ranges::forward_range.");
649 static_assert(std::ranges::viewable_range<urng_t>,
650 "The underlying range in views::to_simd must model std::ranges::viewable_range.");
651 static_assert(std::ranges::input_range<std::ranges::range_value_t<urng_t>>,
652 "The value type of the underlying range must model std::ranges::input_range.");
654 "The value type of the inner ranges must model seqan3::semialphabet.");
655
656 return view_to_simd<type_reduce_t<urng_t>, simd_t>{std::forward<urng_t>(urange), padding_value};
657 }
658
663 template <std::ranges::range urng_t>
664 constexpr auto operator()(urng_t && urange) const noexcept
665 {
666 static_assert(std::ranges::forward_range<urng_t>,
667 "The underlying range in views::to_simd must model std::ranges::forward_range.");
668 static_assert(std::ranges::viewable_range<urng_t>,
669 "The underlying range in views::to_simd must model std::ranges::viewable_range.");
670 static_assert(std::ranges::input_range<std::ranges::range_value_t<urng_t>>,
671 "The value type of the underlying range must model std::ranges::input_range.");
673 "The value type of the inner ranges must model seqan3::semialphabet.");
674
675 return view_to_simd<type_reduce_t<urng_t>, simd_t>{std::forward<urng_t>(urange)};
676 }
677
679 template <std::ranges::range urng_t>
680 constexpr friend auto operator|(urng_t && urange, to_simd_fn const & me)
681 {
682 return me(std::forward<urng_t>(urange));
683 }
684};
685
686} // namespace seqan3::detail
687
688namespace seqan3::views
689{
690
792template <simd::simd_concept simd_t>
793inline constexpr auto to_simd = detail::to_simd_fn<simd_t>{};
794
795} // namespace seqan3::views
Provides seqan3::detail::adaptor_from_functor.
T addressof(T... args)
T advance(T... args)
Provides algorithms to modify seqan3::simd::simd_type.
Core alphabet concept and free function/type trait wrappers.
T begin(T... args)
Template for range adaptor closure objects that store arguments and wrap a proto-adaptor.
Definition: adaptor_from_functor.hpp:57
Iterator that transposes the underlying range of ranges and transforms that to SIMD types.
Definition: to_simd.hpp:215
auto unpack(max_simd_type const &row) const
Unpacks one row of the transposed byte matrix using simd instructions.
Definition: to_simd.hpp:364
ptrdiff_t difference_type
The difference type.
Definition: to_simd.hpp:223
constexpr void update_final_chunk_position(array_t const &iterators_before_update) noexcept
Updates the end of the final chunk and sets the index of the final chunk.
Definition: to_simd.hpp:488
constexpr void split_into_sub_matrices(std::array< max_simd_type, simd_traits< max_simd_type >::length > matrix) const
Unpacks the matrix of simd types and caches the respective chunk entries.
Definition: to_simd.hpp:405
constexpr iterator_type & operator=(iterator_type &&)=default
Defaulted.
void pointer
The pointer type.
Definition: to_simd.hpp:222
constexpr void underflow()
Fetches the next available chunk(s).
Definition: to_simd.hpp:504
constexpr value_type operator++(int)
Advances the iterator to the next chunk and returns the previous pointed-to value.
Definition: to_simd.hpp:317
friend constexpr bool operator!=(std::default_sentinel_t const &, iterator_type const &rhs) noexcept
Returns true if iterator did not reach the end yet, otherwise false.
Definition: to_simd.hpp:347
constexpr bool all_iterators_reached_sentinel() const noexcept
Checks if all sequence iterators reached the end.
Definition: to_simd.hpp:438
constexpr simd_t convert_single_column() noexcept
Convert a single column into a simd vector.
Definition: to_simd.hpp:458
constexpr bool operator!=(std::default_sentinel_t const &) const noexcept
Returns true if iterator did not reach the end yet, otherwise false.
Definition: to_simd.hpp:341
constexpr iterator_type(iterator_type &&)=default
Defaulted.
constexpr iterator_type()=default
Defaulted.
constexpr reference operator*() const noexcept
Returns a reference to the current chunk of simd vectors.
Definition: to_simd.hpp:282
constexpr iterator_type(view_to_simd &this_view)
Construction from the associated range.
Definition: to_simd.hpp:246
friend constexpr bool operator==(std::default_sentinel_t const &, iterator_type const &rhs) noexcept
Returns true if iterator reached the end, otherwise false.
Definition: to_simd.hpp:335
constexpr iterator_type & operator=(iterator_type const &)=default
Defaulted.
constexpr bool operator==(std::default_sentinel_t const &) const noexcept
Returns true if iterator reached the end, otherwise false.
Definition: to_simd.hpp:329
constexpr iterator_type & operator++()
Advances the iterator to the next chunk.
Definition: to_simd.hpp:294
constexpr iterator_type(iterator_type const &)=default
Defaulted.
Transforms a range of ranges into chunks of seqan3::simd vectors.
Definition: to_simd.hpp:60
constexpr iterator_type begin() noexcept
The iterator to begin of this range.
Definition: to_simd.hpp:149
constexpr bool empty() const noexcept
Checks whether the range is empty.
Definition: to_simd.hpp:168
static constexpr uint8_t chunk_size
The size of one chunk. Equals the number of elements in the simd vector.
Definition: to_simd.hpp:94
scalar_type padding_value
The padding value used to fill the corresponding simd vector element.
Definition: to_simd.hpp:203
constexpr std::default_sentinel_t end() noexcept
A sentinel representing the end of this range.
Definition: to_simd.hpp:158
static constexpr bool fast_load
Check if fast load is enabled.
Definition: to_simd.hpp:88
static constexpr uint8_t total_chunks
The total number of chunks that can be cached.
Definition: to_simd.hpp:98
constexpr view_to_simd(other_urng_t &&urng, scalar_type const padding_value=alphabet_size)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: to_simd.hpp:140
constexpr void end() const noexcept=delete
Const iteration is disabled.
static constexpr uint8_t chunks_per_load
The number of chunks that can be gathered with a single load.
Definition: to_simd.hpp:96
simd_t padding_simd_vector
A cached simd vector with the padding symbol.
Definition: to_simd.hpp:202
std::ranges::range_value_t< urng_t > inner_range_type
The inner range type.
Definition: to_simd.hpp:77
static constexpr auto alphabet_size
The alphabet size.
Definition: to_simd.hpp:100
constexpr view_to_simd()=default
Defaulted.
urng_t urng
The underlying range.
Definition: to_simd.hpp:200
std::array< chunk_type, total_chunks > cached_simd_chunks
The cached chunks of transformed simd vectors.
Definition: to_simd.hpp:201
constexpr void begin() const noexcept=delete
Const iteration is disabled.
simd_type_t< uint8_t, simd_traits< simd_t >::max_length > max_simd_type
The SIMD type with maximal number of lanes for the current arch.
Definition: to_simd.hpp:81
typename simd_traits< simd_t >::scalar_type scalar_type
Definition: to_simd.hpp:79
constexpr size_t size() const noexcept
Returns the size of this range.
Definition: to_simd.hpp:185
Provides various transformation traits used by the range module.
@ row
The corresponding alignment coordinate will be incrementable/decrementable in the row index.
decltype(seqan3::to_rank(std::declval< semi_alphabet_type >())) alphabet_rank_t
The rank_type of the semi-alphabet; defined as the return type of seqan3::to_rank....
Definition: concept.hpp:166
constexpr auto to_rank
Return the rank representation of a (semi-)alphabet object.
Definition: concept.hpp:154
constexpr auto to_simd
A view that transforms a range of ranges into chunks of seqan3::simd vectors.
Definition: to_simd.hpp:793
constexpr void transpose(std::array< simd_t, simd_traits< simd_t >::length > &matrix)
Transposes the given simd vector matrix.
Definition: algorithm.hpp:428
typename simd_type< scalar_t, length, simd_backend >::type simd_type_t
Helper type of seqan3::simd::simd_type.
Definition: simd.hpp:59
constexpr bool all_of(unary_predicate_t &&fn)
Tests whether a given predicate evaluates to true for each type in a seqan3::type_list.
Definition: type_list_algorithm.hpp:112
constexpr size_t size
The size of a type pack.
Definition: traits.hpp:151
constexpr auto chunk
A chunk view.
Definition: chunk.hpp:29
constexpr auto zip
A zip view.
Definition: zip.hpp:29
constexpr auto type_reduce
A view adaptor that behaves like std::views::all, but type erases certain ranges.
Definition: type_reduce.hpp:153
Defines the requirements of a matrix (e.g. score matrices, trace matrices).
The basis for seqan3::alphabet, but requires only rank interface (not char).
The internal SeqAn3 namespace.
Definition: aligned_sequence_concept.hpp:29
The SeqAn namespace for views.
Definition: char_strictly_to.hpp:22
constexpr auto const & get(configuration< configs_t... > const &config) noexcept
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: configuration.hpp:429
SeqAn specific customisations in the standard namespace.
The <ranges> header from C++20's standard library.
Provides seqan3::simd::simd_type.
Provides seqan3::simd::simd_traits.
views::to_simd's range adaptor closure object type.
Definition: to_simd.hpp:621
typename simd_traits< simd_t >::scalar_type padding_t
The type of a padding value.
Definition: to_simd.hpp:623
constexpr auto operator()(urng_t &&urange) const noexcept
Call the view's constructor with the underlying std::ranges::viewable_range as argument.
Definition: to_simd.hpp:664
constexpr auto operator()(urng_t &&urange, padding_t const padding_value) const noexcept
Call the view's constructor with the underlying std::ranges::viewable_range as argument.
Definition: to_simd.hpp:645
constexpr friend auto operator|(urng_t &&urange, to_simd_fn const &me)
Overloaded bit-operator to allow chaining with other ranges.
Definition: to_simd.hpp:680
constexpr auto operator()() const noexcept
Returns a range adaptor object.
Definition: to_simd.hpp:634
constexpr auto operator()(padding_t const padding_value) const noexcept
Returns a range adaptor closure object with the given parameter.
Definition: to_simd.hpp:628
seqan3::simd::simd_traits is the trait class that provides uniform interface to the properties of sim...
Definition: simd_traits.hpp:41
Provides type traits for working with templates.
Provides seqan3::views::type_reduce.
Provides seqan3::simd::simd_concept.
Provides seqan3::views::zip.