SeqAn3  3.0.1
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<reference_t<urng_t>, reference_t<inserted_rng_t>>
53 class view_interleave : public std::ranges::view_interface<view_interleave<urng_t, inserted_rng_t>>
54 {
55 private:
57  urng_t urange;
59  size_t step_size{};
61  inserted_rng_t inserted_range;
62 
63 public:
67  using reference = ranges::common_reference_t<reference_t<urng_t>, reference_t<inserted_rng_t>>;
70  using const_reference = detail::transformation_trait_or_t<
71  ranges::common_reference<reference_t<urng_t const>, reference_t<inserted_rng_t const>>, void>;
73  using value_type = value_type_t<urng_t>;
75  using size_type = size_type_t<urng_t>;
77  using difference_type = difference_type_t<urng_t>;
79  using iterator = detail::random_access_iterator<view_interleave>;
81  using const_iterator = detail::random_access_iterator<view_interleave const>;
83 
87  constexpr view_interleave() noexcept = default;
88  constexpr view_interleave(view_interleave const & rhs) noexcept = default;
89  constexpr view_interleave(view_interleave && rhs) noexcept = default;
90  constexpr view_interleave & operator=(view_interleave const & rhs) noexcept = default;
91  constexpr view_interleave & operator=(view_interleave && rhs) noexcept = default;
92  ~view_interleave() noexcept = default;
93 
99  view_interleave(urng_t && _urange, size_t const _step_size, inserted_rng_t && _inserted_range) :
100  urange{_urange}, step_size{_step_size}, inserted_range{_inserted_range}
101  {}
102 
112  template <typename orng_t, typename oirng_t>
117  view_interleave(orng_t && _urange, size_t const _step_size, oirng_t && _inserted_range) :
118  view_interleave{views::type_reduce(std::forward<orng_t>(_urange)), _step_size, views::persist(std::forward<oirng_t>(_inserted_range))}
119  {}
121 
138  iterator begin() noexcept
139  {
140  return {*this, 0};
141  }
142 
144  const_iterator begin() const noexcept
145  {
146  return {*this, 0};
147  }
148 
150  const_iterator cbegin() const noexcept
151  {
152  return begin();
153  }
154 
168  iterator end() noexcept
169  {
170  return {*this, size()};
171  }
172 
174  const_iterator end() const noexcept
175  {
176  return {*this, size()};
177  }
178 
180  const_iterator cend() const noexcept
181  {
182  return end();
183  }
185 
194  size_type size()
195  {
196  return std::ranges::size(urange) +
197  ((std::floor(std::ranges::size(urange) / step_size) -
198  (std::ranges::size(urange) % step_size == 0 ? 1 : 0)) *
199  std::ranges::size(inserted_range));
200  }
201 
203  size_type size() const
204  {
205  return std::ranges::size(urange) +
206  ((std::floor(std::ranges::size(urange) / step_size) -
207  (std::ranges::size(urange) % step_size == 0 ? 1 : 0)) *
208  std::ranges::size(inserted_range));
209  }
210 
226  reference operator[](size_type const i)
227  {
228  size_t combined_size = step_size + std::ranges::size(inserted_range);
229  assert(i < size());
230  if (i % (combined_size) < step_size)
231  return urange[i - (std::floor(i/(combined_size)) * std::ranges::size(inserted_range))];
232  else
233  return inserted_range[(i % (combined_size)) - step_size];
234  }
235 
237  const_reference operator[](size_type const i) const
238  {
239  size_t combined_size = step_size + std::ranges::size(inserted_range);
240  assert(i < size());
241  if (i % (combined_size) < step_size)
242  return urange[i - (std::floor(i/(combined_size)) * std::ranges::size(inserted_range))];
243  else
244  return inserted_range[(i % (combined_size)) - step_size];
245  }
246 };
247 
250 template <std::ranges::random_access_range urng_t, std::ranges::random_access_range inserted_rng_t>
252  requires std::ranges::viewable_range<urng_t> && std::ranges::sized_range<urng_t> &&
253  std::ranges::sized_range<inserted_rng_t> &&
254  std::common_reference_with<reference_t<urng_t>, reference_t<inserted_rng_t>>
256 view_interleave(urng_t &&, size_t, inserted_rng_t &&)
257  -> view_interleave<decltype(views::type_reduce(std::declval<urng_t>())), decltype(views::persist(std::declval<inserted_rng_t>()))>;
258 
259 // ============================================================================
260 // interleave_fn (adaptor definition)
261 // ============================================================================
262 
265 struct interleave_fn
266 {
268  template <std::ranges::forward_range inserted_rng_t, std::integral size_type>
269  constexpr auto operator()(size_type const size, inserted_rng_t && i) const noexcept
270  {
271  return detail::adaptor_from_functor{*this, size, std::forward<inserted_rng_t>(i)};
272  }
273 
280  template <std::ranges::range urng_t, std::ranges::range inserted_rng_t, std::integral size_type>
281  constexpr auto operator()(urng_t && urange, size_type const size, inserted_rng_t && i) const noexcept
282  {
283  static_assert(std::ranges::forward_range<urng_t>,
284  "The underlying range parameter in views::interleave must model std::ranges::forward_range.");
285  static_assert(std::ranges::viewable_range<urng_t>,
286  "The underlying range parameter in views::interleave must model std::ranges::viewable_range.");
287  static_assert(std::ranges::forward_range<inserted_rng_t>,
288  "The range to be inserted by views::interleave must model std::ranges::forward_range.");
289  if constexpr (std::ranges::random_access_range<urng_t> && std::ranges::sized_range<urng_t> &&
290  std::ranges::random_access_range<inserted_rng_t> && std::ranges::sized_range<inserted_rng_t>)
291  {
292  return detail::view_interleave{std::forward<urng_t>(urange),
293  static_cast<size_t>(size),
294  std::forward<inserted_rng_t>(i)};
295  }
296  else
297  {
298  return std::forward<urng_t>(urange) | ranges::views::chunk(static_cast<size_t>(size))
299  | views::join(std::forward<inserted_rng_t>(i));
300  }
301  }
302 };
303 
304 } // namespace seqan3::detail
305 
306 // ============================================================================
307 // views::interleave (adaptor instance definition)
308 // ============================================================================
309 
310 namespace seqan3::views
311 {
312 
385 inline constexpr auto interleave = detail::interleave_fn{};
386 
388 
389 } // namespace seqan3::views
std::floor
T floor(T... args)
seqan3::views
The SeqAn namespace for views.
Definition: view_to_simd.hpp:672
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:385
constructible_from
The std::constructible_from concept specifies that a variable of type T can be initialized with the g...
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:248
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.
common_reference_with
The concept std::common_reference_with<T, U> specifies that two types T and U share a common referenc...
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 .