SeqAn3  3.0.0
The Modern C++ library for sequence analysis.
interleave.hpp
Go to the documentation of this file.
1 // -----------------------------------------------------------------------------------------------------
2 // Copyright (c) 2006-2019, Knut Reinert & Freie Universität Berlin
3 // Copyright (c) 2016-2019, 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 
25 #include <seqan3/std/concepts>
26 #include <seqan3/std/ranges>
27 
28 namespace seqan3::detail
29 {
30 
31 // ============================================================================
32 // view_interleave
33 // ============================================================================
34 
46 template <std::ranges::RandomAccessRange urng_t, std::ranges::RandomAccessRange inserted_rng_t>
50  std::CommonReference<reference_t<urng_t>, 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 
62 public:
66  using reference = ranges::common_reference_t<reference_t<urng_t>, reference_t<inserted_rng_t>>;
69  using const_reference = detail::transformation_trait_or_t<
70  ranges::common_reference<reference_t<urng_t const>, reference_t<inserted_rng_t const>>, void>;
72  using value_type = value_type_t<urng_t>;
74  using size_type = size_type_t<urng_t>;
76  using difference_type = difference_type_t<urng_t>;
78  using iterator = detail::random_access_iterator<view_interleave>;
80  using const_iterator = detail::random_access_iterator<view_interleave const>;
82 
86  constexpr view_interleave() noexcept = default;
87  constexpr view_interleave(view_interleave const & rhs) noexcept = default;
88  constexpr view_interleave(view_interleave && rhs) noexcept = default;
89  constexpr view_interleave & operator=(view_interleave const & rhs) noexcept = default;
90  constexpr view_interleave & operator=(view_interleave && rhs) noexcept = default;
91  ~view_interleave() noexcept = default;
92 
98  view_interleave(urng_t && _urange, size_t const _step_size, inserted_rng_t && _inserted_range) :
99  urange{_urange}, step_size{_step_size}, inserted_range{_inserted_range}
100  {}
101 
111  template <typename orng_t, typename oirng_t>
114  std::Constructible<inserted_rng_t, decltype(view::persist(std::declval<oirng_t>()))>
116  view_interleave(orng_t && _urange, size_t const _step_size, oirng_t && _inserted_range) :
117  view_interleave{view::all(std::forward<orng_t>(_urange)), _step_size, view::persist(std::forward<oirng_t>(_inserted_range))}
118  {}
120 
137  iterator begin() noexcept
138  {
139  return {*this, 0};
140  }
141 
143  const_iterator begin() const noexcept
144  {
145  return {*this, 0};
146  }
147 
149  const_iterator cbegin() const noexcept
150  {
151  return begin();
152  }
153 
167  iterator end() noexcept
168  {
169  return {*this, size()};
170  }
171 
173  const_iterator end() const noexcept
174  {
175  return {*this, size()};
176  }
177 
179  const_iterator cend() const noexcept
180  {
181  return end();
182  }
184 
193  size_type size()
194  {
195  return std::ranges::size(urange) +
196  ((std::floor(std::ranges::size(urange) / step_size) -
197  (std::ranges::size(urange) % step_size == 0 ? 1 : 0)) *
198  std::ranges::size(inserted_range));
199  }
200 
202  size_type size() const
203  {
204  return std::ranges::size(urange) +
205  ((std::floor(std::ranges::size(urange) / step_size) -
206  (std::ranges::size(urange) % step_size == 0 ? 1 : 0)) *
207  std::ranges::size(inserted_range));
208  }
209 
225  reference operator[](size_type const i)
226  {
227  size_t combined_size = step_size + std::ranges::size(inserted_range);
228  assert(i < size());
229  if (i % (combined_size) < step_size)
230  return urange[i - (std::floor(i/(combined_size)) * std::ranges::size(inserted_range))];
231  else
232  return inserted_range[(i % (combined_size)) - step_size];
233  }
234 
236  const_reference operator[](size_type const i) const
237  {
238  size_t combined_size = step_size + std::ranges::size(inserted_range);
239  assert(i < size());
240  if (i % (combined_size) < step_size)
241  return urange[i - (std::floor(i/(combined_size)) * std::ranges::size(inserted_range))];
242  else
243  return inserted_range[(i % (combined_size)) - step_size];
244  }
245 };
246 
249 template <std::ranges::RandomAccessRange urng_t, std::ranges::RandomAccessRange inserted_rng_t>
253  std::CommonReference<reference_t<urng_t>, reference_t<inserted_rng_t>>
255 view_interleave(urng_t &&, size_t, inserted_rng_t &&)
256  -> view_interleave<decltype(view::all(std::declval<urng_t>())), decltype(view::persist(std::declval<inserted_rng_t>()))>;
257 
258 // ============================================================================
259 // interleave_fn (adaptor definition)
260 // ============================================================================
261 
264 struct interleave_fn
265 {
267  template <std::ranges::ForwardRange 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::ForwardRange<urng_t>,
283  "The underlying range parameter in view::interleave must model std::ranges::ForwardRange.");
285  "The underlying range parameter in view::interleave must model std::ranges::ViewableRange.");
287  "The range to be inserted by view::interleave must model std::ranges::ForwardRange.");
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 ranges::view::chunk(std::forward<urng_t>(urange), static_cast<size_t>(size))
298  | std::view::join(std::forward<inserted_rng_t>(i));
299  }
300  }
301 };
302 
303 } // namespace seqan3::detail
304 
305 // ============================================================================
306 // view::interleave (adaptor instance definition)
307 // ============================================================================
308 
309 namespace seqan3::view
310 {
311 
387 inline constexpr auto interleave = detail::interleave_fn{};
388 
390 
391 } // namespace seqan3::view
::ranges::cbegin cbegin
Alias for ranges::cbegin. Returns an iterator to the beginning of a range.
Definition: ranges:209
Specifies the requirements of a Range type that is either a std::ranges::View or an lvalue-reference...
Provides various transformation trait base templates and shortcuts.
Provides seqan3::detail::transformation_trait_or.
Specifies requirements of a Range type for which begin returns a type that models std::RandomAccessIt...
constexpr auto all
A view adaptor that behaves like std::view:all, but type erases contiguous ranges.
Definition: view_all.hpp:160
Provides the seqan3::detail::random_access_iterator class.
T floor(T... args)
::ranges::size size
Alias for ranges::size. Obtains the size of a range whose size can be calculated in constant time...
Definition: ranges:189
constexpr auto join
Flattens a View of ranges into a View.
Definition: ranges:683
::ranges::view_interface< urng_t > view_interface
Alias for ranges::view_interface.
Definition: ranges:220
Specifies the requirements of a Range type that knows its size in constant time with the size functio...
The Concepts library.
Auxiliary header for the view submodule .
Adaptations of concepts from the Ranges TS.
::ranges::begin begin
Alias for ranges::begin. Returns an iterator to the beginning of a range.
Definition: ranges:174
Provides seqan3::view::all.
The SeqAn3 namespace for views.
auto constexpr persist
A view adaptor that wraps rvalue references of non-views.
Definition: persist.hpp:251
The concept std::CommonReference<T, U> specifies that two types T and U share a common reference type...
Specifies the requirements of a Range type that has constant time copy, move and assignment operators...
Definition: aligned_sequence_concept.hpp:35
constexpr auto interleave
A view that interleaves a given range into another range at regular intervals.
Definition: interleave.hpp:387
The std::Constructible concept specifies that a variable of type T can be initialized with the given ...
Provides seqan3::view::persist.
Specifies requirements of a Range type for which begin returns a type that models std::ForwardIterato...
::ranges::cend cend
Alias for ranges::cend. Returns an iterator to the end of a range.
Definition: ranges:214
::ranges::end end
Alias for ranges::end. Returns an iterator to the end of a range.
Definition: ranges:179