SeqAn3 3.4.0-rc.1
The Modern C++ library for sequence analysis.
Loading...
Searching...
No Matches
interleave.hpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2006-2024 Knut Reinert & Freie Universität Berlin
2// SPDX-FileCopyrightText: 2016-2024 Knut Reinert & MPI für molekulare Genetik
3// SPDX-License-Identifier: BSD-3-Clause
4
10#pragma once
11
12#include <cmath>
13#include <concepts>
14#include <ranges>
15#include <type_traits>
16
24
25namespace seqan3::detail
26{
27
28// ============================================================================
29// view_interleave
30// ============================================================================
31
43template <std::ranges::random_access_range urng_t, std::ranges::random_access_range inserted_rng_t>
44 requires std::ranges::view<urng_t> && std::ranges::sized_range<urng_t> && std::ranges::view<inserted_rng_t>
45 && std::ranges::sized_range<inserted_rng_t>
46 && std::common_reference_with<std::ranges::range_reference_t<urng_t>,
47 std::ranges::range_reference_t<inserted_rng_t>>
48class view_interleave : public std::ranges::view_interface<view_interleave<urng_t, inserted_rng_t>>
49{
50private:
52 urng_t urange;
54 size_t step_size{};
56 inserted_rng_t inserted_range;
57
63 using size_type = std::ranges::range_size_t<urng_t>;
65 using reference =
66 std::common_reference_t<std::ranges::range_reference_t<urng_t>, std::ranges::range_reference_t<inserted_rng_t>>;
68 using const_reference =
69 detail::transformation_trait_or_t<std::common_reference<std::ranges::range_reference_t<urng_t const>,
70 std::ranges::range_reference_t<inserted_rng_t const>>,
71 void>;
73 using value_type = std::ranges::range_value_t<urng_t>;
75 using difference_type = std::ranges::range_difference_t<urng_t>;
77 using iterator = detail::random_access_iterator<view_interleave>;
79 using const_iterator = detail::random_access_iterator<view_interleave const>;
81
83 template <typename range_type, template <typename...> typename derived_t_template, typename... args_t>
84 friend class detail::random_access_iterator_base;
85
86public:
90 constexpr view_interleave() noexcept = default;
91 constexpr view_interleave(view_interleave const & rhs) noexcept = default;
92 constexpr view_interleave(view_interleave && rhs) noexcept = default;
93 constexpr view_interleave & operator=(view_interleave const & rhs) noexcept = default;
94 constexpr view_interleave & operator=(view_interleave && rhs) noexcept = default;
95 ~view_interleave() noexcept = default;
96
102 explicit constexpr view_interleave(urng_t && _urange, size_t const _step_size, inserted_rng_t && _inserted_range) :
103 urange{_urange},
104 step_size{_step_size},
105 inserted_range{std::forward<inserted_rng_t>(_inserted_range)}
106 {}
107
117 template <typename orng_t, typename oirng_t>
118 requires std::constructible_from<urng_t, decltype(views::type_reduce(std::declval<orng_t>()))>
119 && std::constructible_from<inserted_rng_t, seqan3::detail::all_t<oirng_t>>
120 explicit constexpr view_interleave(orng_t && _urange, size_t const _step_size, oirng_t && _inserted_range) :
121 view_interleave{views::type_reduce(std::forward<orng_t>(_urange)),
122 _step_size,
123 seqan3::detail::all(std::forward<oirng_t>(_inserted_range))}
124 {}
126
143 iterator begin() noexcept
144 {
145 return {*this, 0};
146 }
147
149 const_iterator begin() const noexcept
150 {
151 return {*this, 0};
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 }
178
187 size_type size()
188 {
189 return std::ranges::size(urange)
190 + ((std::floor(std::ranges::size(urange) / step_size)
191 - (std::ranges::size(urange) % step_size == 0 ? 1 : 0))
192 * std::ranges::size(inserted_range));
193 }
194
196 size_type size() const
197 {
198 return std::ranges::size(urange)
199 + ((std::floor(std::ranges::size(urange) / step_size)
200 - (std::ranges::size(urange) % step_size == 0 ? 1 : 0))
201 * std::ranges::size(inserted_range));
202 }
203
219 reference operator[](size_type const i)
220 {
221 size_t combined_size = step_size + std::ranges::size(inserted_range);
222 assert(i < size());
223 if (i % (combined_size) < step_size)
224 return urange[i - (std::floor(i / (combined_size)) * std::ranges::size(inserted_range))];
225 else
226 return inserted_range[(i % (combined_size)) - step_size];
227 }
228
230 const_reference operator[](size_type const i) const
231 {
232 size_t combined_size = step_size + std::ranges::size(inserted_range);
233 assert(i < size());
234 if (i % (combined_size) < step_size)
235 return urange[i - (std::floor(i / (combined_size)) * std::ranges::size(inserted_range))];
236 else
237 return inserted_range[(i % (combined_size)) - step_size];
238 }
239};
240
243template <std::ranges::random_access_range urng_t, std::ranges::random_access_range inserted_rng_t>
244 requires std::ranges::viewable_range<urng_t> && std::ranges::sized_range<urng_t>
245 && std::ranges::sized_range<inserted_rng_t>
246 && std::common_reference_with<std::ranges::range_reference_t<urng_t>,
247 std::ranges::range_reference_t<inserted_rng_t>>
248 view_interleave(urng_t &&, size_t, inserted_rng_t &&)
249 -> view_interleave<decltype(views::type_reduce(std::declval<urng_t>())),
250 seqan3::detail::all_t<inserted_rng_t>>;
251
252// ============================================================================
253// interleave_fn (adaptor definition)
254// ============================================================================
255
258struct interleave_fn
259{
261 template <std::ranges::forward_range inserted_rng_t, std::integral size_type>
262 constexpr auto operator()(size_type const size, inserted_rng_t && i) const noexcept
263 {
264 return detail::adaptor_from_functor{*this, size, std::forward<inserted_rng_t>(i)};
265 }
266
273 template <std::ranges::range urng_t, std::ranges::range inserted_rng_t, std::integral size_type>
274 constexpr auto operator()(urng_t && urange, size_type const size, inserted_rng_t && i) const noexcept
275 {
276 static_assert(std::ranges::forward_range<urng_t>,
277 "The underlying range parameter in views::interleave must model std::ranges::forward_range.");
278 static_assert(std::ranges::viewable_range<urng_t>,
279 "The underlying range parameter in views::interleave must model std::ranges::viewable_range.");
280 static_assert(std::ranges::forward_range<inserted_rng_t>,
281 "The range to be inserted by views::interleave must model std::ranges::forward_range.");
282 if constexpr (std::ranges::random_access_range<urng_t> && std::ranges::sized_range<urng_t>
283 && std::ranges::random_access_range<inserted_rng_t> && std::ranges::sized_range<inserted_rng_t>)
284 {
285 return detail::view_interleave{std::forward<urng_t>(urange),
286 static_cast<size_t>(size),
287 std::forward<inserted_rng_t>(i)};
288 }
289 else
290 {
291 return std::forward<urng_t>(urange) | seqan3::views::chunk(static_cast<size_t>(size))
292 | views::join_with(std::forward<inserted_rng_t>(i));
293 }
294 }
295};
296
297} // namespace seqan3::detail
298
299// ============================================================================
300// views::interleave (adaptor instance definition)
301// ============================================================================
302
303namespace seqan3::views
304{
376inline constexpr auto interleave = detail::interleave_fn{};
377
378} // namespace seqan3::views
Provides seqan3::detail::adaptor_from_functor.
Provides seqan3::detail::all.
T begin(T... args)
Provides seqan3::views::chunk.
T end(T... args)
T floor(T... args)
T forward(T... args)
constexpr size_t size
The size of a type pack.
Definition type_pack/traits.hpp:143
seqan::stl::views::join_with join_with
A view adaptor that represents view consisting of the sequence obtained from flattening a view of ran...
Definition join_with.hpp:25
seqan::stl::views::chunk chunk
A view adaptor that divides a range into chunks. <dl class="no-api">This entity is not part of the Se...
Definition chunk.hpp:23
constexpr auto interleave
A view that interleaves a given range into another range at regular intervals.
Definition interleave.hpp:376
Provides seqan3::views::join_with.
The SeqAn namespace for views.
Definition char_strictly_to.hpp:19
The main SeqAn3 namespace.
Definition aligned_sequence_concept.hpp:26
SeqAn specific customisations in the standard namespace.
Provides the seqan3::detail::random_access_iterator class.
Provides seqan3::detail::transformation_trait_or.
Provides seqan3::views::type_reduce.
Hide me