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;
284 detail::iterator_concept_tag_t<underlying_iterator_type>>;
290 basic_iterator() =
default;
291 basic_iterator(basic_iterator
const &) =
default;
292 basic_iterator(basic_iterator &&) =
default;
293 basic_iterator & operator=(basic_iterator
const &) =
default;
294 basic_iterator & operator=(basic_iterator &&) =
default;
295 ~basic_iterator() =
default;
309 constexpr basic_iterator(underlying_iterator_type iter,
310 underlying_iterator_type begin_it,
311 underlying_iterator_type end_it) noexcept :
313 second_it{std::ranges::next(iter, 1, end_it)},
326 template <
typename other_range_type>
327 requires std::convertible_to<other_range_type, range_type &>
329 constexpr basic_iterator(basic_iterator<other_range_type> other) noexcept :
330 basic_iterator{std::move(other.first_it), std::move(other.begin_it), std::move(other.end_it)}
338 constexpr reference operator*() const noexcept(noexcept(*
std::declval<underlying_iterator_type>()))
340 return reference{*first_it, *second_it};
346 constexpr reference operator[](
size_t const index)
const
347 noexcept(
noexcept(std::declval<basic_iterator &>().from_index(1)))
348 requires std::random_access_iterator<underlying_iterator_type>
350 return *(*
this + index);
358 constexpr basic_iterator & operator++()
359 noexcept(noexcept(++
std::declval<underlying_iterator_type &>()))
361 if (++second_it == end_it)
364 second_it = first_it;
371 constexpr basic_iterator operator++(
int )
372 noexcept(
noexcept(std::declval<underlying_iterator_type &>()++))
374 basic_iterator tmp{*
this};
380 constexpr basic_iterator & operator--()
381 noexcept(noexcept(--
std::declval<underlying_iterator_type &>()))
382 requires
std::bidirectional_iterator<underlying_iterator_type>
384 if (--second_it == first_it)
394 constexpr basic_iterator operator--(
int )
395 noexcept(
noexcept(std::declval<underlying_iterator_type &>()--))
396 requires std::bidirectional_iterator<underlying_iterator_type>
398 basic_iterator tmp{*
this};
405 constexpr basic_iterator & operator+=(difference_type
const offset)
406 noexcept(
noexcept(std::declval<basic_iterator &>().from_index(1)))
407 requires std::random_access_iterator<underlying_iterator_type>
409 from_index(to_index() +
offset);
415 constexpr basic_iterator operator+(difference_type
const offset)
const
416 noexcept(
noexcept(std::declval<basic_iterator &>() += 1))
417 requires std::random_access_iterator<underlying_iterator_type>
419 basic_iterator tmp{*
this};
425 constexpr friend basic_iterator operator+(difference_type
const offset, basic_iterator iter)
426 noexcept(
noexcept(std::declval<basic_iterator<range_type> &>().from_index(1)))
427 requires std::random_access_iterator<underlying_iterator_type>
429 iter.from_index(iter.to_index() +
offset);
435 constexpr basic_iterator & operator-=(difference_type
const offset)
436 noexcept(
noexcept(std::declval<basic_iterator &>().from_index(1)))
437 requires std::random_access_iterator<underlying_iterator_type>
439 from_index(to_index() -
offset);
445 constexpr basic_iterator operator-(difference_type
const offset)
const
446 noexcept(
noexcept(std::declval<basic_iterator &>() -= 1))
447 requires std::random_access_iterator<underlying_iterator_type>
449 basic_iterator tmp{*
this};
455 template <
typename other_range_type>
456 requires std::random_access_iterator<underlying_iterator_type>
458 constexpr difference_type operator-(basic_iterator<other_range_type>
const & rhs)
const
459 noexcept(
noexcept(std::declval<basic_iterator &>().to_index()))
461 return static_cast<difference_type
>(to_index() - rhs.to_index());
475 template <
typename other_range_type>
476 requires std::equality_comparable_with<underlying_iterator_type, std::ranges::iterator_t<other_range_type>>
478 constexpr bool operator==(basic_iterator<other_range_type>
const & rhs)
const
479 noexcept(
noexcept(std::declval<underlying_iterator_type &>() == std::declval<underlying_iterator_type &>()))
481 return std::tie(first_it, second_it) ==
std::tie(rhs.first_it, rhs.second_it);
485 template <
typename other_range_type>
486 requires std::equality_comparable_with<underlying_iterator_type, std::ranges::iterator_t<other_range_type>>
488 constexpr bool operator!=(basic_iterator<other_range_type>
const & rhs)
const
489 noexcept(
noexcept(std::declval<underlying_iterator_type &>() != std::declval<underlying_iterator_type &>()))
491 return !(*
this == rhs);
495 template <
typename other_range_type>
496 requires std::totally_ordered_with<underlying_iterator_type, std::ranges::iterator_t<other_range_type>>
498 constexpr bool operator<(basic_iterator<other_range_type>
const & rhs)
const
499 noexcept(
noexcept(std::declval<underlying_iterator_type &>() < std::declval<underlying_iterator_type &>()))
501 return std::tie(first_it, second_it) <
std::tie(rhs.first_it, rhs.second_it);
505 template <
typename other_range_type>
506 requires std::totally_ordered_with<underlying_iterator_type, std::ranges::iterator_t<other_range_type>>
508 constexpr bool operator>(basic_iterator<other_range_type>
const & rhs)
const
509 noexcept(
noexcept(std::declval<underlying_iterator_type &>() > std::declval<underlying_iterator_type &>()))
512 return std::tie(first_it, second_it) >
std::tie(rhs.first_it, rhs.second_it);
516 template <
typename other_range_type>
517 requires std::totally_ordered_with<underlying_iterator_type, std::ranges::iterator_t<other_range_type>>
519 constexpr bool operator<=(basic_iterator<other_range_type>
const & rhs)
const
520 noexcept(
noexcept(std::declval<underlying_iterator_type &>() <= std::declval<underlying_iterator_type &>()))
522 return std::tie(first_it, second_it) <=
std::tie(rhs.first_it, rhs.second_it);
526 template <
typename other_range_type>
527 requires std::totally_ordered_with<underlying_iterator_type, std::ranges::iterator_t<other_range_type>>
529 constexpr bool operator>=(basic_iterator<other_range_type>
const & rhs)
const
530 noexcept(
noexcept(std::declval<underlying_iterator_type &>() >= std::declval<underlying_iterator_type &>()))
532 return std::tie(first_it, second_it) >=
std::tie(rhs.first_it, rhs.second_it);
549 constexpr size_t to_index() const
550 noexcept(noexcept(
std::declval<underlying_iterator_type &>() -
std::declval<underlying_iterator_type &>()))
551 requires
std::random_access_iterator<underlying_iterator_type>
553 size_t src_size = end_it - begin_it;
554 size_t index_i = first_it - begin_it;
555 size_t index_j = second_it - begin_it;
556 return (src_size * (src_size - 1) / 2) - (src_size - index_i) * ((src_size - index_i) - 1) / 2 + index_j
564 constexpr void from_index(
size_t const index)
565 noexcept(
noexcept(std::declval<underlying_iterator_type &>() - std::declval<underlying_iterator_type &>())
566 &&
noexcept(std::declval<underlying_iterator_type &>() + 1))
567 requires std::random_access_iterator<underlying_iterator_type>
569 size_t src_size = end_it - begin_it;
571 src_size - 2 -
std::floor(
std::sqrt(-8 * index + 4 * src_size * (src_size - 1) - 7) / 2.0 - 0.5);
573 index + index_i + 1 - src_size * (src_size - 1) / 2 + (src_size - index_i) * ((src_size - index_i) - 1) / 2;
574 first_it = begin_it + index_i;
575 second_it = begin_it + index_j;
579 underlying_iterator_type first_it{};
581 underlying_iterator_type second_it{};
583 underlying_iterator_type begin_it{};
585 underlying_iterator_type end_it{};
654inline 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.