21namespace seqan3::detail
38template <std::ranges::view underlying_range_type>
39 requires std::ranges::forward_range<underlying_range_type> && std::ranges::common_range<underlying_range_type>
40class pairwise_combine_view :
public std::ranges::view_interface<pairwise_combine_view<underlying_range_type>>
44 template <
typename range_type>
52 using iterator = basic_iterator<underlying_range_type>;
54 using const_iterator =
55 transformation_trait_or_t<std::type_identity<basic_iterator<underlying_range_type const>>,
void>;
62 pairwise_combine_view() =
default;
63 pairwise_combine_view(pairwise_combine_view
const &) =
default;
64 pairwise_combine_view(pairwise_combine_view &&) =
default;
65 pairwise_combine_view & operator=(pairwise_combine_view
const &) =
default;
66 pairwise_combine_view & operator=(pairwise_combine_view &&) =
default;
67 ~pairwise_combine_view() =
default;
85 explicit constexpr pairwise_combine_view(underlying_range_type range) : u_range{std::move(range)}
88 if (std::ranges::empty(u_range))
90 back_iterator = std::ranges::end(u_range);
94 if constexpr (std::ranges::bidirectional_range<underlying_range_type>)
96 back_iterator = std::ranges::prev(std::ranges::end(u_range));
100 back_iterator = std::ranges::begin(u_range);
101 if constexpr (std::ranges::sized_range<underlying_range_type>)
103 std::ranges::advance(back_iterator, std::ranges::size(u_range) - 1);
107 auto tmp_it = back_iterator;
110 back_iterator = tmp_it;
112 while (++tmp_it != std::ranges::end(u_range));
137 template <
typename other_range_t>
138 requires (!std::same_as<std::remove_cvref_t<other_range_t>, pairwise_combine_view>)
139 && std::ranges::viewable_range<other_range_t>
141 std::constructible_from<underlying_range_type,
142 std::ranges::ref_view<std::remove_reference_t<other_range_t>>>
146 explicit constexpr pairwise_combine_view(other_range_t && range) :
147 pairwise_combine_view{std::views::all(std::
forward<other_range_t>(range))}
166 constexpr iterator begin() noexcept
168 return {std::ranges::begin(u_range), std::ranges::begin(u_range), std::ranges::end(u_range)};
172 constexpr const_iterator begin() const noexcept
173 requires const_iterable_range<underlying_range_type>
175 return {std::ranges::begin(u_range), std::ranges::begin(u_range), std::ranges::end(u_range)};
191 constexpr iterator end() noexcept
193 return {back_iterator, std::ranges::begin(u_range), std::ranges::end(u_range)};
197 constexpr const_iterator end() const noexcept
198 requires const_iterable_range<underlying_range_type>
200 return {back_iterator, std::ranges::begin(u_range), std::ranges::end(u_range)};
208 constexpr auto size() const noexcept
209 requires std::ranges::sized_range<underlying_range_type>
211 auto const size = std::ranges::size(u_range);
212 return (size * (size - 1)) / 2;
218 underlying_range_type u_range;
220 std::ranges::iterator_t<underlying_range_type> back_iterator{};
228template <std::ranges::viewable_range other_range_t>
229pairwise_combine_view(other_range_t && range) -> pairwise_combine_view<std::views::all_t<other_range_t>>;
245template <std::ranges::view underlying_range_type>
246 requires std::ranges::forward_range<underlying_range_type> && std::ranges::common_range<underlying_range_type>
247template <
typename range_type>
248class pairwise_combine_view<underlying_range_type>::basic_iterator :
249 public maybe_iterator_category<std::ranges::iterator_t<range_type>>
253 template <
typename other_range_type>
254 friend class basic_iterator;
257 using underlying_iterator_type = std::ranges::iterator_t<range_type>;
259 using underlying_val_t = std::iter_value_t<underlying_iterator_type>;
261 using underlying_ref_t = std::iter_reference_t<underlying_iterator_type>;
269 using difference_type = std::ptrdiff_t;
271 using value_type = std::tuple<underlying_val_t, underlying_val_t>;
275 using pointer = void;
277 using iterator_concept = detail::iterator_concept_tag_t<underlying_iterator_type>;
283 basic_iterator() =
default;
284 basic_iterator(basic_iterator
const &) =
default;
285 basic_iterator(basic_iterator &&) =
default;
286 basic_iterator & operator=(basic_iterator
const &) =
default;
287 basic_iterator & operator=(basic_iterator &&) =
default;
288 ~basic_iterator() =
default;
302 constexpr basic_iterator(underlying_iterator_type iter,
303 underlying_iterator_type begin_it,
304 underlying_iterator_type end_it) noexcept :
306 second_it{std::ranges::next(iter, 1, end_it)},
319 template <
typename other_range_type>
320 requires std::convertible_to<other_range_type, range_type &>
321 && std::same_as<std::remove_const_t<other_range_type>, std::remove_const_t<range_type>>
322 constexpr basic_iterator(basic_iterator<other_range_type> other) noexcept :
323 basic_iterator{std::move(other.first_it), std::move(other.begin_it), std::move(other.end_it)}
331 constexpr reference operator*() const noexcept(noexcept(*std::declval<underlying_iterator_type>()))
333 return reference{*first_it, *second_it};
339 constexpr reference operator[](
size_t const index)
const
341 requires std::random_access_iterator<underlying_iterator_type>
343 return *(*
this + index);
351 constexpr basic_iterator & operator++()
352 noexcept(noexcept(++std::declval<underlying_iterator_type &>()))
354 if (++second_it == end_it)
357 second_it = first_it;
364 constexpr basic_iterator operator++(
int )
367 basic_iterator tmp{*
this};
373 constexpr basic_iterator & operator--()
374 noexcept(noexcept(--std::declval<underlying_iterator_type &>()))
375 requires std::bidirectional_iterator<underlying_iterator_type>
377 if (--second_it == first_it)
387 constexpr basic_iterator operator--(
int )
389 requires std::bidirectional_iterator<underlying_iterator_type>
391 basic_iterator tmp{*
this};
398 constexpr basic_iterator & operator+=(difference_type
const offset)
400 requires std::random_access_iterator<underlying_iterator_type>
402 from_index(to_index() +
offset);
408 constexpr basic_iterator operator+(difference_type
const offset)
const
410 requires std::random_access_iterator<underlying_iterator_type>
412 basic_iterator tmp{*
this};
418 constexpr friend basic_iterator operator+(difference_type
const offset, basic_iterator iter)
420 requires std::random_access_iterator<underlying_iterator_type>
422 iter.from_index(iter.to_index() +
offset);
428 constexpr basic_iterator & operator-=(difference_type
const offset)
430 requires std::random_access_iterator<underlying_iterator_type>
432 from_index(to_index() -
offset);
438 constexpr basic_iterator operator-(difference_type
const offset)
const
440 requires std::random_access_iterator<underlying_iterator_type>
442 basic_iterator tmp{*
this};
448 template <
typename other_range_type>
449 requires std::random_access_iterator<underlying_iterator_type>
450 && std::same_as<std::remove_const_t<range_type>, std::remove_const_t<other_range_type>>
451 constexpr difference_type operator-(basic_iterator<other_range_type>
const & rhs)
const
454 return static_cast<difference_type
>(to_index() - rhs.to_index());
468 template <
typename other_range_type>
469 requires std::equality_comparable_with<underlying_iterator_type, std::ranges::iterator_t<other_range_type>>
470 && std::same_as<std::remove_const_t<range_type>, std::remove_const_t<other_range_type>>
471 constexpr bool operator==(basic_iterator<other_range_type>
const & rhs)
const
474 return std::tie(first_it, second_it) ==
std::tie(rhs.first_it, rhs.second_it);
478 template <
typename other_range_type>
479 requires std::equality_comparable_with<underlying_iterator_type, std::ranges::iterator_t<other_range_type>>
480 && std::same_as<std::remove_const_t<range_type>, std::remove_const_t<other_range_type>>
481 constexpr bool operator!=(basic_iterator<other_range_type>
const & rhs)
const
484 return !(*
this == rhs);
488 template <
typename other_range_type>
489 requires std::totally_ordered_with<underlying_iterator_type, std::ranges::iterator_t<other_range_type>>
490 && std::same_as<std::remove_const_t<range_type>, std::remove_const_t<other_range_type>>
491 constexpr bool operator<(basic_iterator<other_range_type>
const & rhs)
const
494 return std::tie(first_it, second_it) <
std::tie(rhs.first_it, rhs.second_it);
498 template <
typename other_range_type>
499 requires std::totally_ordered_with<underlying_iterator_type, std::ranges::iterator_t<other_range_type>>
500 && std::same_as<std::remove_const_t<range_type>, std::remove_const_t<other_range_type>>
501 constexpr bool operator>(basic_iterator<other_range_type>
const & rhs)
const
505 return std::tie(first_it, second_it) >
std::tie(rhs.first_it, rhs.second_it);
509 template <
typename other_range_type>
510 requires std::totally_ordered_with<underlying_iterator_type, std::ranges::iterator_t<other_range_type>>
511 && std::same_as<std::remove_const_t<range_type>, std::remove_const_t<other_range_type>>
512 constexpr bool operator<=(basic_iterator<other_range_type>
const & rhs)
const
515 return std::tie(first_it, second_it) <=
std::tie(rhs.first_it, rhs.second_it);
519 template <
typename other_range_type>
520 requires std::totally_ordered_with<underlying_iterator_type, std::ranges::iterator_t<other_range_type>>
521 && std::same_as<std::remove_const_t<range_type>, std::remove_const_t<other_range_type>>
522 constexpr bool operator>=(basic_iterator<other_range_type>
const & rhs)
const
525 return std::tie(first_it, second_it) >=
std::tie(rhs.first_it, rhs.second_it);
542 constexpr size_t to_index() const
543 noexcept(noexcept(std::declval<underlying_iterator_type &>() - std::declval<underlying_iterator_type &>()))
544 requires std::random_access_iterator<underlying_iterator_type>
546 size_t src_size = end_it - begin_it;
547 size_t index_i = first_it - begin_it;
548 size_t index_j = second_it - begin_it;
549 return (src_size * (src_size - 1) / 2) - (src_size - index_i) * ((src_size - index_i) - 1) / 2 + index_j
557 constexpr void from_index(
size_t const index)
560 requires std::random_access_iterator<underlying_iterator_type>
562 size_t src_size = end_it - begin_it;
564 src_size - 2 -
std::floor(
std::sqrt(-8 * index + 4 * src_size * (src_size - 1) - 7) / 2.0 - 0.5);
566 index + index_i + 1 - src_size * (src_size - 1) / 2 + (src_size - index_i) * ((src_size - index_i) - 1) / 2;
567 first_it = begin_it + index_i;
568 second_it = begin_it + index_j;
572 underlying_iterator_type first_it{};
574 underlying_iterator_type second_it{};
576 underlying_iterator_type begin_it{};
578 underlying_iterator_type end_it{};
647inline 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.
Definition record.hpp:66
seqan::stl::tuple< t... > common_tuple
A std::tuple implementation that incorporates most changes from C++23's standard library.
Definition common_tuple.hpp:24
constexpr auto pairwise_combine
A view adaptor that generates all pairwise combinations of the elements of the underlying range.
Definition pairwise_combine.hpp:647
Provides various transformation traits for use on iterators.
The SeqAn namespace for views.
Definition char_strictly_to.hpp:19
Additional non-standard concepts for ranges.