SeqAn3 3.4.0-rc.4
The Modern C++ library for sequence analysis.
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages Concepts
interleave.hpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2006-2025 Knut Reinert & Freie Universität Berlin
2// SPDX-FileCopyrightText: 2016-2025 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
23
24namespace seqan3::detail
25{
26
27// ============================================================================
28// view_interleave
29// ============================================================================
30
42template <std::ranges::random_access_range urng_t, std::ranges::random_access_range inserted_rng_t>
43 requires std::ranges::view<urng_t> && std::ranges::sized_range<urng_t> && std::ranges::view<inserted_rng_t>
44 && std::ranges::sized_range<inserted_rng_t>
45 && std::common_reference_with<std::ranges::range_reference_t<urng_t>,
46 std::ranges::range_reference_t<inserted_rng_t>>
47class view_interleave : public std::ranges::view_interface<view_interleave<urng_t, inserted_rng_t>>
48{
49private:
51 urng_t urange;
53 size_t step_size{};
55 inserted_rng_t inserted_range;
56
62 using size_type = std::ranges::range_size_t<urng_t>;
64 using reference =
65 std::common_reference_t<std::ranges::range_reference_t<urng_t>, std::ranges::range_reference_t<inserted_rng_t>>;
67 using const_reference =
68 detail::transformation_trait_or_t<std::common_reference<std::ranges::range_reference_t<urng_t const>,
69 std::ranges::range_reference_t<inserted_rng_t const>>,
70 void>;
72 using value_type = std::ranges::range_value_t<urng_t>;
74 using difference_type = std::ranges::range_difference_t<urng_t>;
76 using iterator = detail::random_access_iterator<view_interleave>;
78 using const_iterator = detail::random_access_iterator<view_interleave const>;
80
82 template <typename range_type, template <typename...> typename derived_t_template, typename... args_t>
83 friend class detail::random_access_iterator_base;
84
85public:
89 constexpr view_interleave() noexcept = default;
90 constexpr view_interleave(view_interleave const & rhs) noexcept = default;
91 constexpr view_interleave(view_interleave && rhs) noexcept = default;
92 constexpr view_interleave & operator=(view_interleave const & rhs) noexcept = default;
93 constexpr view_interleave & operator=(view_interleave && rhs) noexcept = default;
94 ~view_interleave() noexcept = default;
95
101 explicit constexpr view_interleave(urng_t && _urange, size_t const _step_size, inserted_rng_t && _inserted_range) :
102 urange{_urange},
103 step_size{_step_size},
104 inserted_range{std::forward<inserted_rng_t>(_inserted_range)}
105 {}
106
116 template <typename orng_t, typename oirng_t>
117 requires std::constructible_from<urng_t, decltype(views::type_reduce(std::declval<orng_t>()))>
118 && std::constructible_from<inserted_rng_t, std::views::all_t<oirng_t>>
119 explicit constexpr view_interleave(orng_t && _urange, size_t const _step_size, oirng_t && _inserted_range) :
120 view_interleave{views::type_reduce(std::forward<orng_t>(_urange)),
121 _step_size,
122 std::views::all(std::forward<oirng_t>(_inserted_range))}
123 {}
125
142 iterator begin() noexcept
143 {
144 return {*this, 0};
145 }
146
148 const_iterator begin() const noexcept
149 {
150 return {*this, 0};
151 }
152
166 iterator end() noexcept
167 {
168 return {*this, size()};
169 }
170
172 const_iterator end() const noexcept
173 {
174 return {*this, size()};
175 }
177
186 size_type size()
187 {
188 return std::ranges::size(urange)
189 + ((std::floor(std::ranges::size(urange) / step_size)
190 - (std::ranges::size(urange) % step_size == 0 ? 1 : 0))
191 * std::ranges::size(inserted_range));
192 }
193
195 size_type size() const
196 {
197 return std::ranges::size(urange)
198 + ((std::floor(std::ranges::size(urange) / step_size)
199 - (std::ranges::size(urange) % step_size == 0 ? 1 : 0))
200 * std::ranges::size(inserted_range));
201 }
202
218 reference operator[](size_type const i)
219 {
220 size_t combined_size = step_size + std::ranges::size(inserted_range);
221 assert(i < size());
222 if (i % (combined_size) < step_size)
223 return urange[i - (std::floor(i / (combined_size)) * std::ranges::size(inserted_range))];
224 else
225 return inserted_range[(i % (combined_size)) - step_size];
226 }
227
229 const_reference operator[](size_type const i) const
230 {
231 size_t combined_size = step_size + std::ranges::size(inserted_range);
232 assert(i < size());
233 if (i % (combined_size) < step_size)
234 return urange[i - (std::floor(i / (combined_size)) * std::ranges::size(inserted_range))];
235 else
236 return inserted_range[(i % (combined_size)) - step_size];
237 }
238};
239
242template <std::ranges::random_access_range urng_t, std::ranges::random_access_range inserted_rng_t>
243 requires std::ranges::viewable_range<urng_t> && std::ranges::sized_range<urng_t>
244 && std::ranges::sized_range<inserted_rng_t>
245 && std::common_reference_with<std::ranges::range_reference_t<urng_t>,
246 std::ranges::range_reference_t<inserted_rng_t>>
247view_interleave(urng_t &&, size_t, inserted_rng_t &&)
248 -> view_interleave<decltype(views::type_reduce(std::declval<urng_t>())), std::views::all_t<inserted_rng_t>>;
249
250// ============================================================================
251// interleave_fn (adaptor definition)
252// ============================================================================
253
256struct interleave_fn
257{
259 template <std::ranges::forward_range inserted_rng_t, std::integral size_type>
260 constexpr auto operator()(size_type const size, inserted_rng_t && i) const noexcept
261 {
262 return detail::adaptor_from_functor{*this, size, std::forward<inserted_rng_t>(i)};
263 }
264
271 template <std::ranges::range urng_t, std::ranges::range inserted_rng_t, std::integral size_type>
272 constexpr auto operator()(urng_t && urange, size_type const size, inserted_rng_t && i) const noexcept
273 {
274 static_assert(std::ranges::forward_range<urng_t>,
275 "The underlying range parameter in views::interleave must model std::ranges::forward_range.");
276 static_assert(std::ranges::viewable_range<urng_t>,
277 "The underlying range parameter in views::interleave must model std::ranges::viewable_range.");
278 static_assert(std::ranges::forward_range<inserted_rng_t>,
279 "The range to be inserted by views::interleave must model std::ranges::forward_range.");
280 if constexpr (std::ranges::random_access_range<urng_t> && std::ranges::sized_range<urng_t>
281 && std::ranges::random_access_range<inserted_rng_t> && std::ranges::sized_range<inserted_rng_t>)
282 {
283 return detail::view_interleave{std::forward<urng_t>(urange),
284 static_cast<size_t>(size),
285 std::forward<inserted_rng_t>(i)};
286 }
287 else
288 {
289 return std::forward<urng_t>(urange) | seqan3::views::chunk(static_cast<size_t>(size))
290 | views::join_with(std::forward<inserted_rng_t>(i));
291 }
292 }
293};
294
295} // namespace seqan3::detail
296
297// ============================================================================
298// views::interleave (adaptor instance definition)
299// ============================================================================
300
301namespace seqan3::views
302{
374inline constexpr auto interleave = detail::interleave_fn{};
375
376} // namespace seqan3::views
Provides seqan3::detail::adaptor_from_functor.
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:374
Provides seqan3::views::join_with.
The SeqAn namespace for views.
Definition char_strictly_to.hpp:19
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