Arene Base
Fundamental Utilities For Safety Critical C++
Loading...
Searching...
No Matches
rotate.hpp
Go to the documentation of this file.
1// parasoft-begin-suppress AUTOSAR-A2_8_1-a-2 "False positive: also defines arene::base::rotate"
2
3// Copyright 2024, Toyota Motor Corporation
4//
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6#ifndef INCLUDE_GUARD_ARENE_BASE_ARENE_BASE_ALGORITHM_ROTATE_HPP_
7#define INCLUDE_GUARD_ARENE_BASE_ARENE_BASE_ALGORITHM_ROTATE_HPP_
8
9// IWYU pragma: private, include "arene/base/algorithm.hpp"
10// IWYU pragma: friend "(arene/base(?!/tests)|stdlib/include/stdlib_detail)/.*"
11
12// parasoft-begin-suppress AUTOSAR-A16_2_2-a-2 "Arene Base aggregate headers permitted by A16-2-2 Permit #1"
13#include "arene/base/algorithm/detail/traits.hpp"
14#include "arene/base/algorithm/iter_swap.hpp"
15#include "arene/base/algorithm/move.hpp"
16#include "arene/base/algorithm/move_backward.hpp"
17#include "arene/base/algorithm/swap_ranges.hpp"
18#include "arene/base/compiler_support/cpp14_inline.hpp"
19#include "arene/base/constraints/constraints.hpp"
20#include "arene/base/contracts/contract.hpp"
21#include "arene/base/iterator/advance.hpp"
22#include "arene/base/iterator/distance.hpp"
23#include "arene/base/iterator/next.hpp"
24#include "arene/base/iterator/prev.hpp"
25#include "arene/base/math/gcd.hpp"
26#include "arene/base/stdlib_choice/declval.hpp"
27#include "arene/base/stdlib_choice/enable_if.hpp"
28#include "arene/base/stdlib_choice/ignore.hpp"
29#include "arene/base/stdlib_choice/is_copy_assignable.hpp"
30#include "arene/base/stdlib_choice/is_copy_constructible.hpp"
31#include "arene/base/stdlib_choice/is_move_assignable.hpp"
32#include "arene/base/stdlib_choice/is_move_constructible.hpp"
33#include "arene/base/stdlib_choice/move.hpp"
34#include "arene/base/type_traits/comparison_traits.hpp"
35#include "arene/base/type_traits/denotes_range.hpp"
36#include "arene/base/type_traits/is_movable.hpp"
37#include "arene/base/type_traits/is_swappable.hpp"
38#include "arene/base/type_traits/iterator_category_traits.hpp"
39#include "arene/base/type_traits/remove_cvref.hpp"
40// parasoft-end-suppress AUTOSAR-A16_2_2-a-2
41
42// IWYU pragma: no_include "arene/base/stdlib_choice/iterator_traits.hpp"
43// IWYU pragma: no_include "arene/base/stdlib_choice/remove_cv.hpp"
44// IWYU pragma: no_include "arene/base/stdlib_choice/remove_reference.hpp"
45
46namespace arene {
47namespace base {
48namespace algorithm_detail {
49namespace rotate_detail {
50
51/// @brief function object implementing the rotate algorithm
52///
53class rotate_impl_fn {
54 // parasoft-begin-suppress AUTOSAR-M3_3_2-a-2 "False positive: inline function used in multiple translation units"
55 /// @brief Helper function for the Rotate algorithm implementation if iterator
56 /// allows forward access. Should not be called directly.
57 /// @tparam Iterator The type of the Iterator
58 /// @param first The beginning of the original range
59 /// @param last The end of the original range
60 /// @return The Iterator to the new location of the element pointed by first.
61 template <class Iterator, constraints<std::enable_if_t<base::is_forward_iterator_v<Iterator>>> = nullptr>
62 static constexpr auto rotate_left(Iterator first, Iterator last) -> Iterator {
63 auto tmp = std::move(*first); // CODEQLFP(A7-1-2)
64 auto lm1 = ::arene::base::move(::arene::base::next(first), last, first); // CODEQLFP(A7-1-1) CODEQLFP(A7-1-2)
65 *lm1 = std::move(tmp);
66 return lm1;
67 }
68 // parasoft-end-suppress AUTOSAR-M3_3_2-a-2
69
70 /// @brief Helper function for the Rotate algorithm implementation if iterator
71 /// allows bidirectional access. Should not be called directly.
72 /// @tparam Iterator The type of the Iterator
73 /// @param first The beginning of the original range
74 /// @param last The end of the original range
75 /// @return The Iterator to the new location of the element pointed by first.
76 template <class Iterator, constraints<std::enable_if_t<base::is_forward_iterator_v<Iterator>>> = nullptr>
77 static constexpr auto rotate_right(Iterator first, Iterator last) -> Iterator {
78 Iterator lm1{arene::base::prev(last)}; // CODEQLFP(A7-1-2)
79 auto tmp = std::move(*lm1); // CODEQLFP(A7-1-2)
80 auto fp1 = ::arene::base::move_backward(first, lm1, last); // CODEQLFP(A7-1-1) CODEQLFP(A7-1-2)
81 *first = std::move(tmp);
82 return fp1;
83 }
84
85 // parasoft-begin-suppress AUTOSAR-M3_3_2-a-2 "False positive: inline function used in multiple translation units"
86 /// @brief Helper function for the Rotate algorithm implementation if iterator
87 /// allows forward access. Should not be called directly.
88 /// @tparam Iterator The type of the Iterator
89 /// @param first The beginning of the original range
90 /// @param middle The element that should appear at the beginning of the rotated
91 /// range
92 /// @param last The end of the original range
93 /// @return The Iterator to the new location of the element pointed by
94 /// first.
95 template <class Iterator, constraints<std::enable_if_t<base::is_forward_iterator_v<Iterator>>> = nullptr>
96 static constexpr auto rotate_forward(Iterator first, Iterator middle, Iterator last) -> Iterator {
97 Iterator iter{middle};
98 while (true) {
99 ::arene::base::iter_swap(first, iter);
100 arene::base::advance(first, 1);
101 arene::base::advance(iter, 1);
102 if (iter == last) {
103 break;
104 }
105 if (first == middle) {
106 middle = iter;
107 }
108 }
109 Iterator const result{first}; // parasoft-suppress AUTOSAR-A7_1_3-a-2 "False positive: const *is* on the rhs"
110 if (first != middle) {
111 iter = middle;
112 while (true) {
113 ::arene::base::iter_swap(first, iter);
114 arene::base::advance(first, 1);
115 arene::base::advance(iter, 1);
116 if (iter == last) {
117 if (first == middle) {
118 break;
119 }
120 iter = middle;
121 } else if (first == middle) {
122 middle = iter;
123 } else {
124 // nothing to do
125 }
126 }
127 }
128 return result;
129 }
130 // parasoft-end-suppress AUTOSAR-M3_3_2-a-2
131
132 /// @brief Helper function for the Rotate algorithm implementation if iterator
133 /// allows random access. Should not be called directly.
134 /// @tparam Iterator The type of the Iterator
135 /// @param first The beginning of the original range
136 /// @param middle The element that should appear at the beginning of the rotated
137 /// range
138 /// @param last The end of the original range
139 /// @return The Iterator to the new location of the element pointed by first.
140 template <typename Iterator, constraints<std::enable_if_t<base::is_random_access_iterator_v<Iterator>>> = nullptr>
141 static constexpr auto rotate_random_access(Iterator first, Iterator middle, Iterator last)
142 -> Iterator { // CODEQLFP(A7-1-1)
143 auto const distance_to_middle = arene::base::distance(first, middle);
144 auto const distance_from_middle = arene::base::distance(middle, last);
145 if (distance_to_middle == distance_from_middle) {
146 std::ignore = ::arene::base::swap_ranges(first, middle, middle);
147 return middle;
148 }
149 auto const gcd_distance = ::arene::base::gcd(distance_to_middle, distance_from_middle);
150 auto pos = ::arene::base::next(first, gcd_distance);
151 while (pos != first) {
152 arene::base::advance(pos, -1);
153 auto temp(std::move(*pos));
154 Iterator pos1{pos};
155 Iterator pos2{arene::base::next(pos1, distance_to_middle)};
156 // NOLINTNEXTLINE(cppcoreguidelines-avoid-do-while)
157 do {
158 *pos1 = std::move(*pos2);
159 pos1 = pos2;
160 auto const distance_to_end = arene::base::distance(pos2, last);
161 if (distance_to_middle < distance_to_end) {
162 arene::base::advance(pos2, distance_to_middle);
163 } else {
164 pos2 = arene::base::next(first, distance_to_middle - distance_to_end);
165 }
166 } while (pos2 != pos); // CODEQLFP(A5-0-2)
167 *pos1 = std::move(temp);
168 } // CODEQLFP(A5-0-2)
169 return arene::base::next(first, distance_from_middle);
170 }
171
172 // parasoft-begin-suppress AUTOSAR-M3_3_2-a-2 "False positive: inline function used in multiple translation units"
173 /// @brief Overloading function for the particular Rotate algorithm
174 /// implementation if iterator allows forward access. Should not be called
175 /// directly.
176 /// @tparam Iterator The type of the Iterator
177 /// @param first The beginning of the original range
178 /// @param middle The element that should appear at the beginning of the rotated
179 /// range
180 /// @param last The end of the original range
181 /// @return The Iterator to the new location of the element pointed by
182 /// first.
183 template <
184 class Iterator,
185 constraints<
186 std::enable_if_t<base::is_forward_iterator_v<Iterator>>,
187 std::enable_if_t<!base::is_bidirectional_iterator_v<Iterator>>> = nullptr>
188 static constexpr auto impl(Iterator first, Iterator middle, Iterator last) -> Iterator { // CODEQLFP(DCL51-CPP)
189 if (::arene::base::next(first) == middle) {
190 return rotate_left(first, last);
191 }
192 return rotate_forward(first, middle, last);
193 }
194 // parasoft-end-suppress AUTOSAR-M3_3_2-a-2
195
196 /// @brief Overloading function for the particular Rotate algorithm
197 /// implementation if iterator allows bidirectional access. Should not be called
198 /// directly.
199 /// @tparam Iterator The type of the Iterator
200 /// @param first The beginning of the original range
201 /// @param middle The element that should appear at the beginning of the rotated
202 /// range
203 /// @param last The end of the original range
204 /// @return The Iterator to the new location of the element
205 /// pointed by first.
206 template <
207 class Iterator,
208 constraints<
209 std::enable_if_t<base::is_bidirectional_iterator_v<Iterator>>,
210 std::enable_if_t<!base::is_random_access_iterator_v<Iterator>>> = nullptr>
211 static constexpr auto impl(Iterator first, Iterator middle, Iterator last) -> Iterator { // CODEQLFP(DCL51-CPP)
212 if (::arene::base::next(first) == middle) {
213 return rotate_left(first, last);
214 }
215 if (::arene::base::next(middle) == last) {
216 return rotate_right(first, last);
217 }
218 return rotate_forward(first, middle, last);
219 }
220
221 /// @brief Overloading function for the particular Rotate algorithm
222 /// implementation if iterator allows random access. Should not be called
223 /// directly.
224 /// @tparam Iterator The type of the Iterator
225 /// @param first The beginning of the original range
226 /// @param middle The element that should appear at the beginning of the rotated
227 /// range
228 /// @param last The end of the original range
229 /// @return The Iterator to the new location of the element pointed
230 /// by first.
231 template <class Iterator, constraints<std::enable_if_t<base::is_random_access_iterator_v<Iterator>>> = nullptr>
232 static constexpr auto impl(Iterator first, Iterator middle, Iterator last) -> Iterator { // CODEQLFP(DCL51-CPP)
233 ARENE_PRECONDITION((::arene::base::distance(first, middle) >= 0) && (::arene::base::distance(middle, last) >= 0));
234 if (::arene::base::next(first) == middle) {
235 return rotate_left(first, last);
236 }
237 if (::arene::base::next(middle) == last) {
238 return rotate_right(first, last);
239 }
240 return rotate_random_access(first, middle, last);
241 }
242
243 public:
244 /// @brief Performs a left rotation on a range of elements.
245 /// Specifically, @c rotate swaps the elements in the range <c>[first,
246 /// last)</c> in such a way that the element @c middle becomes the first
247 /// element of the new range and <c>middle - 1</c> becomes the last element.
248 /// @tparam Iterator The type of the Iterator for the range to rotate
249 /// @param first The beginning of the original range
250 /// @param middle The element that should appear at the beginning of the rotated
251 /// range
252 /// @param last The end of the original range
253 /// @return The Iterator to the new location of the element pointed by first.
254 /// Equal to <c>first + (last - middle)</c>
255 ///
256 /// @pre <c>[first, middle)</c> is a valid range
257 /// @pre <c>[middle, last)</c> is a valid range
258 /// @pre <c>[first, last)</c> is a valid range
259 ///
260 /// @note Constraints <br>
261 /// * @c Iterator must satisfy forward iterator requirements
262 /// * @c Iterator must be ValueSwappable
263 /// * the type of <c>*first</c> must be move constructible
264 /// * the type of <c>*first</c> must be move assignable
265 ///
266 template <
267 class Iterator,
268 constraints<
269 std::enable_if_t<is_forward_iterator_v<Iterator>>,
270 std::enable_if_t<is_swappable_v<iter_reference_t<Iterator>>>,
271 std::enable_if_t<is_movable_v<remove_cvref_t<iter_reference_t<Iterator>>>>> = nullptr>
272 constexpr auto operator()(Iterator first, Iterator middle, Iterator last) const noexcept( //
273 denotes_nothrow_iterable_range_v<Iterator> && //
274 is_nothrow_equality_comparable_v<Iterator> && //
275 std::is_nothrow_copy_constructible<Iterator>::value && //
276 std::is_nothrow_copy_assignable<Iterator>::value&& //
277 noexcept(arene::base::advance( //
278 std::declval<Iterator&>(), //
279 std::declval<iter_difference_t<Iterator>>() //
280 )) && //
281 std::is_nothrow_move_constructible<remove_cvref_t<iter_reference_t<Iterator>>>::value && //
282 std::is_nothrow_move_assignable<remove_cvref_t<iter_reference_t<Iterator>>>::value && //
283 (is_random_access_iterator_v<Iterator> || //
284 is_nothrow_swappable_v<remove_cvref_t<iter_reference_t<Iterator>>>) //
285 ) -> Iterator {
286 if (first == middle) {
287 return last;
288 }
289 if (middle == last) {
290 return first;
291 }
292 return impl(first, middle, last);
293 }
294};
295
296} // namespace rotate_detail
297} // namespace algorithm_detail
298
299/// @def arene::base::rotate
300/// @copydoc arene::base::algorithm_detail::rotate_detail::rotate_impl_fn::operator()
301// parasoft-begin-suppress AUTOSAR-M7_3_3-a "An unnamed namespace is used to create a per-TU reference to a global
302// object used in multiple TUs."
303// parasoft-begin-suppress CERT_CPP-DCL59-a "An unnamed namespace is used to create a per-TU reference to a global
304// object used in multiple TUs."
305ARENE_CPP14_INLINE_VARIABLE(algorithm_detail::rotate_detail::rotate_impl_fn, rotate);
306// parasoft-end-suppress AUTOSAR-M7_3_3-a
307// parasoft-end-suppress CERT_CPP-DCL59-a
308
309} // namespace base
310} // namespace arene
311
312#endif // INCLUDE_GUARD_ARENE_BASE_ARENE_BASE_ALGORITHM_ROTATE_HPP_
Definition array_exceptions_disabled.cpp:11
ARENE_CPP14_INLINE_VARIABLE(algorithm_detail::rotate_detail::rotate_impl_fn, rotate)
Copyright 2026, Toyota Motor Corporation.
Definition array_exceptions_disabled.cpp:10