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>)
106 std::ranges::advance(back_iterator, std::ranges::size(u_range) - 1);
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>
214 auto const size = std::ranges::size(u_range);
215 return (size * (size - 1)) / 2;
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>
257 friend class basic_iterator;
260 using underlying_iterator_type = std::ranges::iterator_t<range_type>;
276 using reference = common_tuple<underlying_ref_t, underlying_ref_t>;
278 using pointer = void;
280 using iterator_concept = detail::iterator_concept_tag_t<underlying_iterator_type>;
286 basic_iterator() =
default;
287 basic_iterator(basic_iterator
const &) =
default;
288 basic_iterator(basic_iterator &&) =
default;
289 basic_iterator & operator=(basic_iterator
const &) =
default;
290 basic_iterator & operator=(basic_iterator &&) =
default;
291 ~basic_iterator() =
default;
305 constexpr basic_iterator(underlying_iterator_type iter,
306 underlying_iterator_type begin_it,
307 underlying_iterator_type end_it) noexcept :
309 second_it{std::ranges::next(iter, 1, end_it)},
322 template <
typename other_range_type>
323 requires std::convertible_to<other_range_type, range_type &>
325 constexpr basic_iterator(basic_iterator<other_range_type> other) noexcept :
326 basic_iterator{std::move(other.first_it), std::move(other.begin_it), std::move(other.end_it)}
334 constexpr reference operator*() const noexcept(noexcept(*
std::declval<underlying_iterator_type>()))
336 return reference{*first_it, *second_it};
342 constexpr reference operator[](
size_t const index)
const
343 noexcept(
noexcept(std::declval<basic_iterator &>().from_index(1)))
344 requires std::random_access_iterator<underlying_iterator_type>
346 return *(*
this + index);
354 constexpr basic_iterator &
355 operator++() noexcept(noexcept(++
std::declval<underlying_iterator_type &>()))
357 if (++second_it == end_it)
360 second_it = first_it;
367 constexpr basic_iterator
368 operator++(
int )
noexcept(
noexcept(std::declval<underlying_iterator_type &>()++))
370 basic_iterator tmp{*
this};
376 constexpr basic_iterator &
377 operator--() noexcept(noexcept(--
std::declval<underlying_iterator_type &>()))
378 requires
std::bidirectional_iterator<underlying_iterator_type>
380 if (--second_it == first_it)
390 constexpr basic_iterator
391 operator--(
int )
noexcept(
noexcept(std::declval<underlying_iterator_type &>()--))
392 requires std::bidirectional_iterator<underlying_iterator_type>
394 basic_iterator tmp{*
this};
401 constexpr basic_iterator &
402 operator+=(difference_type
const offset)
noexcept(
noexcept(std::declval<basic_iterator &>().from_index(1)))
403 requires std::random_access_iterator<underlying_iterator_type>
405 from_index(to_index() +
offset);
411 constexpr basic_iterator operator+(difference_type
const offset)
const
412 noexcept(
noexcept(std::declval<basic_iterator &>() += 1))
413 requires std::random_access_iterator<underlying_iterator_type>
415 basic_iterator tmp{*
this};
421 constexpr friend basic_iterator
422 operator+(difference_type
const offset,
423 basic_iterator iter)
noexcept(
noexcept(std::declval<basic_iterator<range_type> &>().from_index(1)))
424 requires std::random_access_iterator<underlying_iterator_type>
426 iter.from_index(iter.to_index() +
offset);
432 constexpr basic_iterator &
433 operator-=(difference_type
const offset)
noexcept(
noexcept(std::declval<basic_iterator &>().from_index(1)))
434 requires std::random_access_iterator<underlying_iterator_type>
436 from_index(to_index() -
offset);
442 constexpr basic_iterator operator-(difference_type
const offset)
const
443 noexcept(
noexcept(std::declval<basic_iterator &>() -= 1))
444 requires std::random_access_iterator<underlying_iterator_type>
446 basic_iterator tmp{*
this};
452 template <
typename other_range_type>
453 requires std::random_access_iterator<underlying_iterator_type>
455 constexpr difference_type operator-(basic_iterator<other_range_type>
const & rhs)
const
456 noexcept(
noexcept(std::declval<basic_iterator &>().to_index()))
458 return static_cast<difference_type
>(to_index() - rhs.to_index());
472 template <
typename other_range_type>
473 requires std::equality_comparable_with<underlying_iterator_type, std::ranges::iterator_t<other_range_type>>
475 constexpr bool operator==(basic_iterator<other_range_type>
const & rhs)
const
476 noexcept(
noexcept(std::declval<underlying_iterator_type &>() == std::declval<underlying_iterator_type &>()))
478 return std::tie(first_it, second_it) ==
std::tie(rhs.first_it, rhs.second_it);
482 template <
typename other_range_type>
483 requires std::equality_comparable_with<underlying_iterator_type, std::ranges::iterator_t<other_range_type>>
485 constexpr bool operator!=(basic_iterator<other_range_type>
const & rhs)
const
486 noexcept(
noexcept(std::declval<underlying_iterator_type &>() != std::declval<underlying_iterator_type &>()))
488 return !(*
this == rhs);
492 template <
typename other_range_type>
493 requires std::totally_ordered_with<underlying_iterator_type, std::ranges::iterator_t<other_range_type>>
495 constexpr bool operator<(basic_iterator<other_range_type>
const & rhs)
const
496 noexcept(
noexcept(std::declval<underlying_iterator_type &>() < std::declval<underlying_iterator_type &>()))
498 return std::tie(first_it, second_it) <
std::tie(rhs.first_it, rhs.second_it);
502 template <
typename other_range_type>
503 requires std::totally_ordered_with<underlying_iterator_type, std::ranges::iterator_t<other_range_type>>
505 constexpr bool operator>(basic_iterator<other_range_type>
const & rhs)
const
506 noexcept(
noexcept(std::declval<underlying_iterator_type &>() > std::declval<underlying_iterator_type &>()))
509 return std::tie(first_it, second_it) >
std::tie(rhs.first_it, rhs.second_it);
513 template <
typename other_range_type>
514 requires std::totally_ordered_with<underlying_iterator_type, std::ranges::iterator_t<other_range_type>>
516 constexpr bool operator<=(basic_iterator<other_range_type>
const & rhs)
const
517 noexcept(
noexcept(std::declval<underlying_iterator_type &>() <= std::declval<underlying_iterator_type &>()))
519 return std::tie(first_it, second_it) <=
std::tie(rhs.first_it, rhs.second_it);
523 template <
typename other_range_type>
524 requires std::totally_ordered_with<underlying_iterator_type, std::ranges::iterator_t<other_range_type>>
526 constexpr bool operator>=(basic_iterator<other_range_type>
const & rhs)
const
527 noexcept(
noexcept(std::declval<underlying_iterator_type &>() >= std::declval<underlying_iterator_type &>()))
529 return std::tie(first_it, second_it) >=
std::tie(rhs.first_it, rhs.second_it);
546 constexpr size_t to_index() const
547 noexcept(noexcept(
std::declval<underlying_iterator_type &>() -
std::declval<underlying_iterator_type &>()))
548 requires
std::random_access_iterator<underlying_iterator_type>
550 size_t src_size = end_it - begin_it;
551 size_t index_i = first_it - begin_it;
552 size_t index_j = second_it - begin_it;
553 return (src_size * (src_size - 1) / 2) - (src_size - index_i) * ((src_size - index_i) - 1) / 2 + index_j
561 constexpr void from_index(
size_t const index)
noexcept(
noexcept(
562 std::declval<underlying_iterator_type &>()
563 - std::declval<underlying_iterator_type &>()) &&
noexcept(std::declval<underlying_iterator_type &>() + 1))
564 requires std::random_access_iterator<underlying_iterator_type>
566 size_t src_size = end_it - begin_it;
568 src_size - 2 -
std::floor(
std::sqrt(-8 * index + 4 * src_size * (src_size - 1) - 7) / 2.0 - 0.5);
570 index + index_i + 1 - src_size * (src_size - 1) / 2 + (src_size - index_i) * ((src_size - index_i) - 1) / 2;
571 first_it = begin_it + index_i;
572 second_it = begin_it + index_j;
576 underlying_iterator_type first_it{};
578 underlying_iterator_type second_it{};
580 underlying_iterator_type begin_it{};
582 underlying_iterator_type end_it{};
651inline 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: type_pack/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:651
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.