take_evenly.hpp
Go to the documentation of this file.
1 // Copyright 2023 Ekumen, Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #ifndef BELUGA_VIEWS_TAKE_EVENLY_HPP
16 #define BELUGA_VIEWS_TAKE_EVENLY_HPP
17 
19 
20 #include <range/v3/view/cache1.hpp>
21 #include <range/v3/view/enumerate.hpp>
22 #include <range/v3/view/filter.hpp>
23 
29 namespace beluga::views {
30 
31 namespace detail {
32 
34 struct take_evenly_fn { // NOLINT(readability-identifier-naming)
36 
45  template <class Range>
46  constexpr auto operator()(Range&& range, std::size_t count) const {
47  const std::size_t size = ranges::size(range);
48 
49  const auto filter_function = [size, count](const auto& pair) {
50  if ((size == 0UL) || (count == 0UL)) {
51  return false;
52  }
53 
54  if (count > size) {
55  return true;
56  }
57 
58  const auto [index, _] = pair;
59  if (count == 1UL) {
60  return index == 0UL;
61  }
62 
63  if ((index == 0UL) || (index == size - 1UL)) {
64  return true;
65  }
66 
67  const std::size_t m0 = (index - 1UL) * (count - 1UL) / (size - 1UL);
68  const std::size_t m1 = index * (count - 1UL) / (size - 1UL);
69  return m0 != m1;
70  };
71 
72  // `cache1` ensures that views prior to `filter` in the pipeline are iterated exactly once.
73  // This is needed because filter needs to dereference the input iterator twice.
74  return ranges::views::enumerate(range) | ranges::views::cache1 | ranges::views::filter(filter_function) |
75  beluga::views::elements<1>;
76  }
77 
79 
86  constexpr auto operator()(std::size_t count) const {
87  return ranges::make_view_closure(ranges::bind_back(take_evenly_fn{}, count));
88  }
89 };
90 
91 } // namespace detail
92 
95 
102 inline constexpr detail::take_evenly_fn take_evenly; // NOLINT(readability-identifier-naming)
103 
104 } // namespace beluga::views
105 
106 #endif
beluga::views
Definition: elements.hpp:27
beluga::views::detail::take_evenly_fn::operator()
constexpr auto operator()(Range &&range, std::size_t count) const
Overload that implements the take_evenly algorithm.
Definition: take_evenly.hpp:46
beluga::views::detail::take_evenly_fn::operator()
constexpr auto operator()(std::size_t count) const
Overload that returns a view closure to compose with other views.
Definition: take_evenly.hpp:86
elements.hpp
Implementation of the C++20's std::views::elements view.
beluga::views::take_evenly
constexpr detail::take_evenly_fn take_evenly
Definition: take_evenly.hpp:102
beluga::views::detail::take_evenly_fn
Implementation detail for a take_evenly range adaptor object.
Definition: take_evenly.hpp:34


beluga
Author(s):
autogenerated on Tue Jul 16 2024 02:59:53