Arene Base
Fundamental Utilities For Safety Critical C++
Loading...
Searching...
No Matches
inplace_merge.hpp
Go to the documentation of this file.
1// parasoft-begin-suppress AUTOSAR-A2_8_1-a "False positive: also defines arene::base::inplace_merge"
2
3// Copyright 2026, Toyota Motor Corporation
4//
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
7#ifndef INCLUDE_GUARD_ARENE_BASE_ARENE_BASE_ALGORITHM_INPLACE_MERGE_HPP_
8#define INCLUDE_GUARD_ARENE_BASE_ARENE_BASE_ALGORITHM_INPLACE_MERGE_HPP_
9
10// IWYU pragma: private, include "arene/base/algorithm.hpp"
11// IWYU pragma: friend "(arene/base(?!/tests)|stdlib/include/stdlib_detail)/.*"
12
13#include "arene/base/algorithm/detail/bind_back_with_iterator.hpp"
14#include "arene/base/algorithm/detail/traits.hpp"
15#include "arene/base/algorithm/find_if.hpp"
16#include "arene/base/algorithm/rotate.hpp"
17#include "arene/base/compiler_support/cpp14_inline.hpp"
18#include "arene/base/constraints/constraints.hpp"
19#include "arene/base/functional/not_fn.hpp"
20#include "arene/base/iterator/advance.hpp"
21#include "arene/base/iterator/distance.hpp"
22#include "arene/base/stdlib_choice/declval.hpp"
23#include "arene/base/stdlib_choice/enable_if.hpp"
24#include "arene/base/stdlib_choice/is_copy_constructible.hpp"
25#include "arene/base/stdlib_choice/is_move_assignable.hpp"
26#include "arene/base/stdlib_choice/move.hpp"
27#include "arene/base/type_traits/comparison_traits.hpp"
28#include "arene/base/type_traits/denotes_range.hpp"
29#include "arene/base/type_traits/is_compare.hpp"
30#include "arene/base/type_traits/is_invocable.hpp"
31#include "arene/base/type_traits/is_movable.hpp"
32#include "arene/base/type_traits/is_swappable.hpp"
33#include "arene/base/type_traits/iterator_category_traits.hpp"
34#include "arene/base/type_traits/remove_cvref.hpp"
35
36// IWYU pragma: no_include "arene/base/stdlib_choice/iterator_traits.hpp"
37// IWYU pragma: no_include "arene/base/stdlib_choice/remove_cv.hpp"
38// IWYU pragma: no_include "arene/base/stdlib_choice/remove_reference.hpp"
39
40namespace arene {
41namespace base {
42namespace algorithm_detail {
43namespace inplace_merge_detail {
44
45/// @brief function object implementing the @c inplace_merge algorithm
46///
47class inplace_merge_impl_fn {
48 public:
49 /// @brief merges a range consisting of two ordered sub-ranges in-place so the whole range is sorted
50 /// @tparam BidirectionalIt iterator type
51 /// @tparam Compare compare type
52 /// @param first beginning of the first range
53 /// @param middle end of the first range, beginning of the second range
54 /// @param last end of the second range
55 /// @param comp comparison function object
56 ///
57 /// @pre @c BidirectionalIt must satisfy the bidirectional iterator requirements.
58 /// @pre @c BidiectionalIt must be ValueSwappable.
59 /// @pre the type of <c>*first</c> must be Movable.
60 /// @pre @c Compare must be Compare.
61 /// @pre <c>[first, last)</c> must be a valid range.
62 /// @pre <c> is_sorted(first, middle, comp) </c> is @c true
63 /// @pre <c> is_sorted(middle, last, comp) </c> is @c true
64 /// @pre The expression <c>comp(r1, r2)</c> must be convertible to @c bool
65 /// for every argument @c r1 and @c r2 of type @c RT, where @c RT is the
66 /// reference type of @c I, regardless of value category, and must not modify
67 /// @c r1 or @c r2.
68 /// @pre comp must define a *strict weak ordering relation*. For values
69 /// @c a, @c b, and @c c, the following properties must be satisfied:
70 /// * irreflexivity: <c> comp(a, a) </c> is @c false
71 /// * transitivity: if <c> comp(a, b) </c> and <c> comp(b, c) </c> are both
72 /// @c true, then <c> comp(a, c) </c> is @c true
73 /// * transitivity of incomparability: let <c> e(a, b) </c> be
74 /// <c> !comp(a, b) && !comp(b, a) </c>, then @c e is transitive
75 ///
76 /// Merges two consecutive sorted ranges <c> [first, middle) </c> and <c>
77 /// [middle, last) </c> into one sorted range <c> [first, last) </c>.
78 ///
79 /// This merge function is stable, which means that for equivalent elements in
80 /// the original two ranges, the elements from the first range (preserving
81 /// their original order) precede the elements from the second range
82 /// (preserving their original order).
83 ///
84 /// @post <c> is_sorted(first, last, comp) </c> is @c true
85 ///
86 /// @note Complexity
87 /// Given N as <c> last - first </c>, worst case of <c> O(N * log(N)) </c>
88 /// applications of @c comp.
89 /// @note This implementation never tries to allocate additional memory.
90 template <
91 class BidirectionalIt,
92 class Compare,
93 constraints<
94 std::enable_if_t<is_bidirectional_iterator_v<BidirectionalIt>>,
95 std::enable_if_t<is_swappable_v<iter_reference_t<BidirectionalIt>>>,
96 std::enable_if_t<is_movable_v<remove_cvref_t<iter_reference_t<BidirectionalIt>>>>,
97 std::enable_if_t<is_compare_v<Compare&, iter_reference_t<BidirectionalIt>>>> = nullptr>
98 constexpr auto operator()(BidirectionalIt first, BidirectionalIt middle, BidirectionalIt last, Compare comp) const
99 noexcept( //
100 is_nothrow_equality_comparable_v<BidirectionalIt> && //
101 denotes_nothrow_iterable_range_v<BidirectionalIt> && //
102 std::is_nothrow_copy_constructible<BidirectionalIt>::value&& //
103 noexcept(arene::base::find_if( //
104 std::declval<BidirectionalIt>(), //
105 std::declval<BidirectionalIt&>(), //
106 std::declval<bind_back_with_iterator<Compare, BidirectionalIt>>() //
107 )) && //
108 is_nothrow_invocable_v<decltype(rotate), BidirectionalIt, BidirectionalIt, BidirectionalIt>&& //
109 noexcept(arene::base::advance( //
110 std::declval<BidirectionalIt&>(), //
111 arene::base::distance( //
112 std::declval<BidirectionalIt&>(), //
113 std::declval<BidirectionalIt&>() //
114 ) //
115 )) && //
116 std::is_nothrow_move_assignable<BidirectionalIt>::value //
117 ) -> void {
118 auto left = first;
119 auto right = middle;
120
121 while ((left != middle) && (right != last)) {
122 auto right_end = arene::base::find_if( //
123 right,
124 last,
125 not_fn(bind_back_with_iterator<Compare, BidirectionalIt>{comp, left})
126 );
127 if (right_end == right) {
128 ++left;
129 } else {
130 auto const block_size = arene::base::distance(right, right_end);
131 left = rotate(left, right, right_end);
132 arene::base::advance(middle, block_size);
133 right = std::move(right_end);
134 }
135 }
136 }
137};
138
139} // namespace inplace_merge_detail
140} // namespace algorithm_detail
141
142/// @def arene::base::inplace_merge
143/// @copydoc arene::base::algorithm_detail::inplace_merge_detail::inplace_merge_impl_fn::operator()
144// parasoft-begin-suppress AUTOSAR-M7_3_3-a "An unnamed namespace is used to create a per-TU reference to a global
145// object used in multiple TUs."
146// parasoft-begin-suppress CERT_CPP-DCL59-a "An unnamed namespace is used to create a per-TU reference to a global
147// object used in multiple TUs."
148ARENE_CPP14_INLINE_VARIABLE(algorithm_detail::inplace_merge_detail::inplace_merge_impl_fn, inplace_merge);
149// parasoft-end-suppress AUTOSAR-M7_3_3-a
150// parasoft-end-suppress CERT_CPP-DCL59-a
151
152} // namespace base
153} // namespace arene
154#endif // INCLUDE_GUARD_ARENE_BASE_ARENE_BASE_ALGORITHM_INPLACE_MERGE_HPP_
Definition array_exceptions_disabled.cpp:11
ARENE_CPP14_INLINE_VARIABLE(algorithm_detail::inplace_merge_detail::inplace_merge_impl_fn, inplace_merge)
Copyright 2026, Toyota Motor Corporation.
Definition array_exceptions_disabled.cpp:10