21 namespace seqan3::detail
40 template <std::ranges::view urng_t>
41 class kmer_hash_view :
public std::ranges::view_interface<kmer_hash_view<urng_t>>
44 static_assert(std::ranges::forward_range<urng_t const>,
"The kmer_hash_view only works on forward_ranges");
45 static_assert(
semialphabet<reference_t<urng_t>>,
"The reference type of the underlying range must model "
46 "seqan3::semialphabet.");
79 template <
typename rng_t>
84 using it_t = std::ranges::iterator_t<rng_t>;
86 using sentinel_t = std::ranges::sentinel_t<rng_t>;
92 using difference_type =
typename it_t::difference_type;
95 using value_type = size_t;
99 using reference = value_type;
105 iterator_tag_t<it_t>>;
111 constexpr shape_iterator() =
default;
112 constexpr shape_iterator(shape_iterator
const &) =
default;
113 constexpr shape_iterator(shape_iterator &&) =
default;
114 constexpr shape_iterator & operator=(shape_iterator
const &) =
default;
115 constexpr shape_iterator & operator=(shape_iterator &&) =
default;
116 ~shape_iterator() =
default;
128 shape_iterator(it_t it_start, shape s_) :
129 shape_{s_}, text_left{it_start}, text_right{it_start}
144 friend bool operator==(shape_iterator
const & lhs, sentinel_t
const & rhs) noexcept
146 return lhs.text_right == rhs;
150 friend bool operator==(sentinel_t
const & lhs, shape_iterator
const & rhs) noexcept
152 return lhs == rhs.text_right;
156 friend bool operator==(shape_iterator
const & lhs, shape_iterator
const & rhs) noexcept
158 return std::tie(lhs.text_right, lhs.shape_) ==
std::tie(rhs.text_right, rhs.shape_);
162 friend bool operator!=(shape_iterator
const & lhs, sentinel_t
const & rhs) noexcept
164 return !(lhs == rhs);
168 friend bool operator!=(sentinel_t
const & lhs, shape_iterator
const & rhs) noexcept
170 return !(lhs == rhs);
174 friend bool operator!=(shape_iterator
const & lhs, shape_iterator
const & rhs) noexcept
176 return !(lhs == rhs);
180 friend bool operator<(shape_iterator
const & lhs, shape_iterator
const & rhs) noexcept
182 return (lhs.shape_ <= rhs.shape_) && (lhs.text_right < rhs.text_right);
186 friend bool operator>(shape_iterator
const & lhs, shape_iterator
const & rhs) noexcept
188 return (lhs.shape_ >= rhs.shape_) && (lhs.text_right > rhs.text_right);
192 friend bool operator<=(shape_iterator
const & lhs, shape_iterator
const & rhs) noexcept
194 return (lhs.shape_ <= rhs.shape_) && (lhs.text_right <= rhs.text_right);
198 friend bool operator>=(shape_iterator
const & lhs, shape_iterator
const & rhs) noexcept
200 return (lhs.shape_ >= rhs.shape_) && (lhs.text_right >= rhs.text_right);
206 shape_iterator & operator++() noexcept
213 shape_iterator operator++(
int) noexcept
215 shape_iterator tmp{*
this};
223 shape_iterator & operator--() noexcept
225 requires
std::bidirectional_iterator<it_t>
235 shape_iterator operator--(
int) noexcept
237 requires std::bidirectional_iterator<it_t>
240 shape_iterator tmp{*
this};
248 shape_iterator & operator+=(difference_type
const skip) noexcept
250 requires std::random_access_iterator<it_t>
260 shape_iterator operator+(difference_type
const skip)
const noexcept
262 requires std::random_access_iterator<it_t>
265 shape_iterator tmp{*
this};
272 friend shape_iterator operator+(difference_type
const skip, shape_iterator
const & it) noexcept
274 requires std::random_access_iterator<it_t>
283 shape_iterator & operator-=(difference_type
const skip) noexcept
285 requires std::random_access_iterator<it_t>
296 shape_iterator operator-(difference_type
const skip)
const noexcept
298 requires std::random_access_iterator<it_t>
301 shape_iterator tmp{*
this};
308 friend shape_iterator operator-(difference_type
const skip, shape_iterator
const & it) noexcept
310 requires std::random_access_iterator<it_t>
320 difference_type operator-(shape_iterator
const & lhs)
const noexcept
322 requires std::random_access_iterator<it_t>
325 return static_cast<difference_type>(text_right - lhs.text_right);
331 friend difference_type operator-(sentinel_t
const & lhs, shape_iterator
const & rhs) noexcept
333 requires std::sized_sentinel_for<sentinel_t, it_t>
336 return static_cast<difference_type>(lhs - rhs.text_right);
342 friend difference_type operator-(shape_iterator
const & lhs, sentinel_t
const & rhs) noexcept
344 requires std::sized_sentinel_for<it_t, sentinel_t>
347 return static_cast<difference_type>(lhs.text_right - rhs);
353 value_type operator[](difference_type
const n)
355 requires std::random_access_iterator<it_t>
364 value_type operator*() const noexcept
366 return hash_value +
to_rank(*text_right);
371 using alphabet_t = value_type_t<it_t>;
374 static constexpr
auto const sigma{alphabet_size<alphabet_t>};
377 size_t hash_value{0};
380 size_t roll_factor{0};
400 std::ranges::advance(text_left, 1);
409 void hash_forward(difference_type
const skip)
411 requires std::random_access_iterator<it_t>
414 std::ranges::advance(text_left, skip);
423 requires
std::bidirectional_iterator<it_t>
428 hash_roll_backward();
432 std::ranges::advance(text_left, -1);
441 void hash_backward(difference_type
const skip)
443 std::ranges::advance(text_left, -skip);
450 text_right = text_left;
453 for (
size_t i{0}; i < shape_.size() - 1u; ++i)
455 hash_value += shape_[i] *
to_rank(*text_right);
456 hash_value *= shape_[i] ? sigma : 1;
457 std::ranges::advance(text_right, 1);
462 void hash_roll_forward()
464 hash_value -=
to_rank(*(text_left)) * roll_factor;
465 hash_value +=
to_rank(*(text_right));
468 std::ranges::advance(text_left, 1);
469 std::ranges::advance(text_right, 1);
475 void hash_roll_backward()
477 requires
std::bidirectional_iterator<it_t>
480 std::ranges::advance(text_left, -1);
481 std::ranges::advance(text_right, -1);
484 hash_value -=
to_rank(*(text_right));
485 hash_value +=
to_rank(*(text_left)) * roll_factor;
493 kmer_hash_view() =
default;
494 kmer_hash_view(kmer_hash_view
const & rhs) =
default;
495 kmer_hash_view(kmer_hash_view && rhs) =
default;
496 kmer_hash_view & operator=(kmer_hash_view
const & rhs) =
default;
497 kmer_hash_view & operator=(kmer_hash_view && rhs) =
default;
498 ~kmer_hash_view() =
default;
504 kmer_hash_view(urng_t urange_, shape
const & s_) : urange{
std::move(urange_)}, shape_{s_}
506 if (shape_.size() > (64 / std::log2(
alphabet_size<reference_t<urng_t>>)))
509 "The alphabet or shape size must be reduced."};
517 template <
typename rng_t>
520 std::ranges::viewable_range<rng_t> &&
523 kmer_hash_view(rng_t && urange_, shape
const & s_) :
526 if (shape_.size() > (64 / std::log2(
alphabet_size<reference_t<urng_t>>)))
529 "The alphabet or shape size must be reduced."};
550 auto begin() noexcept
556 auto begin() const noexcept
565 auto cbegin() const noexcept
590 return std::ranges::end(urange);
594 auto end() const noexcept
599 return std::ranges::end(urange);
603 auto cend() const noexcept
614 template <std::ranges::viewable_range rng_t>
615 kmer_hash_view(rng_t &&, shape
const & shape_) -> kmer_hash_view<std::ranges::all_view<rng_t>>;
626 constexpr
auto operator()(shape
const & shape_)
const
628 return adaptor_from_functor{*
this, shape_};
638 template <std::ranges::range urng_t>
639 constexpr
auto operator()(urng_t && urange, shape
const & shape_)
const
641 static_assert(std::ranges::viewable_range<urng_t>,
642 "The range parameter to views::kmer_hash cannot be a temporary of a non-view range.");
643 static_assert(std::ranges::forward_range<urng_t>,
644 "The range parameter to views::kmer_hash must model std::ranges::forward_range.");
646 "The range parameter to views::kmer_hash must be over elements of seqan3::semialphabet.");
648 return kmer_hash_view{std::forward<urng_t>(urange), shape_};
705 inline constexpr
auto kmer_hash = detail::kmer_hash_fn{};