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>
139 && std::ranges::viewable_range<other_range_t>
141 std::constructible_from<underlying_range_type,
146 explicit constexpr pairwise_combine_view(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
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
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>;
273 using reference = common_tuple<underlying_ref_t, underlying_ref_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>
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
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 )
391 basic_iterator tmp{*
this};
398 constexpr basic_iterator & operator+=(difference_type
const offset)
402 from_index(to_index() +
offset);
408 constexpr basic_iterator operator+(difference_type
const offset)
const
412 basic_iterator tmp{*
this};
418 constexpr friend basic_iterator operator+(difference_type
const offset, basic_iterator iter)
422 iter.from_index(iter.to_index() +
offset);
428 constexpr basic_iterator & operator-=(difference_type
const offset)
432 from_index(to_index() -
offset);
438 constexpr basic_iterator operator-(difference_type
const offset)
const
442 basic_iterator tmp{*
this};
448 template <
typename 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>
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>
481 constexpr bool operator!=(basic_iterator<other_range_type>
const & rhs)
const
484 return !(*
this == rhs);
488 template <
typename 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>
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>
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>
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)
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.
constexpr size_t size
The size of a type pack.
Definition type_pack/traits.hpp:143
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:19
SeqAn specific customisations in the standard namespace.
Additional non-standard concepts for ranges.