SeqAn3  3.0.3
The Modern C++ library for sequence analysis.
interleave.hpp
Go to the documentation of this file.
1 // -----------------------------------------------------------------------------------------------------
2 // Copyright (c) 2006-2021, Knut Reinert & Freie Universität Berlin
3 // Copyright (c) 2016-2021, Knut Reinert & MPI für molekulare Genetik
4 // This file may be used, modified and/or redistributed under the terms of the 3-clause BSD-License
5 // shipped with this file and also available at: https://github.com/seqan/seqan3/blob/master/LICENSE.md
6 // -----------------------------------------------------------------------------------------------------
7 
13 #pragma once
14 
15 #include <cmath>
16 #include <seqan3/std/concepts>
17 #include <seqan3/std/ranges>
18 
26 
27 namespace seqan3::detail
28 {
29 
30 // ============================================================================
31 // view_interleave
32 // ============================================================================
33 
45 template <std::ranges::random_access_range urng_t, std::ranges::random_access_range inserted_rng_t>
47  requires std::ranges::view<urng_t> && std::ranges::sized_range<urng_t> &&
48  std::ranges::view<inserted_rng_t> && std::ranges::sized_range<inserted_rng_t> &&
49  std::common_reference_with<std::ranges::range_reference_t<urng_t>,
50  std::ranges::range_reference_t<inserted_rng_t>>
52 class view_interleave : public std::ranges::view_interface<view_interleave<urng_t, inserted_rng_t>>
53 {
54 private:
56  urng_t urange;
58  size_t step_size{};
60  inserted_rng_t inserted_range;
61 
67  using size_type = std::ranges::range_size_t<urng_t>;
69  using reference = ranges::common_reference_t<std::ranges::range_reference_t<urng_t>,
70  std::ranges::range_reference_t<inserted_rng_t>>;
72  using const_reference = detail::transformation_trait_or_t<
73  ranges::common_reference<std::ranges::range_reference_t<urng_t const>,
74  std::ranges::range_reference_t<inserted_rng_t const>>, void>;
76  using value_type = std::ranges::range_value_t<urng_t>;
78  using difference_type = std::ranges::range_difference_t<urng_t>;
80  using iterator = detail::random_access_iterator<view_interleave>;
82  using const_iterator = detail::random_access_iterator<view_interleave const>;
84 
86  template <typename parent_type, typename crtp_base>
87  friend class detail::random_access_iterator_base;
88 
89 public:
93  constexpr view_interleave() noexcept = default;
94  constexpr view_interleave(view_interleave const & rhs) noexcept = default;
95  constexpr view_interleave(view_interleave && rhs) noexcept = default;
96  constexpr view_interleave & operator=(view_interleave const & rhs) noexcept = default;
97  constexpr view_interleave & operator=(view_interleave && rhs) noexcept = default;
98  ~view_interleave() noexcept = default;
99 
105  view_interleave(urng_t && _urange, size_t const _step_size, inserted_rng_t && _inserted_range) :
106  urange{_urange}, step_size{_step_size}, inserted_range{_inserted_range}
107  {}
108 
118  template <typename orng_t, typename oirng_t>
120  requires std::constructible_from<urng_t, decltype(views::type_reduce(std::declval<orng_t>()))> &&
121  std::constructible_from<inserted_rng_t, decltype(detail::persist(std::declval<oirng_t>()))>
123  view_interleave(orng_t && _urange, size_t const _step_size, oirng_t && _inserted_range) :
124  view_interleave{views::type_reduce(std::forward<orng_t>(_urange)), _step_size,
125  detail::persist(std::forward<oirng_t>(_inserted_range))}
126  {}
128 
145  iterator begin() noexcept
146  {
147  return {*this, 0};
148  }
149 
151  const_iterator begin() const noexcept
152  {
153  return {*this, 0};
154  }
155 
169  iterator end() noexcept
170  {
171  return {*this, size()};
172  }
173 
175  const_iterator end() const noexcept
176  {
177  return {*this, size()};
178  }
180 
189  size_type size()
190  {
191  return std::ranges::size(urange) +
192  ((std::floor(std::ranges::size(urange) / step_size) -
193  (std::ranges::size(urange) % step_size == 0 ? 1 : 0)) *
194  std::ranges::size(inserted_range));
195  }
196 
198  size_type size() const
199  {
200  return std::ranges::size(urange) +
201  ((std::floor(std::ranges::size(urange) / step_size) -
202  (std::ranges::size(urange) % step_size == 0 ? 1 : 0)) *
203  std::ranges::size(inserted_range));
204  }
205 
221  reference operator[](size_type const i)
222  {
223  size_t combined_size = step_size + std::ranges::size(inserted_range);
224  assert(i < size());
225  if (i % (combined_size) < step_size)
226  return urange[i - (std::floor(i/(combined_size)) * std::ranges::size(inserted_range))];
227  else
228  return inserted_range[(i % (combined_size)) - step_size];
229  }
230 
232  const_reference operator[](size_type const i) const
233  {
234  size_t combined_size = step_size + std::ranges::size(inserted_range);
235  assert(i < size());
236  if (i % (combined_size) < step_size)
237  return urange[i - (std::floor(i/(combined_size)) * std::ranges::size(inserted_range))];
238  else
239  return inserted_range[(i % (combined_size)) - step_size];
240  }
241 };
242 
245 template <std::ranges::random_access_range urng_t, std::ranges::random_access_range inserted_rng_t>
247  requires std::ranges::viewable_range<urng_t> && std::ranges::sized_range<urng_t> &&
248  std::ranges::sized_range<inserted_rng_t> &&
249  std::common_reference_with<std::ranges::range_reference_t<urng_t>,
250  std::ranges::range_reference_t<inserted_rng_t>>
252 view_interleave(urng_t &&, size_t, inserted_rng_t &&)
253  -> view_interleave<decltype(views::type_reduce(std::declval<urng_t>())),
254  decltype(detail::persist(std::declval<inserted_rng_t>()))>;
255 
256 // ============================================================================
257 // interleave_fn (adaptor definition)
258 // ============================================================================
259 
262 struct interleave_fn
263 {
265  template <std::ranges::forward_range inserted_rng_t, std::integral size_type>
266  constexpr auto operator()(size_type const size, inserted_rng_t && i) const noexcept
267  {
268  return detail::adaptor_from_functor{*this, size, std::forward<inserted_rng_t>(i)};
269  }
270 
277  template <std::ranges::range urng_t, std::ranges::range inserted_rng_t, std::integral size_type>
278  constexpr auto operator()(urng_t && urange, size_type const size, inserted_rng_t && i) const noexcept
279  {
280  static_assert(std::ranges::forward_range<urng_t>,
281  "The underlying range parameter in views::interleave must model std::ranges::forward_range.");
282  static_assert(std::ranges::viewable_range<urng_t>,
283  "The underlying range parameter in views::interleave must model std::ranges::viewable_range.");
284  static_assert(std::ranges::forward_range<inserted_rng_t>,
285  "The range to be inserted by views::interleave must model std::ranges::forward_range.");
286  if constexpr (std::ranges::random_access_range<urng_t> && std::ranges::sized_range<urng_t> &&
287  std::ranges::random_access_range<inserted_rng_t> && std::ranges::sized_range<inserted_rng_t>)
288  {
289  return detail::view_interleave{std::forward<urng_t>(urange),
290  static_cast<size_t>(size),
291  std::forward<inserted_rng_t>(i)};
292  }
293  else
294  {
295  return std::forward<urng_t>(urange) | seqan3::views::chunk(static_cast<size_t>(size))
296  | views::join_with(std::forward<inserted_rng_t>(i));
297  }
298  }
299 };
300 
301 } // namespace seqan3::detail
302 
303 // ============================================================================
304 // views::interleave (adaptor instance definition)
305 // ============================================================================
306 
307 namespace seqan3::views
308 {
309 
384 inline constexpr auto interleave = detail::interleave_fn{};
385 
387 
388 } // namespace seqan3::views
Provides seqan3::detail::adaptor_from_functor.
T begin(T... args)
The Concepts library.
Provides the seqan3::detail::random_access_iterator class.
T end(T... args)
T floor(T... args)
T forward(T... args)
constexpr size_t size
The size of a type pack.
Definition: traits.hpp:151
constexpr auto join_with
A join view, please use std::views::join if you don't need a separator.
Definition: join_with.hpp:37
constexpr auto chunk
A chunk view.
Definition: chunk.hpp:29
constexpr auto type_reduce
A view adaptor that behaves like std::views::all, but type erases certain ranges.
Definition: type_reduce.hpp:158
constexpr auto interleave
A view that interleaves a given range into another range at regular intervals.
Definition: interleave.hpp:384
Provides seqan3::views::join_with.
The SeqAn namespace for views.
Definition: char_to.hpp:22
SeqAn specific customisations in the standard namespace.
Provides seqan3::detail::persist.
Adaptations of concepts from the Ranges TS.
Provides seqan3::detail::transformation_trait_or.
Provides seqan3::views::chunk.
Provides seqan3::views::type_reduce.