Program Listing for File take_evenly.hpp
↰ Return to documentation for file (include/beluga/views/take_evenly.hpp
)
// Copyright 2023 Ekumen, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef BELUGA_VIEWS_TAKE_EVENLY_HPP
#define BELUGA_VIEWS_TAKE_EVENLY_HPP
#include <beluga/views/elements.hpp>
#include <range/v3/view/cache1.hpp>
#include <range/v3/view/enumerate.hpp>
#include <range/v3/view/filter.hpp>
namespace beluga::views {
namespace detail {
struct take_evenly_fn { // NOLINT(readability-identifier-naming)
template <class Range>
constexpr auto operator()(Range&& range, std::size_t count) const {
const std::size_t size = ranges::size(range);
const auto filter_function = [size, count](const auto& pair) {
if ((size == 0UL) || (count == 0UL)) {
return false;
}
if (count > size) {
return true;
}
const auto [index, _] = pair;
if (count == 1UL) {
return index == 0UL;
}
if ((index == 0UL) || (index == size - 1UL)) {
return true;
}
const std::size_t m0 = (index - 1UL) * (count - 1UL) / (size - 1UL);
const std::size_t m1 = index * (count - 1UL) / (size - 1UL);
return m0 != m1;
};
// `cache1` ensures that views prior to `filter` in the pipeline are iterated exactly once.
// This is needed because filter needs to dereference the input iterator twice.
return ranges::views::enumerate(range) | ranges::views::cache1 | ranges::views::filter(filter_function) |
beluga::views::elements<1>;
}
constexpr auto operator()(std::size_t count) const {
return ranges::make_view_closure(ranges::bind_back(take_evenly_fn{}, count));
}
};
} // namespace detail
inline constexpr detail::take_evenly_fn take_evenly; // NOLINT(readability-identifier-naming)
} // namespace beluga::views
#endif