24namespace seqan3::detail
41template <std::ranges::view underlying_range_type>
42 requires std::ranges::forward_range<underlying_range_type> && std::ranges::common_range<underlying_range_type>
43class pairwise_combine_view :
public std::ranges::view_interface<pairwise_combine_view<underlying_range_type>>
47 template <
typename range_type>
55 using iterator = basic_iterator<underlying_range_type>;
57 using const_iterator =
58 transformation_trait_or_t<std::type_identity<basic_iterator<underlying_range_type const>>,
void>;
65 pairwise_combine_view() =
default;
66 pairwise_combine_view(pairwise_combine_view
const &) =
default;
67 pairwise_combine_view(pairwise_combine_view &&) =
default;
68 pairwise_combine_view & operator=(pairwise_combine_view
const &) =
default;
69 pairwise_combine_view & operator=(pairwise_combine_view &&) =
default;
70 ~pairwise_combine_view() =
default;
88 explicit constexpr pairwise_combine_view(underlying_range_type range) : u_range{
std::
move(range)}
91 if (std::ranges::empty(u_range))
93 back_iterator = std::ranges::end(u_range);
97 if constexpr (std::ranges::bidirectional_range<underlying_range_type>)
99 back_iterator = std::ranges::prev(std::ranges::end(u_range));
104 if constexpr (std::ranges::sized_range<underlying_range_type>)
110 auto tmp_it = back_iterator;
113 back_iterator = tmp_it;
115 while (++tmp_it != std::ranges::end(u_range));
140 template <
typename other_range_t>
141 requires (!std::same_as<std::remove_cvref_t<other_range_t>, pairwise_combine_view>)
142 && std::ranges::viewable_range<other_range_t>
144 std::constructible_from<underlying_range_type,
149 explicit constexpr pairwise_combine_view(other_range_t && range) :
150 pairwise_combine_view{std::views::all(std::forward<other_range_t>(range))}
169 constexpr iterator
begin() noexcept
175 constexpr const_iterator
begin() const noexcept
194 constexpr iterator
end() noexcept
200 constexpr const_iterator
end() const noexcept
211 constexpr auto size() const noexcept
212 requires
std::ranges::sized_range<underlying_range_type>
221 underlying_range_type u_range{};
223 std::ranges::iterator_t<underlying_range_type> back_iterator{};
231template <std::ranges::viewable_range other_range_t>
232pairwise_combine_view(other_range_t && range) -> pairwise_combine_view<std::views::all_t<other_range_t>>;
248template <std::ranges::view underlying_range_type>
249 requires std::ranges::forward_range<underlying_range_type> && std::ranges::common_range<underlying_range_type>
250template <
typename range_type>
251class pairwise_combine_view<underlying_range_type>::basic_iterator :
252 public maybe_iterator_category<std::ranges::iterator_t<range_type>>
256 template <
typename other_range_type>
258 friend class basic_iterator;
261 using underlying_iterator_type = std::ranges::iterator_t<range_type>;
277 using reference = common_tuple<underlying_ref_t, underlying_ref_t>;
279 using pointer = void;
281 using iterator_concept = detail::iterator_concept_tag_t<underlying_iterator_type>;
287 basic_iterator() =
default;
288 basic_iterator(basic_iterator
const &) =
default;
289 basic_iterator(basic_iterator &&) =
default;
290 basic_iterator & operator=(basic_iterator
const &) =
default;
291 basic_iterator & operator=(basic_iterator &&) =
default;
292 ~basic_iterator() =
default;
306 constexpr basic_iterator(underlying_iterator_type iter,
307 underlying_iterator_type begin_it,
308 underlying_iterator_type end_it) noexcept :
310 second_it{std::ranges::next(iter, 1, end_it)},
323 template <
typename other_range_type>
324 requires std::convertible_to<other_range_type, range_type &>
326 constexpr basic_iterator(basic_iterator<other_range_type> other) noexcept :
327 basic_iterator{std::move(other.first_it), std::move(other.begin_it), std::move(other.end_it)}
335 constexpr reference operator*() const noexcept(noexcept(*
std::declval<underlying_iterator_type>()))
337 return reference{*first_it, *second_it};
343 constexpr reference operator[](
size_t const index)
const
344 noexcept(
noexcept(std::declval<basic_iterator &>().from_index(1)))
345 requires std::random_access_iterator<underlying_iterator_type>
347 return *(*
this + index);
355 constexpr basic_iterator &
356 operator++() noexcept(noexcept(++
std::declval<underlying_iterator_type &>()))
358 if (++second_it == end_it)
361 second_it = first_it;
368 constexpr basic_iterator
369 operator++(
int )
noexcept(
noexcept(std::declval<underlying_iterator_type &>()++))
371 basic_iterator tmp{*
this};
377 constexpr basic_iterator &
378 operator--() noexcept(noexcept(--
std::declval<underlying_iterator_type &>()))
379 requires
std::bidirectional_iterator<underlying_iterator_type>
381 if (--second_it == first_it)
391 constexpr basic_iterator
392 operator--(
int )
noexcept(
noexcept(std::declval<underlying_iterator_type &>()--))
393 requires std::bidirectional_iterator<underlying_iterator_type>
395 basic_iterator tmp{*
this};
402 constexpr basic_iterator &
403 operator+=(difference_type
const offset)
noexcept(
noexcept(std::declval<basic_iterator &>().from_index(1)))
404 requires std::random_access_iterator<underlying_iterator_type>
406 from_index(to_index() + offset);
412 constexpr basic_iterator operator+(difference_type
const offset)
const
413 noexcept(
noexcept(std::declval<basic_iterator &>() += 1))
414 requires std::random_access_iterator<underlying_iterator_type>
416 basic_iterator tmp{*
this};
417 return (tmp += offset);
422 constexpr friend basic_iterator
423 operator+(difference_type
const offset,
424 basic_iterator iter)
noexcept(
noexcept(std::declval<basic_iterator<range_type> &>().from_index(1)))
425 requires std::random_access_iterator<underlying_iterator_type>
427 iter.from_index(iter.to_index() +
offset);
433 constexpr basic_iterator &
434 operator-=(difference_type
const offset)
noexcept(
noexcept(std::declval<basic_iterator &>().from_index(1)))
435 requires std::random_access_iterator<underlying_iterator_type>
437 from_index(to_index() - offset);
443 constexpr basic_iterator operator-(difference_type
const offset)
const
444 noexcept(
noexcept(std::declval<basic_iterator &>() -= 1))
445 requires std::random_access_iterator<underlying_iterator_type>
447 basic_iterator tmp{*
this};
448 return (tmp -= offset);
453 template <
typename other_range_type>
454 requires std::random_access_iterator<underlying_iterator_type>
456 constexpr difference_type operator-(basic_iterator<other_range_type>
const & rhs)
const
457 noexcept(
noexcept(std::declval<basic_iterator &>().to_index()))
459 return static_cast<difference_type
>(to_index() - rhs.to_index());
473 template <
typename other_range_type>
474 requires std::equality_comparable_with<underlying_iterator_type, std::ranges::iterator_t<other_range_type>>
476 constexpr bool operator==(basic_iterator<other_range_type>
const & rhs)
const
477 noexcept(
noexcept(std::declval<underlying_iterator_type &>() == std::declval<underlying_iterator_type &>()))
479 return std::tie(first_it, second_it) ==
std::tie(rhs.first_it, rhs.second_it);
483 template <
typename other_range_type>
484 requires std::equality_comparable_with<underlying_iterator_type, std::ranges::iterator_t<other_range_type>>
486 constexpr bool operator!=(basic_iterator<other_range_type>
const & rhs)
const
487 noexcept(
noexcept(std::declval<underlying_iterator_type &>() != std::declval<underlying_iterator_type &>()))
489 return !(*
this == rhs);
493 template <
typename other_range_type>
494 requires std::totally_ordered_with<underlying_iterator_type, std::ranges::iterator_t<other_range_type>>
496 constexpr bool operator<(basic_iterator<other_range_type>
const & rhs)
const
497 noexcept(
noexcept(std::declval<underlying_iterator_type &>() < std::declval<underlying_iterator_type &>()))
499 return std::tie(first_it, second_it) <
std::tie(rhs.first_it, rhs.second_it);
503 template <
typename other_range_type>
504 requires std::totally_ordered_with<underlying_iterator_type, std::ranges::iterator_t<other_range_type>>
506 constexpr bool operator>(basic_iterator<other_range_type>
const & rhs)
const
507 noexcept(
noexcept(std::declval<underlying_iterator_type &>() > std::declval<underlying_iterator_type &>()))
510 return std::tie(first_it, second_it) >
std::tie(rhs.first_it, rhs.second_it);
514 template <
typename other_range_type>
515 requires std::totally_ordered_with<underlying_iterator_type, std::ranges::iterator_t<other_range_type>>
517 constexpr bool operator<=(basic_iterator<other_range_type>
const & rhs)
const
518 noexcept(
noexcept(std::declval<underlying_iterator_type &>() <= std::declval<underlying_iterator_type &>()))
520 return std::tie(first_it, second_it) <=
std::tie(rhs.first_it, rhs.second_it);
524 template <
typename other_range_type>
525 requires std::totally_ordered_with<underlying_iterator_type, std::ranges::iterator_t<other_range_type>>
527 constexpr bool operator>=(basic_iterator<other_range_type>
const & rhs)
const
528 noexcept(
noexcept(std::declval<underlying_iterator_type &>() >= std::declval<underlying_iterator_type &>()))
530 return std::tie(first_it, second_it) >=
std::tie(rhs.first_it, rhs.second_it);
547 constexpr size_t to_index() const
548 noexcept(noexcept(
std::declval<underlying_iterator_type &>() -
std::declval<underlying_iterator_type &>()))
549 requires
std::random_access_iterator<underlying_iterator_type>
551 size_t src_size = end_it - begin_it;
552 size_t index_i = first_it - begin_it;
553 size_t index_j = second_it - begin_it;
554 return (src_size * (src_size - 1) / 2) - (src_size - index_i) * ((src_size - index_i) - 1) / 2 + index_j
562 constexpr void from_index(
size_t const index)
noexcept(
noexcept(
563 std::declval<underlying_iterator_type &>()
564 - std::declval<underlying_iterator_type &>()) &&
noexcept(std::declval<underlying_iterator_type &>() + 1))
565 requires std::random_access_iterator<underlying_iterator_type>
567 size_t src_size = end_it - begin_it;
569 src_size - 2 -
std::floor(
std::sqrt(-8 * index + 4 * src_size * (src_size - 1) - 7) / 2.0 - 0.5);
571 index + index_i + 1 - src_size * (src_size - 1) / 2 + (src_size - index_i) * ((src_size - index_i) - 1) / 2;
572 first_it = begin_it + index_i;
573 second_it = begin_it + index_j;
577 underlying_iterator_type first_it{};
579 underlying_iterator_type second_it{};
581 underlying_iterator_type begin_it{};
583 underlying_iterator_type end_it{};
652inline constexpr auto pairwise_combine = detail::adaptor_for_view_without_args<detail::pairwise_combine_view>{};
Provides seqan3::detail::adaptor_for_view_without_args.
Provides seqan3::common_tuple.
@ offset
Sequence (seqan3::field::seq) relative start position (0-based), unsigned value.
constexpr size_t size
The size of a type pack.
Definition: traits.hpp:146
constexpr auto pairwise_combine
A view adaptor that generates all pairwise combinations of the elements of the underlying range.
Definition: pairwise_combine.hpp:652
Specifies requirements of an input range type for which the const version of that type satisfies the ...
Provides various transformation traits for use on iterators.
The SeqAn namespace for views.
Definition: char_strictly_to.hpp:22
SeqAn specific customisations in the standard namespace.
Additional non-standard concepts for ranges.