SeqAn3  3.0.2
The Modern C++ library for sequence analysis.
interleave.hpp
Go to the documentation of this file.
1 // -----------------------------------------------------------------------------------------------------
2 // Copyright (c) 2006-2020, Knut Reinert & Freie Universität Berlin
3 // Copyright (c) 2016-2020, 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 
17 #include <range/v3/view/chunk.hpp>
18 
26 #include <seqan3/std/concepts>
27 #include <seqan3/std/ranges>
28 
29 namespace seqan3::detail
30 {
31 
32 // ============================================================================
33 // view_interleave
34 // ============================================================================
35 
47 template <std::ranges::random_access_range urng_t, std::ranges::random_access_range inserted_rng_t>
49  requires std::ranges::view<urng_t> && std::ranges::sized_range<urng_t> &&
50  std::ranges::view<inserted_rng_t> && std::ranges::sized_range<inserted_rng_t> &&
51  std::common_reference_with<std::ranges::range_reference_t<urng_t>,
52  std::ranges::range_reference_t<inserted_rng_t>>
54 class view_interleave : public std::ranges::view_interface<view_interleave<urng_t, inserted_rng_t>>
55 {
56 private:
58  urng_t urange;
60  size_t step_size{};
62  inserted_rng_t inserted_range;
63 
68  using size_type = std::ranges::range_size_t<urng_t>;
71  using reference = ranges::common_reference_t<std::ranges::range_reference_t<urng_t>,
72  std::ranges::range_reference_t<inserted_rng_t>>;
74  using const_reference = detail::transformation_trait_or_t<
75  ranges::common_reference<std::ranges::range_reference_t<urng_t const>,
76  std::ranges::range_reference_t<inserted_rng_t const>>, void>;
78  using value_type = std::ranges::range_value_t<urng_t>;
80  using difference_type = std::ranges::range_difference_t<urng_t>;
82  using iterator = detail::random_access_iterator<view_interleave>;
84  using const_iterator = detail::random_access_iterator<view_interleave const>;
86 
88  template <typename parent_type, typename crtp_base>
89  friend class detail::random_access_iterator_base;
90 
91 public:
95  constexpr view_interleave() noexcept = default;
96  constexpr view_interleave(view_interleave const & rhs) noexcept = default;
97  constexpr view_interleave(view_interleave && rhs) noexcept = default;
98  constexpr view_interleave & operator=(view_interleave const & rhs) noexcept = default;
99  constexpr view_interleave & operator=(view_interleave && rhs) noexcept = default;
100  ~view_interleave() noexcept = default;
101 
107  view_interleave(urng_t && _urange, size_t const _step_size, inserted_rng_t && _inserted_range) :
108  urange{_urange}, step_size{_step_size}, inserted_range{_inserted_range}
109  {}
110 
120  template <typename orng_t, typename oirng_t>
122  requires std::constructible_from<urng_t, decltype(views::type_reduce(std::declval<orng_t>()))> &&
123  std::constructible_from<inserted_rng_t, decltype(views::persist(std::declval<oirng_t>()))>
125  view_interleave(orng_t && _urange, size_t const _step_size, oirng_t && _inserted_range) :
126  view_interleave{views::type_reduce(std::forward<orng_t>(_urange)), _step_size,
127  views::persist(std::forward<oirng_t>(_inserted_range))}
128  {}
130 
147  iterator begin() noexcept
148  {
149  return {*this, 0};
150  }
151 
153  const_iterator begin() const noexcept
154  {
155  return {*this, 0};
156  }
157 
171  iterator end() noexcept
172  {
173  return {*this, size()};
174  }
175 
177  const_iterator end() const noexcept
178  {
179  return {*this, size()};
180  }
182 
191  size_type size()
192  {
193  return std::ranges::size(urange) +
194  ((std::floor(std::ranges::size(urange) / step_size) -
195  (std::ranges::size(urange) % step_size == 0 ? 1 : 0)) *
196  std::ranges::size(inserted_range));
197  }
198 
200  size_type size() const
201  {
202  return std::ranges::size(urange) +
203  ((std::floor(std::ranges::size(urange) / step_size) -
204  (std::ranges::size(urange) % step_size == 0 ? 1 : 0)) *
205  std::ranges::size(inserted_range));
206  }
207 
223  reference operator[](size_type const i)
224  {
225  size_t combined_size = step_size + std::ranges::size(inserted_range);
226  assert(i < size());
227  if (i % (combined_size) < step_size)
228  return urange[i - (std::floor(i/(combined_size)) * std::ranges::size(inserted_range))];
229  else
230  return inserted_range[(i % (combined_size)) - step_size];
231  }
232 
234  const_reference operator[](size_type const i) const
235  {
236  size_t combined_size = step_size + std::ranges::size(inserted_range);
237  assert(i < size());
238  if (i % (combined_size) < step_size)
239  return urange[i - (std::floor(i/(combined_size)) * std::ranges::size(inserted_range))];
240  else
241  return inserted_range[(i % (combined_size)) - step_size];
242  }
243 };
244 
247 template <std::ranges::random_access_range urng_t, std::ranges::random_access_range inserted_rng_t>
249  requires std::ranges::viewable_range<urng_t> && std::ranges::sized_range<urng_t> &&
250  std::ranges::sized_range<inserted_rng_t> &&
251  std::common_reference_with<std::ranges::range_reference_t<urng_t>,
252  std::ranges::range_reference_t<inserted_rng_t>>
254 view_interleave(urng_t &&, size_t, inserted_rng_t &&)
255  -> view_interleave<decltype(views::type_reduce(std::declval<urng_t>())),
256  decltype(views::persist(std::declval<inserted_rng_t>()))>;
257 
258 // ============================================================================
259 // interleave_fn (adaptor definition)
260 // ============================================================================
261 
264 struct interleave_fn
265 {
267  template <std::ranges::forward_range inserted_rng_t, std::integral size_type>
268  constexpr auto operator()(size_type const size, inserted_rng_t && i) const noexcept
269  {
270  return detail::adaptor_from_functor{*this, size, std::forward<inserted_rng_t>(i)};
271  }
272 
279  template <std::ranges::range urng_t, std::ranges::range inserted_rng_t, std::integral size_type>
280  constexpr auto operator()(urng_t && urange, size_type const size, inserted_rng_t && i) const noexcept
281  {
282  static_assert(std::ranges::forward_range<urng_t>,
283  "The underlying range parameter in views::interleave must model std::ranges::forward_range.");
284  static_assert(std::ranges::viewable_range<urng_t>,
285  "The underlying range parameter in views::interleave must model std::ranges::viewable_range.");
286  static_assert(std::ranges::forward_range<inserted_rng_t>,
287  "The range to be inserted by views::interleave must model std::ranges::forward_range.");
288  if constexpr (std::ranges::random_access_range<urng_t> && std::ranges::sized_range<urng_t> &&
289  std::ranges::random_access_range<inserted_rng_t> && std::ranges::sized_range<inserted_rng_t>)
290  {
291  return detail::view_interleave{std::forward<urng_t>(urange),
292  static_cast<size_t>(size),
293  std::forward<inserted_rng_t>(i)};
294  }
295  else
296  {
297  return std::forward<urng_t>(urange) | ranges::views::chunk(static_cast<size_t>(size))
298  | views::join(std::forward<inserted_rng_t>(i));
299  }
300  }
301 };
302 
303 } // namespace seqan3::detail
304 
305 // ============================================================================
306 // views::interleave (adaptor instance definition)
307 // ============================================================================
308 
309 namespace seqan3::views
310 {
311 
384 inline constexpr auto interleave = detail::interleave_fn{};
385 
387 
388 } // namespace seqan3::views
std::floor
T floor(T... args)
seqan3::views
The SeqAn namespace for views.
Definition: view_iota_simd.hpp:218
pre.hpp
Provides various transformation trait base templates and shortcuts.
seqan3::views::interleave
constexpr auto interleave
A view that interleaves a given range into another range at regular intervals.
Definition: interleave.hpp:384
seqan3::views::type_reduce
constexpr auto type_reduce
A view adaptor that behaves like std::views::all, but type erases certain ranges.
Definition: type_reduce.hpp:158
cmath
concepts
The Concepts library.
seqan3::views::persist
constexpr auto persist
A view adaptor that wraps rvalue references of non-views.
Definition: persist.hpp:233
random_access_iterator.hpp
Provides the seqan3::detail::random_access_iterator class.
type_reduce.hpp
Provides seqan3::views::type_reduce.
transformation_trait_or.hpp
Provides seqan3::detail::transformation_trait_or.
persist.hpp
Provides seqan3::views::persist.
seqan3::pack_traits::size
constexpr size_t size
The size of a type pack.
Definition: traits.hpp:116
join.hpp
Provides seqan3::views::join.
ranges
Adaptations of concepts from the Ranges TS.
std::begin
T begin(T... args)
std::end
T end(T... args)
detail.hpp
Auxiliary header for the views submodule .