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));
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,
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
172 constexpr const_iterator
begin() const noexcept
191 constexpr iterator
end() noexcept
197 constexpr const_iterator
end() const noexcept
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>
320 requires std::convertible_to<other_range_type, 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
340 noexcept(
noexcept(std::declval<basic_iterator &>().from_index(1)))
341 requires std::random_access_iterator<underlying_iterator_type>
343 return *(*
this + index);
351 constexpr basic_iterator &
352 operator++() noexcept(noexcept(++
std::declval<underlying_iterator_type &>()))
354 if (++second_it == end_it)
357 second_it = first_it;
364 constexpr basic_iterator
365 operator++(
int )
noexcept(
noexcept(std::declval<underlying_iterator_type &>()++))
367 basic_iterator tmp{*
this};
373 constexpr basic_iterator &
374 operator--() 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
388 operator--(
int )
noexcept(
noexcept(std::declval<underlying_iterator_type &>()--))
389 requires std::bidirectional_iterator<underlying_iterator_type>
391 basic_iterator tmp{*
this};
398 constexpr basic_iterator &
399 operator+=(difference_type
const offset)
noexcept(
noexcept(std::declval<basic_iterator &>().from_index(1)))
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
409 noexcept(
noexcept(std::declval<basic_iterator &>() += 1))
410 requires std::random_access_iterator<underlying_iterator_type>
412 basic_iterator tmp{*
this};
418 constexpr friend basic_iterator
419 operator+(difference_type
const offset,
420 basic_iterator iter)
noexcept(
noexcept(std::declval<basic_iterator<range_type> &>().from_index(1)))
421 requires std::random_access_iterator<underlying_iterator_type>
423 iter.from_index(iter.to_index() +
offset);
429 constexpr basic_iterator &
430 operator-=(difference_type
const offset)
noexcept(
noexcept(std::declval<basic_iterator &>().from_index(1)))
431 requires std::random_access_iterator<underlying_iterator_type>
433 from_index(to_index() -
offset);
439 constexpr basic_iterator operator-(difference_type
const offset)
const
440 noexcept(
noexcept(std::declval<basic_iterator &>() -= 1))
441 requires std::random_access_iterator<underlying_iterator_type>
443 basic_iterator tmp{*
this};
449 template <
typename other_range_type>
450 requires std::random_access_iterator<underlying_iterator_type>
452 constexpr difference_type operator-(basic_iterator<other_range_type>
const & rhs)
const
453 noexcept(
noexcept(std::declval<basic_iterator &>().to_index()))
455 return static_cast<difference_type
>(to_index() - rhs.to_index());
469 template <
typename other_range_type>
470 requires std::equality_comparable_with<underlying_iterator_type, std::ranges::iterator_t<other_range_type>>
472 constexpr bool operator==(basic_iterator<other_range_type>
const & rhs)
const
473 noexcept(
noexcept(std::declval<underlying_iterator_type &>() == std::declval<underlying_iterator_type &>()))
475 return std::tie(first_it, second_it) ==
std::tie(rhs.first_it, rhs.second_it);
479 template <
typename other_range_type>
480 requires std::equality_comparable_with<underlying_iterator_type, std::ranges::iterator_t<other_range_type>>
482 constexpr bool operator!=(basic_iterator<other_range_type>
const & rhs)
const
483 noexcept(
noexcept(std::declval<underlying_iterator_type &>() != std::declval<underlying_iterator_type &>()))
485 return !(*
this == rhs);
489 template <
typename other_range_type>
490 requires std::totally_ordered_with<underlying_iterator_type, std::ranges::iterator_t<other_range_type>>
492 constexpr bool operator<(basic_iterator<other_range_type>
const & rhs)
const
493 noexcept(
noexcept(std::declval<underlying_iterator_type &>() < std::declval<underlying_iterator_type &>()))
495 return std::tie(first_it, second_it) <
std::tie(rhs.first_it, rhs.second_it);
499 template <
typename other_range_type>
500 requires std::totally_ordered_with<underlying_iterator_type, std::ranges::iterator_t<other_range_type>>
502 constexpr bool operator>(basic_iterator<other_range_type>
const & rhs)
const
503 noexcept(
noexcept(std::declval<underlying_iterator_type &>() > std::declval<underlying_iterator_type &>()))
506 return std::tie(first_it, second_it) >
std::tie(rhs.first_it, rhs.second_it);
510 template <
typename other_range_type>
511 requires std::totally_ordered_with<underlying_iterator_type, std::ranges::iterator_t<other_range_type>>
513 constexpr bool operator<=(basic_iterator<other_range_type>
const & rhs)
const
514 noexcept(
noexcept(std::declval<underlying_iterator_type &>() <= std::declval<underlying_iterator_type &>()))
516 return std::tie(first_it, second_it) <=
std::tie(rhs.first_it, rhs.second_it);
520 template <
typename other_range_type>
521 requires std::totally_ordered_with<underlying_iterator_type, std::ranges::iterator_t<other_range_type>>
523 constexpr bool operator>=(basic_iterator<other_range_type>
const & rhs)
const
524 noexcept(
noexcept(std::declval<underlying_iterator_type &>() >= std::declval<underlying_iterator_type &>()))
526 return std::tie(first_it, second_it) >=
std::tie(rhs.first_it, rhs.second_it);
543 constexpr size_t to_index() const
544 noexcept(noexcept(
std::declval<underlying_iterator_type &>() -
std::declval<underlying_iterator_type &>()))
545 requires
std::random_access_iterator<underlying_iterator_type>
547 size_t src_size = end_it - begin_it;
548 size_t index_i = first_it - begin_it;
549 size_t index_j = second_it - begin_it;
550 return (src_size * (src_size - 1) / 2) - (src_size - index_i) * ((src_size - index_i) - 1) / 2 + index_j
558 constexpr void from_index(
size_t const index)
noexcept(
noexcept(
559 std::declval<underlying_iterator_type &>()
560 - std::declval<underlying_iterator_type &>()) &&
noexcept(std::declval<underlying_iterator_type &>() + 1))
561 requires std::random_access_iterator<underlying_iterator_type>
563 size_t src_size = end_it - begin_it;
565 src_size - 2 -
std::floor(
std::sqrt(-8 * index + 4 * src_size * (src_size - 1) - 7) / 2.0 - 0.5);
567 index + index_i + 1 - src_size * (src_size - 1) / 2 + (src_size - index_i) * ((src_size - index_i) - 1) / 2;
568 first_it = begin_it + index_i;
569 second_it = begin_it + index_j;
573 underlying_iterator_type first_it{};
575 underlying_iterator_type second_it{};
577 underlying_iterator_type begin_it{};
579 underlying_iterator_type end_it{};
648inline 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.