20namespace seqan3::detail
38template <std::ranges::view urng_t>
39class kmer_hash_view :
public std::ranges::view_interface<kmer_hash_view<urng_t>>
42 static_assert(std::ranges::forward_range<urng_t>,
"The kmer_hash_view only works on forward_ranges");
44 "The reference type of the underlying range must model seqan3::semialphabet.");
52 template <
bool const_range>
60 requires std::default_initializable<urng_t>
62 kmer_hash_view(kmer_hash_view const & rhs) = default;
63 kmer_hash_view(kmer_hash_view && rhs) = default;
64 kmer_hash_view & operator=(kmer_hash_view const & rhs) = default;
65 kmer_hash_view & operator=(kmer_hash_view && rhs) = default;
66 ~kmer_hash_view() = default;
72 explicit kmer_hash_view(urng_t urange_, shape const & s_) : urange{std::move(urange_)}, shape_{s_}
77 "The alphabet or shape size must be reduced."};
85 template <
typename rng_t>
86 requires (!std::same_as<std::remove_cvref_t<rng_t>, kmer_hash_view>) && std::ranges::viewable_range<rng_t>
88 explicit kmer_hash_view(rng_t && urange_, shape
const & s_) :
89 urange{std::views::all(std::forward<rng_t>(urange_))},
95 "The alphabet or shape size must be reduced."};
116 auto begin() noexcept
118 return basic_iterator<false>{
std::ranges::begin(urange), std::ranges::end(urange), shape_};
122 auto begin() const noexcept
125 return basic_iterator<true>{
std::ranges::begin(urange), std::ranges::end(urange), shape_};
146 if constexpr (std::ranges::common_range<urng_t>)
147 return basic_iterator<false>{
std::ranges::begin(urange), std::ranges::end(urange), shape_,
true};
149 return std::ranges::end(urange);
153 auto end() const noexcept
157 if constexpr (std::ranges::common_range<urng_t const>)
158 return basic_iterator<true>{
std::ranges::begin(urange), std::ranges::end(urange), shape_,
true};
160 return std::ranges::cend(urange);
168 requires std::ranges::sized_range<urng_t>
170 using size_type = std::ranges::range_size_t<urng_t>;
171 return std::max<size_type>(std::ranges::size(urange) + 1, shape_.size()) - shape_.size();
176 requires
std::ranges::sized_range<urng_t const>
178 using size_type = std::ranges::range_size_t<urng_t const>;
179 return std::max<size_type>(std::ranges::size(urange) + 1, shape_.size()) - shape_.size();
210template <std::ranges::view urng_t>
211template <
bool const_range>
212class kmer_hash_view<urng_t>::basic_iterator :
213 public maybe_iterator_category<maybe_const_iterator_t<const_range, urng_t>>
217 using it_t = maybe_const_iterator_t<const_range, urng_t>;
219 using sentinel_t = maybe_const_sentinel_t<const_range, urng_t>;
221 template <
bool other_const_range>
222 friend class basic_iterator;
231 using value_type = size_t;
233 using pointer = void;
235 using reference = value_type;
239 detail::iterator_concept_tag_t<it_t>>;
245 constexpr basic_iterator() =
default;
246 constexpr basic_iterator(basic_iterator
const &) =
default;
247 constexpr basic_iterator(basic_iterator &&) =
default;
248 constexpr basic_iterator & operator=(basic_iterator
const &) =
default;
249 constexpr basic_iterator & operator=(basic_iterator &&) =
default;
250 ~basic_iterator() =
default;
253 constexpr basic_iterator(basic_iterator<!const_range>
const & it)
noexcept
256 hash_value{std::move(it.hash_value)},
257 roll_factor{std::move(it.roll_factor)},
258 shape_{std::move(it.shape_)},
259 text_left{std::move(it.text_left)},
260 text_right{std::move(it.text_right)}
274 basic_iterator(it_t it_start, sentinel_t it_end, shape s_) :
277 text_right{
std::ranges::
next(text_left, shape_.
size() - 1, it_end)}
279 assert(std::ranges::size(shape_) > 0);
286 if (shape_.size() <= std::ranges::distance(text_left, text_right) + 1)
288 roll_factor =
pow(sigma,
static_cast<size_t>(std::ranges::size(shape_) - 1));
316 basic_iterator(it_t it_start, sentinel_t it_end, shape s_,
bool SEQAN3_DOXYGEN_ONLY(is_end)) : shape_{s_}
318 assert(std::ranges::size(shape_) > 0);
320 auto urange_size = std::ranges::distance(it_start, it_end);
321 auto step = (shape_.size() > urange_size + 1) ? 0 : urange_size - shape_.size() + 1;
322 text_left = std::ranges::next(it_start, step, it_end);
329 if (shape_.size() <= std::ranges::distance(text_left, it_end) + 1)
331 roll_factor =
pow(sigma,
static_cast<size_t>(std::ranges::size(shape_) - 1));
344 friend bool operator==(basic_iterator
const & lhs, sentinel_t
const & rhs)
noexcept
346 return lhs.text_right == rhs;
350 friend bool operator==(sentinel_t
const & lhs, basic_iterator
const & rhs)
noexcept
352 return lhs == rhs.text_right;
356 friend bool operator==(basic_iterator
const & lhs, basic_iterator
const & rhs)
noexcept
358 return std::tie(lhs.text_right, lhs.shape_) ==
std::tie(rhs.text_right, rhs.shape_);
362 friend bool operator!=(basic_iterator
const & lhs, sentinel_t
const & rhs)
noexcept
364 return !(lhs == rhs);
368 friend bool operator!=(sentinel_t
const & lhs, basic_iterator
const & rhs)
noexcept
370 return !(lhs == rhs);
374 friend bool operator!=(basic_iterator
const & lhs, basic_iterator
const & rhs)
noexcept
376 return !(lhs == rhs);
380 friend bool operator<(basic_iterator
const & lhs, basic_iterator
const & rhs)
noexcept
382 return (lhs.shape_ <= rhs.shape_) && (lhs.text_right < rhs.text_right);
386 friend bool operator>(basic_iterator
const & lhs, basic_iterator
const & rhs)
noexcept
388 return (lhs.shape_ >= rhs.shape_) && (lhs.text_right > rhs.text_right);
392 friend bool operator<=(basic_iterator
const & lhs, basic_iterator
const & rhs)
noexcept
394 return (lhs.shape_ <= rhs.shape_) && (lhs.text_right <= rhs.text_right);
398 friend bool operator>=(basic_iterator
const & lhs, basic_iterator
const & rhs)
noexcept
400 return (lhs.shape_ >= rhs.shape_) && (lhs.text_right >= rhs.text_right);
406 basic_iterator & operator++() noexcept
413 basic_iterator operator++(
int)
noexcept
415 basic_iterator tmp{*
this};
423 basic_iterator & operator--() noexcept
424 requires
std::bidirectional_iterator<it_t>
433 basic_iterator operator--(
int)
noexcept
434 requires std::bidirectional_iterator<it_t>
436 basic_iterator tmp{*
this};
444 basic_iterator & operator+=(difference_type
const skip)
noexcept
445 requires std::random_access_iterator<it_t>
454 basic_iterator operator+(difference_type
const skip)
const noexcept
455 requires std::random_access_iterator<it_t>
457 basic_iterator tmp{*
this};
464 friend basic_iterator operator+(difference_type
const skip, basic_iterator
const & it)
noexcept
465 requires std::random_access_iterator<it_t>
473 basic_iterator & operator-=(difference_type
const skip)
noexcept
474 requires std::random_access_iterator<it_t>
484 basic_iterator operator-(difference_type
const skip)
const noexcept
485 requires std::random_access_iterator<it_t>
487 basic_iterator tmp{*
this};
494 friend basic_iterator operator-(difference_type
const skip, basic_iterator
const & it)
noexcept
495 requires std::random_access_iterator<it_t>
504 friend difference_type operator-(basic_iterator
const & lhs, basic_iterator
const & rhs)
noexcept
505 requires std::sized_sentinel_for<it_t, it_t>
507 return static_cast<difference_type
>(lhs.text_right - rhs.text_right);
513 friend difference_type operator-(sentinel_t
const & lhs, basic_iterator
const & rhs)
noexcept
514 requires std::sized_sentinel_for<sentinel_t, it_t>
516 return static_cast<difference_type
>(lhs - rhs.text_right);
522 friend difference_type operator-(basic_iterator
const & lhs, sentinel_t
const & rhs)
noexcept
523 requires std::sized_sentinel_for<it_t, sentinel_t>
525 return static_cast<difference_type
>(lhs.text_right - rhs);
531 reference operator[](difference_type
const n)
const
532 requires std::random_access_iterator<it_t>
538 value_type operator*() const noexcept
540 return hash_value +
to_rank(*text_right);
548 static constexpr auto const sigma{alphabet_size<alphabet_t>};
551 size_t hash_value{0};
554 size_t roll_factor{0};
574 std::ranges::advance(text_left, 1);
583 void hash_forward(difference_type
const skip)
584 requires std::random_access_iterator<it_t>
586 std::ranges::advance(text_left, skip);
594 requires std::bidirectional_iterator<it_t>
598 hash_roll_backward();
602 std::ranges::advance(text_left, -1);
611 void hash_backward(difference_type
const skip)
613 std::ranges::advance(text_left, -skip);
620 text_right = text_left;
623 for (
size_t i{0}; i < shape_.size() - 1u; ++i)
625 hash_value += shape_[i] *
to_rank(*text_right);
626 hash_value *= shape_[i] ? sigma : 1;
627 std::ranges::advance(text_right, 1);
632 void hash_roll_forward()
634 hash_value -=
to_rank(*(text_left)) * roll_factor;
635 hash_value +=
to_rank(*(text_right));
638 std::ranges::advance(text_left, 1);
639 std::ranges::advance(text_right, 1);
645 void hash_roll_backward()
646 requires std::bidirectional_iterator<it_t>
648 std::ranges::advance(text_left, -1);
649 std::ranges::advance(text_right, -1);
652 hash_value -=
to_rank(*(text_right));
653 hash_value +=
to_rank(*(text_left)) * roll_factor;
658template <std::ranges::viewable_range rng_t>
659kmer_hash_view(rng_t &&, shape
const & shape_) -> kmer_hash_view<std::views::all_t<rng_t>>;
671 constexpr auto operator()(shape
const & shape_)
const
673 return adaptor_from_functor{*
this, shape_};
683 template <std::ranges::range urng_t>
684 constexpr auto operator()(urng_t && urange, shape
const & shape_)
const
686 static_assert(std::ranges::viewable_range<urng_t>,
687 "The range parameter to views::kmer_hash cannot be a temporary of a non-view range.");
688 static_assert(std::ranges::forward_range<urng_t>,
689 "The range parameter to views::kmer_hash must model std::ranges::forward_range.");
691 "The range parameter to views::kmer_hash must be over elements of seqan3::semialphabet.");
693 return kmer_hash_view{std::forward<urng_t>(urange), shape_};
750inline 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:849
constexpr auto to_rank
Return the rank representation of a (semi-)alphabet object.
Definition: alphabet/concept.hpp:155
constexpr auto kmer_hash
Computes hash values for each position of a range via a given shape.
Definition: kmer_hash.hpp:750
constexpr size_t size
The size of a type pack.
Definition: type_pack/traits.hpp:146
base_t pow(base_t base, exp_t exp)
Computes the value of base raised to the power exp.
Definition: math.hpp:122
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:22
SeqAn specific customisations in the standard namespace.
Provides overloads for std::hash.