libhatchet
Loading...
Searching...
No Matches
hxalgorithm.hpp
Go to the documentation of this file.
1#pragma once
2// SPDX-FileCopyrightText: © 2017-2026 Adrian Johnston.
3// SPDX-License-Identifier: MIT
4// This file is licensed under the MIT license found in the LICENSE.md file.
5
14
15#include "libhatchet.h"
16
17// HX_USE_MACROS_WITH_MODULE allows including macros alongside the module.
18#if HX_USE_MACROS_WITH_MODULE
19#error Header does not provide macros alone.
20#endif
21
22#include "hxkey.hpp"
23
24HX_NS_BEGIN_
25
29template<typename iterator_t_, typename callable_t_>
31bool hxall_of(iterator_t_ begin_, iterator_t_ end_, callable_t_&& callable_) {
32 for(; begin_ != end_; ++begin_) {
33 if(!hxforward<callable_t_>(callable_)(*begin_)) {
34 return false;
35 }
36 }
37 return true;
38}
39
43template<typename iterator_t_, typename callable_t_>
45bool hxany_of(iterator_t_ begin_, iterator_t_ end_, callable_t_&& callable_) {
46 for(; begin_ != end_; ++begin_) {
47 if(hxforward<callable_t_>(callable_)(*begin_)) {
48 return true;
49 }
50 }
51 return false;
52}
53
56template<typename iterator_t_, typename callable_t_>
58hxsize_t hxcount_if(iterator_t_ begin_, iterator_t_ end_, callable_t_&& callable_) {
59 hxsize_t count_ = hxsize_t{0};
60 for(; begin_ != end_; ++begin_) {
61 if(hxforward<callable_t_>(callable_)(*begin_)) {
62 ++count_;
63 }
64 }
65 return count_;
66}
67
71template<typename T_, typename U_>
73T_ hxexchange(T_& obj_, U_&& new_value_) noexcept {
74 T_ old_(hxmove(obj_));
75 obj_ = hxforward<U_>(new_value_);
76 return old_;
77}
78
82template<typename iterator_t_, typename callable_t_>
84iterator_t_ hxfind_if(iterator_t_ begin_, iterator_t_ end_, callable_t_&& callable_) {
85 for(; begin_ != end_; ++begin_) {
86 if(hxforward<callable_t_>(callable_)(*begin_)) {
87 return begin_;
88 }
89 }
90 return end_;
91}
92
96template<typename iterator_t_, typename callable_t_>
98callable_t_ hxfor_each(iterator_t_ begin_, iterator_t_ end_, callable_t_&& callable_) {
99 for(; begin_ != end_; ++begin_) {
100 hxforward<callable_t_>(callable_)(*begin_);
101 }
102 return hxforward<callable_t_>(callable_);
103}
104
113template<typename iterator_t_, typename output_iterator_t_, typename less_t_>
115output_iterator_t_ hxmerge(iterator_t_ begin0_, iterator_t_ end0_, iterator_t_ begin1_, iterator_t_ end1_,
116 output_iterator_t_&& output_, const less_t_& less_) noexcept {
117 hxrestrict_t<iterator_t_> src0_(begin0_);
118 hxrestrict_t<iterator_t_> src1_(begin1_);
119 hxrestrict_t<output_iterator_t_> output_r_(output_);
120 while(src0_ != end0_ && src1_ != end1_) {
121 const bool take1_ = less_(*src1_, *src0_);
122 const hxrestrict_t<iterator_t_> sel_ = take1_ ? src1_ : src0_;
123 *output_r_ = hxmove(*sel_);
124 ++output_r_;
125 src1_ = src1_ + static_cast<ptrdiff_t>(take1_);
126 src0_ = src0_ + static_cast<ptrdiff_t>(!take1_);
127 }
128 while(src0_ != end0_) {
129 *output_r_ = hxmove(*src0_);
130 ++output_r_; ++src0_;
131 }
132 while(src1_ != end1_) {
133 *output_r_ = hxmove(*src1_);
134 ++output_r_; ++src1_;
135 }
136 return output_r_;
137}
138
146template<typename iterator_t_, typename output_iterator_t_>
148output_iterator_t_ hxmerge(iterator_t_ begin0_, iterator_t_ end0_, iterator_t_ begin1_,
149 iterator_t_ end1_, output_iterator_t_&& output_) noexcept {
150 return hxmerge<iterator_t_, output_iterator_t_>(begin0_, end0_, begin1_, end1_,
151 hxforward<output_iterator_t_>(output_), hxkey_less_t<decltype(*begin0_)>{});
152}
153
156template<typename iterator_t_>
158public:
159 iterator_t_ min;
160 iterator_t_ max;
161};
162
169template<typename iterator_t_, typename less_t_>
172hxminmax(iterator_t_ begin_, iterator_t_ end_, const less_t_& less_) {
173 hxminmax_result<iterator_t_> result_{begin_, begin_};
174 if(begin_ == end_) { return result_; }
175 for(++begin_; begin_ != end_; ++begin_) {
176 if(less_(*begin_, *result_.min)) {
177 result_.min = begin_;
178 }
179 else if(less_(*result_.max, *begin_)) {
180 result_.max = begin_;
181 }
182 }
183 return result_;
184}
185
188template<typename iterator_t_>
191hxminmax(iterator_t_ begin_, iterator_t_ end_) {
192 return hxminmax<iterator_t_>(begin_, end_, hxkey_less_t<decltype(*begin_)>{});
193}
194
204template<typename iterator_t_, typename output_iterator_t_, typename less_t_>
206output_iterator_t_ hxset_difference(iterator_t_ begin0_, iterator_t_ end0_, iterator_t_ begin1_,
207 iterator_t_ end1_, output_iterator_t_&& output_, const less_t_& less_) noexcept {
208 hxrestrict_t<iterator_t_> src0_(begin0_);
209 hxrestrict_t<iterator_t_> src1_(begin1_);
210 hxrestrict_t<output_iterator_t_> output_r_(output_);
211 while(src0_ != end0_ && src1_ != end1_) {
212 const bool lt_ = less_(*src0_, *src1_);
213 const bool gt_ = less_(*src1_, *src0_);
214 if(lt_) {
215 *output_r_ = hxmove(*src0_);
216 ++output_r_;
217 }
218 src0_ = src0_ + static_cast<ptrdiff_t>(!gt_);
219 src1_ = src1_ + static_cast<ptrdiff_t>(!lt_);
220 }
221 while(src0_ != end0_) {
222 *output_r_ = hxmove(*src0_);
223 ++output_r_; ++src0_;
224 }
225 return output_r_;
226}
227
235template<typename iterator_t_, typename output_iterator_t_>
237output_iterator_t_ hxset_difference(iterator_t_ begin0_, iterator_t_ end0_, iterator_t_ begin1_,
238 iterator_t_ end1_, output_iterator_t_&& output_) noexcept {
239 return hxset_difference<iterator_t_, output_iterator_t_>(begin0_, end0_, begin1_, end1_,
240 hxforward<output_iterator_t_>(output_), hxkey_less_t<decltype(*begin0_)>{});
241}
242
252template<typename iterator_t_, typename output_iterator_t_, typename less_t_>
254output_iterator_t_ hxset_intersection(iterator_t_ begin0_, iterator_t_ end0_, iterator_t_ begin1_,
255 iterator_t_ end1_, output_iterator_t_&& output_, const less_t_& less_) noexcept {
256 hxrestrict_t<iterator_t_> src0_(begin0_);
257 hxrestrict_t<iterator_t_> src1_(begin1_);
258 hxrestrict_t<output_iterator_t_> output_r_(output_);
259 while(src0_ != end0_ && src1_ != end1_) {
260 const bool lt_ = less_(*src0_, *src1_);
261 const bool gt_ = less_(*src1_, *src0_);
262 if(!lt_ && !gt_) {
263 *output_r_ = hxmove(*src0_);
264 ++output_r_;
265 }
266 src0_ = src0_ + static_cast<ptrdiff_t>(!gt_);
267 src1_ = src1_ + static_cast<ptrdiff_t>(!lt_);
268 }
269 return output_r_;
270}
271
279template<typename iterator_t_, typename output_iterator_t_>
281output_iterator_t_ hxset_intersection(iterator_t_ begin0_, iterator_t_ end0_, iterator_t_ begin1_,
282 iterator_t_ end1_, output_iterator_t_&& output_) noexcept {
283 return hxset_intersection<iterator_t_, output_iterator_t_>(begin0_, end0_, begin1_, end1_,
284 hxforward<output_iterator_t_>(output_), hxkey_less_t<decltype(*begin0_)>{});
285}
286
296template<typename iterator_t_, typename output_iterator_t_, typename less_t_>
298output_iterator_t_ hxset_union(iterator_t_ begin0_, iterator_t_ end0_, iterator_t_ begin1_,
299 iterator_t_ end1_, output_iterator_t_&& output_, const less_t_& less_) noexcept {
300 hxrestrict_t<iterator_t_> src0_(begin0_);
301 hxrestrict_t<iterator_t_> src1_(begin1_);
302 hxrestrict_t<output_iterator_t_> output_r_(output_);
303 while(src0_ != end0_ && src1_ != end1_) {
304 const bool take1_ = less_(*src1_, *src0_);
305 const bool less0_ = less_(*src0_, *src1_);
306 const hxrestrict_t<iterator_t_> sel_ = take1_ ? src1_ : src0_;
307 *output_r_ = hxmove(*sel_);
308 ++output_r_;
309 src0_ = src0_ + static_cast<ptrdiff_t>(!take1_);
310 src1_ = src1_ + static_cast<ptrdiff_t>(!less0_);
311 }
312 while(src0_ != end0_) {
313 *output_r_ = hxmove(*src0_);
314 ++output_r_; ++src0_;
315 }
316 while(src1_ != end1_) {
317 *output_r_ = hxmove(*src1_);
318 ++output_r_; ++src1_;
319 }
320 return output_r_;
321}
322
331template<typename iterator_t_, typename output_iterator_t_>
333output_iterator_t_ hxset_union(iterator_t_ begin0_, iterator_t_ end0_, iterator_t_ begin1_,
334 iterator_t_ end1_, output_iterator_t_&& output_) noexcept {
335 return hxset_union<iterator_t_, output_iterator_t_>(begin0_, end0_, begin1_, end1_,
336 hxforward<output_iterator_t_>(output_), hxkey_less_t<decltype(*begin0_)>{});
337}
338
346template<typename iterator_t_, typename equal_t_>
348iterator_t_ hxunique(iterator_t_ begin_, iterator_t_ end_, const equal_t_& equal_) noexcept {
349 if(begin_ == end_) { return end_; }
350 iterator_t_ dst_ = begin_;
351 for(++begin_; begin_ != end_; ++begin_, ++dst_) {
352 if(equal_(*dst_, *begin_)) { break; }
353 }
354 if(begin_ == end_) { return end_; }
355 for(++begin_; begin_ != end_; ++begin_) {
356 if(!equal_(*dst_, *begin_)) {
357 ++dst_;
358 *dst_ = hxmove(*begin_);
359 }
360 }
361 return ++dst_;
362}
363
366template<typename iterator_t_>
368iterator_t_ hxunique(iterator_t_ begin_, iterator_t_ end_) noexcept {
369 return hxunique<iterator_t_>(begin_, end_, hxkey_equal_t<decltype(*begin_)>{});
370}
371
372HX_NS_END_
hxkey_equal_t<T> - A constexpr callable that invokes hxkey_equal.
Definition hxkey.hpp:87
hxkey_less_t<T> - A constexpr callable that invokes hxkey_less.
Definition hxkey.hpp:131
hxminmax_result - Return type of hxminmax holding iterators to the minimum and maximum elements of a ...
Definition hxalgorithm.hpp:157
iterator_t_ max
Definition hxalgorithm.hpp:160
iterator_t_ min
Definition hxalgorithm.hpp:159
constexpr callable_t_ hxfor_each(iterator_t_ begin_, iterator_t_ end_, callable_t_ &&callable_)
hxfor_each - Applies the callable to each element in [begin, end) in order.
Definition hxalgorithm.hpp:98
constexpr iterator_t_ hxfind_if(iterator_t_ begin_, iterator_t_ end_, callable_t_ &&callable_)
hxfind_if - Returns an iterator to the first element in [begin, end) for which the predicate callable...
Definition hxalgorithm.hpp:84
constexpr iterator_t_ hxunique(iterator_t_ begin_, iterator_t_ end_, const equal_t_ &equal_) noexcept
hxunique - Removes consecutive duplicate elements from the range [begin, end) using equal to identify...
Definition hxalgorithm.hpp:348
HX_NS_BEGIN_ constexpr bool hxall_of(iterator_t_ begin_, iterator_t_ end_, callable_t_ &&callable_)
hxall_of - Returns true if the predicate callable returns true for every element in [begin,...
Definition hxalgorithm.hpp:31
constexpr hxminmax_result< iterator_t_ > hxminmax(iterator_t_ begin_, iterator_t_ end_, const less_t_ &less_)
hxminmax - Returns an hxminmax_result with iterators to the smallest and largest elements in [begin,...
Definition hxalgorithm.hpp:172
constexpr output_iterator_t_ hxset_difference(iterator_t_ begin0_, iterator_t_ end0_, iterator_t_ begin1_, iterator_t_ end1_, output_iterator_t_ &&output_, const less_t_ &less_) noexcept
hxset_difference - Forms the difference of two ordered ranges [begin0, end0) and [begin1,...
Definition hxalgorithm.hpp:206
constexpr hxsize_t hxcount_if(iterator_t_ begin_, iterator_t_ end_, callable_t_ &&callable_)
hxcount_if - Returns the number of elements in [begin, end) for which the predicate callable returns ...
Definition hxalgorithm.hpp:58
constexpr output_iterator_t_ hxmerge(iterator_t_ begin0_, iterator_t_ end0_, iterator_t_ begin1_, iterator_t_ end1_, output_iterator_t_ &&output_, const less_t_ &less_) noexcept
hxmerge - Performs a stable merge of two ordered ranges [begin0, end0) and [begin1,...
Definition hxalgorithm.hpp:115
constexpr output_iterator_t_ hxset_intersection(iterator_t_ begin0_, iterator_t_ end0_, iterator_t_ begin1_, iterator_t_ end1_, output_iterator_t_ &&output_, const less_t_ &less_) noexcept
hxset_intersection - Forms the intersection of two ordered ranges [begin0, end0) and [begin1,...
Definition hxalgorithm.hpp:254
constexpr T hxexchange(T &obj_, U_ &&new_value_) noexcept
hxexchange - Replaces obj with new_value and returns the old value of obj.
Definition hxalgorithm.hpp:73
constexpr bool hxany_of(iterator_t_ begin_, iterator_t_ end_, callable_t_ &&callable_)
hxany_of - Returns true if the predicate callable returns true for at least one element in [begin,...
Definition hxalgorithm.hpp:45
constexpr output_iterator_t_ hxset_union(iterator_t_ begin0_, iterator_t_ end0_, iterator_t_ begin1_, iterator_t_ end1_, output_iterator_t_ &&output_, const less_t_ &less_) noexcept
hxset_union - Forms the union of two ordered ranges [begin0, end0) and [begin1, end1) into output.
Definition hxalgorithm.hpp:298
User-overloadable key-equal, key-less, and key-hash functions.
#define hxinline
hxinline - Force a function to be inlined into its callers.
Definition hxsettings.h:120
#define hxattr_nodiscard
hxattr_nodiscard - Indicates the caller should not discard the return value.
Definition hxsettings.h:89
#define hxattr_flatten
hxattr_flatten - Inline every call inside a function's body into it, recursively, regardless of the c...
Definition hxsettings.h:82
#define hxconstexpr
hxconstexpr - Enables C++23 compatable constexpr usage for functions as that has support for destruct...
Definition hxsettings.h:263
typename hxrestrict_t_< T >::type hxrestrict_t
hxrestrict_t - Adds the __restrict keyword to C++ pointers.
Definition hxutility.h:237
constexpr T && hxforward(hxremove_reference_t< T > &&x_)
hxforward - Implements std::forward.
Definition hxutility.h:304
constexpr hxremove_reference_t< T > && hxmove(T &&t_)
hxmove - Implements std::move.
Definition hxutility.h:333
Provides core macros, memory management and feature detection.
ptrdiff_t hxsize_t
hxsize_t - A signed size type, same as ssize_t or ptrdiff_t.
Definition libhatchet.h:209