17namespace seqan3::detail
35template <std::ranges::view urng_t>
36class kmer_hash_view :
public std::ranges::view_interface<kmer_hash_view<urng_t>>
39 static_assert(std::ranges::forward_range<urng_t>,
"The kmer_hash_view only works on forward_ranges");
41 "The reference type of the underlying range must model seqan3::semialphabet.");
49 template <
bool const_range>
56 [[noreturn]]
void shape_too_long_error()
const
58 std::string message{
"The shape is too long for the given alphabet.\n"};
59 message +=
"Alphabet: ";
64 message += detail::type_name_as_string<std::remove_cvref_t<std::ranges::range_value_t<urng_t>>>;
65 message +=
"\nMaximum shape count: ";
67 message +=
"\nGiven shape count: ";
73 inline void validate_shape()
const
75 if (shape_.count() > max_shape_count)
76 shape_too_long_error();
84 requires std::default_initializable<urng_t>
86 kmer_hash_view(kmer_hash_view const & rhs) = default;
87 kmer_hash_view(kmer_hash_view && rhs) = default;
88 kmer_hash_view & operator=(kmer_hash_view const & rhs) = default;
89 kmer_hash_view & operator=(kmer_hash_view && rhs) = default;
90 ~kmer_hash_view() = default;
96 explicit kmer_hash_view(urng_t urange_, shape const & s_) : urange{std::move(urange_)}, shape_{s_}
105 template <
typename rng_t>
106 requires (!std::same_as<std::remove_cvref_t<rng_t>, kmer_hash_view>) && std::ranges::viewable_range<rng_t>
108 explicit kmer_hash_view(rng_t && urange_, shape
const & s_) :
109 urange{std::views::all(std::forward<rng_t>(urange_))},
132 auto begin() noexcept
134 return basic_iterator<false>{
std::ranges::begin(urange), std::ranges::end(urange), shape_};
138 auto begin() const noexcept
141 return basic_iterator<true>{
std::ranges::begin(urange), std::ranges::end(urange), shape_};
162 if constexpr (std::ranges::common_range<urng_t>)
163 return basic_iterator<false>{
std::ranges::begin(urange), std::ranges::end(urange), shape_,
true};
165 return std::ranges::end(urange);
169 auto end() const noexcept
173 if constexpr (std::ranges::common_range<urng_t const>)
174 return basic_iterator<true>{
std::ranges::begin(urange), std::ranges::end(urange), shape_,
true};
176 return std::ranges::cend(urange);
184 requires std::ranges::sized_range<urng_t>
186 using size_type = std::ranges::range_size_t<urng_t>;
187 return std::max<size_type>(std::ranges::size(urange) + 1, shape_.size()) - shape_.size();
192 requires
std::ranges::sized_range<urng_t const>
194 using size_type = std::ranges::range_size_t<urng_t const>;
195 return std::max<size_type>(std::ranges::size(urange) + 1, shape_.size()) - shape_.size();
226template <std::ranges::view urng_t>
227template <
bool const_range>
228class kmer_hash_view<urng_t>::basic_iterator :
229 public maybe_iterator_category<maybe_const_iterator_t<const_range, urng_t>>
233 using it_t = maybe_const_iterator_t<const_range, urng_t>;
235 using sentinel_t = maybe_const_sentinel_t<const_range, urng_t>;
237 template <
bool other_const_range>
238 friend class basic_iterator;
247 using value_type = size_t;
249 using pointer = void;
251 using reference = value_type;
255 detail::iterator_concept_tag_t<it_t>>;
261 constexpr basic_iterator() =
default;
262 constexpr basic_iterator(basic_iterator
const &) =
default;
263 constexpr basic_iterator(basic_iterator &&) =
default;
264 constexpr basic_iterator & operator=(basic_iterator
const &) =
default;
265 constexpr basic_iterator & operator=(basic_iterator &&) =
default;
266 ~basic_iterator() =
default;
269 constexpr basic_iterator(basic_iterator<!const_range>
const & it)
noexcept
272 hash_value{std::move(it.hash_value)},
273 roll_factor{std::move(it.roll_factor)},
274 shape_{std::move(it.shape_)},
275 text_left{std::move(it.text_left)},
276 text_right{std::move(it.text_right)}
290 basic_iterator(it_t it_start, sentinel_t it_end, shape s_) :
293 text_right{
std::ranges::
next(text_left, shape_.
size() - 1, it_end)}
295 assert(std::ranges::size(shape_) > 0);
302 if (shape_.size() <= std::ranges::distance(text_left, text_right) + 1)
304 roll_factor =
pow(sigma,
static_cast<size_t>(std::ranges::size(shape_) - 1));
332 basic_iterator(it_t it_start, sentinel_t it_end, shape s_,
bool SEQAN3_DOXYGEN_ONLY(is_end)) : shape_{s_}
334 assert(std::ranges::size(shape_) > 0);
336 auto urange_size = std::ranges::distance(it_start, it_end);
337 auto step = (shape_.size() > urange_size + 1) ? 0 : urange_size - shape_.
size() + 1;
338 text_left = std::ranges::next(it_start, step, it_end);
345 if (shape_.size() <= std::ranges::distance(text_left, it_end) + 1)
347 roll_factor =
pow(sigma,
static_cast<size_t>(std::ranges::size(shape_) - 1));
360 friend bool operator==(basic_iterator
const & lhs, sentinel_t
const & rhs)
noexcept
362 return lhs.text_right == rhs;
366 friend bool operator==(sentinel_t
const & lhs, basic_iterator
const & rhs)
noexcept
368 return lhs == rhs.text_right;
372 friend bool operator==(basic_iterator
const & lhs, basic_iterator
const & rhs)
noexcept
374 return std::tie(lhs.text_right, lhs.shape_) ==
std::tie(rhs.text_right, rhs.shape_);
378 friend bool operator!=(basic_iterator
const & lhs, sentinel_t
const & rhs)
noexcept
380 return !(lhs == rhs);
384 friend bool operator!=(sentinel_t
const & lhs, basic_iterator
const & rhs)
noexcept
386 return !(lhs == rhs);
390 friend bool operator!=(basic_iterator
const & lhs, basic_iterator
const & rhs)
noexcept
392 return !(lhs == rhs);
396 friend bool operator<(basic_iterator
const & lhs, basic_iterator
const & rhs)
noexcept
398 return (lhs.shape_ <= rhs.shape_) && (lhs.text_right < rhs.text_right);
402 friend bool operator>(basic_iterator
const & lhs, basic_iterator
const & rhs)
noexcept
404 return (lhs.shape_ >= rhs.shape_) && (lhs.text_right > rhs.text_right);
408 friend bool operator<=(basic_iterator
const & lhs, basic_iterator
const & rhs)
noexcept
410 return (lhs.shape_ <= rhs.shape_) && (lhs.text_right <= rhs.text_right);
414 friend bool operator>=(basic_iterator
const & lhs, basic_iterator
const & rhs)
noexcept
416 return (lhs.shape_ >= rhs.shape_) && (lhs.text_right >= rhs.text_right);
422 basic_iterator & operator++() noexcept
429 basic_iterator operator++(
int)
noexcept
431 basic_iterator tmp{*
this};
439 basic_iterator & operator--() noexcept
440 requires
std::bidirectional_iterator<it_t>
449 basic_iterator operator--(
int)
noexcept
450 requires std::bidirectional_iterator<it_t>
452 basic_iterator tmp{*
this};
460 basic_iterator & operator+=(difference_type
const skip)
noexcept
461 requires std::random_access_iterator<it_t>
470 basic_iterator operator+(difference_type
const skip)
const noexcept
471 requires std::random_access_iterator<it_t>
473 basic_iterator tmp{*
this};
480 friend basic_iterator operator+(difference_type
const skip, basic_iterator
const & it)
noexcept
481 requires std::random_access_iterator<it_t>
489 basic_iterator & operator-=(difference_type
const skip)
noexcept
490 requires std::random_access_iterator<it_t>
500 basic_iterator operator-(difference_type
const skip)
const noexcept
501 requires std::random_access_iterator<it_t>
503 basic_iterator tmp{*
this};
510 friend basic_iterator operator-(difference_type
const skip, basic_iterator
const & it)
noexcept
511 requires std::random_access_iterator<it_t>
520 friend difference_type operator-(basic_iterator
const & lhs, basic_iterator
const & rhs)
noexcept
521 requires std::sized_sentinel_for<it_t, it_t>
523 return static_cast<difference_type
>(lhs.text_right - rhs.text_right);
529 friend difference_type operator-(sentinel_t
const & lhs, basic_iterator
const & rhs)
noexcept
530 requires std::sized_sentinel_for<sentinel_t, it_t>
532 return static_cast<difference_type
>(lhs - rhs.text_right);
538 friend difference_type operator-(basic_iterator
const & lhs, sentinel_t
const & rhs)
noexcept
539 requires std::sized_sentinel_for<it_t, sentinel_t>
541 return static_cast<difference_type
>(lhs.text_right - rhs);
547 reference operator[](difference_type
const n)
const
548 requires std::random_access_iterator<it_t>
554 value_type operator*() const noexcept
556 return hash_value +
to_rank(*text_right);
564 static constexpr auto const sigma{alphabet_size<alphabet_t>};
567 size_t hash_value{0};
570 size_t roll_factor{0};
590 std::ranges::advance(text_left, 1);
599 void hash_forward(difference_type
const skip)
600 requires std::random_access_iterator<it_t>
602 std::ranges::advance(text_left, skip);
610 requires std::bidirectional_iterator<it_t>
614 hash_roll_backward();
618 std::ranges::advance(text_left, -1);
627 void hash_backward(difference_type
const skip)
629 std::ranges::advance(text_left, -skip);
636 text_right = text_left;
639 for (
size_t i{0}; i < shape_.size() - 1u; ++i)
641 hash_value += shape_[i] *
to_rank(*text_right);
642 hash_value *= shape_[i] ? sigma : 1;
643 std::ranges::advance(text_right, 1);
648 void hash_roll_forward()
650 hash_value -=
to_rank(*(text_left)) * roll_factor;
651 hash_value +=
to_rank(*(text_right));
654 std::ranges::advance(text_left, 1);
655 std::ranges::advance(text_right, 1);
661 void hash_roll_backward()
662 requires std::bidirectional_iterator<it_t>
664 std::ranges::advance(text_left, -1);
665 std::ranges::advance(text_right, -1);
668 hash_value -=
to_rank(*(text_right));
669 hash_value +=
to_rank(*(text_left)) * roll_factor;
674template <std::ranges::viewable_range rng_t>
675kmer_hash_view(rng_t &&, shape
const & shape_) -> kmer_hash_view<std::views::all_t<rng_t>>;
687 constexpr auto operator()(shape
const & shape_)
const
689 return adaptor_from_functor{*
this, shape_};
699 template <std::ranges::range urng_t>
700 constexpr auto operator()(urng_t && urange, shape
const & shape_)
const
702 static_assert(std::ranges::viewable_range<urng_t>,
703 "The range parameter to views::kmer_hash cannot be a temporary of a non-view range.");
704 static_assert(std::ranges::forward_range<urng_t>,
705 "The range parameter to views::kmer_hash must model std::ranges::forward_range.");
707 "The range parameter to views::kmer_hash must be over elements of seqan3::semialphabet.");
709 return kmer_hash_view{std::forward<urng_t>(urange), shape_};
766inline constexpr auto kmer_hash = detail::kmer_hash_fn{};
Core alphabet concept and free function/type trait wrappers.
constexpr auto alphabet_size
A type trait that holds the size of a (semi-)alphabet.
Definition alphabet/concept.hpp:834
constexpr auto to_rank
Return the rank representation of a (semi-)alphabet object.
Definition alphabet/concept.hpp:152
constexpr auto kmer_hash
Computes hash values for each position of a range via a given shape.
Definition kmer_hash.hpp:766
constexpr size_t size
The size of a type pack.
Definition type_pack/traits.hpp:143
base_t pow(base_t base, exp_t exp)
Computes the value of base raised to the power exp.
Definition math.hpp:120
Specifies requirements of an input range type for which the const version of that type satisfies the ...
The basis for seqan3::alphabet, but requires only rank interface (not char).
Provides math related functionality.
The SeqAn namespace for views.
Definition char_strictly_to.hpp:19
SeqAn specific customisations in the standard namespace.
Provides overloads for std::hash.