Loading...
Searching...
No Matches
interleave.hpp
Go to the documentation of this file.
// SPDX-FileCopyrightText: 2006-2025 Knut Reinert & Freie Universität Berlin
// SPDX-FileCopyrightText: 2016-2025 Knut Reinert & MPI für molekulare Genetik
// SPDX-License-Identifier: BSD-3-Clause
#pragma once
#include <cmath>
#include <concepts>
#include <ranges>
#include <type_traits>
#include <seqan3/core/range/detail/adaptor_from_functor.hpp>
#include <seqan3/core/range/detail/random_access_iterator.hpp>
#include <seqan3/utility/type_traits/detail/transformation_trait_or.hpp>
#include <seqan3/utility/views/chunk.hpp>
#include <seqan3/utility/views/join_with.hpp>
#include <seqan3/utility/views/type_reduce.hpp>
namespace seqan3::detail
{
// ============================================================================
// view_interleave
// ============================================================================
template <std::ranges::random_access_range urng_t, std::ranges::random_access_range inserted_rng_t>
requires std::ranges::view<urng_t> && std::ranges::sized_range<urng_t> && std::ranges::view<inserted_rng_t>
&& std::ranges::sized_range<inserted_rng_t>
&& std::common_reference_with<std::ranges::range_reference_t<urng_t>,
std::ranges::range_reference_t<inserted_rng_t>>
class view_interleave : public std::ranges::view_interface<view_interleave<urng_t, inserted_rng_t>>
{
private:
urng_t urange;
size_t step_size{};
inserted_rng_t inserted_range;
using size_type = std::ranges::range_size_t<urng_t>;
using reference =
std::common_reference_t<std::ranges::range_reference_t<urng_t>, std::ranges::range_reference_t<inserted_rng_t>>;
using const_reference =
detail::transformation_trait_or_t<std::common_reference<std::ranges::range_reference_t<urng_t const>,
std::ranges::range_reference_t<inserted_rng_t const>>,
void>;
using value_type = std::ranges::range_value_t<urng_t>;
using difference_type = std::ranges::range_difference_t<urng_t>;
using iterator = detail::random_access_iterator<view_interleave>;
using const_iterator = detail::random_access_iterator<view_interleave const>;
template <typename range_type, template <typename...> typename derived_t_template, typename... args_t>
friend class detail::random_access_iterator_base;
public:
constexpr view_interleave() noexcept = default;
constexpr view_interleave(view_interleave const & rhs) noexcept = default;
constexpr view_interleave(view_interleave && rhs) noexcept = default;
constexpr view_interleave & operator=(view_interleave const & rhs) noexcept = default;
constexpr view_interleave & operator=(view_interleave && rhs) noexcept = default;
~view_interleave() noexcept = default;
explicit constexpr view_interleave(urng_t && _urange, size_t const _step_size, inserted_rng_t && _inserted_range) :
urange{_urange},
step_size{_step_size},
inserted_range{std::forward<inserted_rng_t>(_inserted_range)}
{}
template <typename orng_t, typename oirng_t>
requires std::constructible_from<urng_t, decltype(views::type_reduce(std::declval<orng_t>()))>
&& std::constructible_from<inserted_rng_t, std::views::all_t<oirng_t>>
explicit constexpr view_interleave(orng_t && _urange, size_t const _step_size, oirng_t && _inserted_range) :
view_interleave{views::type_reduce(std::forward<orng_t>(_urange)),
_step_size,
std::views::all(std::forward<oirng_t>(_inserted_range))}
{}
iterator begin() noexcept
{
return {*this, 0};
}
const_iterator begin() const noexcept
{
return {*this, 0};
}
iterator end() noexcept
{
return {*this, size()};
}
const_iterator end() const noexcept
{
return {*this, size()};
}
size_type size()
{
return std::ranges::size(urange)
+ ((std::floor(std::ranges::size(urange) / step_size)
- (std::ranges::size(urange) % step_size == 0 ? 1 : 0))
* std::ranges::size(inserted_range));
}
size_type size() const
{
return std::ranges::size(urange)
+ ((std::floor(std::ranges::size(urange) / step_size)
- (std::ranges::size(urange) % step_size == 0 ? 1 : 0))
* std::ranges::size(inserted_range));
}
reference operator[](size_type const i)
{
size_t combined_size = step_size + std::ranges::size(inserted_range);
assert(i < size());
if (i % (combined_size) < step_size)
return urange[i - (std::floor(i / (combined_size)) * std::ranges::size(inserted_range))];
else
return inserted_range[(i % (combined_size)) - step_size];
}
const_reference operator[](size_type const i) const
{
size_t combined_size = step_size + std::ranges::size(inserted_range);
assert(i < size());
if (i % (combined_size) < step_size)
return urange[i - (std::floor(i / (combined_size)) * std::ranges::size(inserted_range))];
else
return inserted_range[(i % (combined_size)) - step_size];
}
};
template <std::ranges::random_access_range urng_t, std::ranges::random_access_range inserted_rng_t>
requires std::ranges::viewable_range<urng_t> && std::ranges::sized_range<urng_t>
&& std::ranges::sized_range<inserted_rng_t>
&& std::common_reference_with<std::ranges::range_reference_t<urng_t>,
std::ranges::range_reference_t<inserted_rng_t>>
view_interleave(urng_t &&, size_t, inserted_rng_t &&)
-> view_interleave<decltype(views::type_reduce(std::declval<urng_t>())), std::views::all_t<inserted_rng_t>>;
// ============================================================================
// interleave_fn (adaptor definition)
// ============================================================================
struct interleave_fn
{
template <std::ranges::forward_range inserted_rng_t, std::integral size_type>
constexpr auto operator()(size_type const size, inserted_rng_t && i) const noexcept
{
return detail::adaptor_from_functor{*this, size, std::forward<inserted_rng_t>(i)};
}
template <std::ranges::range urng_t, std::ranges::range inserted_rng_t, std::integral size_type>
constexpr auto operator()(urng_t && urange, size_type const size, inserted_rng_t && i) const noexcept
{
static_assert(std::ranges::forward_range<urng_t>,
"The underlying range parameter in views::interleave must model std::ranges::forward_range.");
static_assert(std::ranges::viewable_range<urng_t>,
"The underlying range parameter in views::interleave must model std::ranges::viewable_range.");
static_assert(std::ranges::forward_range<inserted_rng_t>,
"The range to be inserted by views::interleave must model std::ranges::forward_range.");
if constexpr (std::ranges::random_access_range<urng_t> && std::ranges::sized_range<urng_t>
&& std::ranges::random_access_range<inserted_rng_t> && std::ranges::sized_range<inserted_rng_t>)
{
return detail::view_interleave{std::forward<urng_t>(urange),
static_cast<size_t>(size),
std::forward<inserted_rng_t>(i)};
}
else
{
return std::forward<urng_t>(urange) | seqan3::views::chunk(static_cast<size_t>(size))
| views::join_with(std::forward<inserted_rng_t>(i));
}
}
};
} // namespace seqan3::detail
// ============================================================================
// views::interleave (adaptor instance definition)
// ============================================================================
namespace seqan3::views
{
inline constexpr auto interleave = detail::interleave_fn{};
} // namespace seqan3::views
adaptor_from_functor.hpp
Provides seqan3::detail::adaptor_from_functor.
chunk.hpp
Provides seqan3::views::chunk.
cmath
std::floor
T floor(T... args)
std::forward
T forward(T... args)
seqan3::pack_traits::size
constexpr size_t size
The size of a type pack.
Definition type_pack/traits.hpp:143
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:147
seqan3::views::chunk
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
seqan3::views::interleave
constexpr auto interleave
A view that interleaves a given range into another range at regular intervals.
Definition interleave.hpp:374
seqan3::views::join_with
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
join_with.hpp
Provides seqan3::views::join_with.
seqan3::views
The SeqAn namespace for views.
Definition char_strictly_to.hpp:19
random_access_iterator.hpp
Provides the seqan3::detail::random_access_iterator class.
transformation_trait_or.hpp
Provides seqan3::detail::transformation_trait_or.
type_reduce.hpp
Provides seqan3::views::type_reduce.
type_traits
Hide me