41template<
typename ForwardRange,
typename Compare = std::less<>,
typename Proj = std::
identity>
42[[nodiscard]]
bool is_sorted(ForwardRange&&
range, Compare comp = {}, Proj proj = {})
44 return std::is_sorted(std::begin(range), std::end(range),
45 [&](
const auto& x,
const auto& y) {
46 return comp(std::invoke(proj, x), std::invoke(proj, y));
50template<
typename RandomAccessRange>
56template<
typename RandomAccessRange,
typename Compare>
57constexpr void sort(RandomAccessRange&&
range, Compare comp)
59 std::sort(std::begin(
range), std::end(
range), comp);
62template<
typename RAIter,
typename Compare = std::less<>,
typename Proj>
63constexpr void sort(RAIter first, RAIter last, Compare comp, Proj proj)
65 std::sort(first, last,
66 [&](
const auto& x,
const auto& y) {
67 return comp(std::invoke(proj, x), std::invoke(proj, y));
71template<
typename RandomAccessRange,
typename Compare = std::less<>,
typename Proj>
72constexpr void sort(RandomAccessRange&&
range, Compare comp, Proj proj)
77template<
typename RandomAccessRange>
80 std::stable_sort(std::begin(
range), std::end(
range));
83template<
typename RandomAccessRange,
typename Compare>
86 std::stable_sort(std::begin(
range), std::end(
range), comp);
89template<
typename RAIter,
typename Compare = std::less<>,
typename Proj>
90void stable_sort(RAIter first, RAIter last, Compare comp, Proj proj)
92 std::stable_sort(first, last,
93 [&](
const auto& x,
const auto& y) {
94 return comp(std::invoke(proj, x), std::invoke(proj, y));
98template<
typename RandomAccessRange,
typename Compare = std::less<>,
typename Proj>
104template<
typename ForwardRange,
typename T>
107 return std::binary_search(std::begin(
range), std::end(
range), value);
110template<
typename ForwardRange,
typename T,
typename Compare>
113 return std::binary_search(std::begin(
range), std::end(
range), value, comp);
116template<
typename ForwardRange,
typename T,
typename Compare = std::less<>,
typename Proj = std::
identity>
117[[nodiscard]]
auto lower_bound(ForwardRange&&
range,
const T& value, Compare comp = {}, Proj proj = {})
119 auto comp2 = [&](
const auto& x,
const auto& y) {
120 return comp(std::invoke(proj, x), y);
122 return std::lower_bound(std::begin(range), std::end(range), value, comp2);
125template<
typename ForwardRange,
typename T,
typename Compare = std::less<>,
typename Proj = std::
identity>
126[[nodiscard]]
auto upper_bound(ForwardRange&&
range,
const T& value, Compare comp = {}, Proj proj = {})
128 auto comp2 = [&](
const auto& x,
const auto& y) {
129 return comp(x, std::invoke(proj, y));
131 return std::upper_bound(std::begin(range), std::end(range), value, comp2);
134template<
typename ForwardRange,
typename T,
typename Compare = std::less<>>
137 return std::equal_range(std::begin(range), std::end(range), value, comp);
139template<
typename ForwardRange,
typename T,
typename Compare = std::less<>,
typename Proj = std::
identity>
140[[nodiscard]]
auto equal_range(ForwardRange&&
range,
const T& value, Compare comp, Proj proj)
142 using Iter =
decltype(std::begin(
range));
143 using R =
typename std::iterator_traits<Iter>::value_type;
145 [[no_unique_address]] Compare comp;
146 [[no_unique_address]] Proj proj;
148 bool operator()(
const R& x,
const R& y)
const {
149 return comp(std::invoke(proj, x), std::invoke(proj, y));
151 bool operator()(
const R& x,
const T& y)
const {
152 return comp(std::invoke(proj, x), y);
154 bool operator()(
const T& x,
const R& y)
const {
155 return comp(x, std::invoke(proj, y));
158 return std::equal_range(std::begin(
range), std::end(
range), value, Comp2{comp, proj});
161template<
typename InputRange,
typename T>
162[[nodiscard]]
auto find(InputRange&&
range,
const T& value)
164 return std::find(std::begin(
range), std::end(
range), value);
167template<
typename InputRange,
typename T,
typename Proj>
168[[nodiscard]]
auto find(InputRange&&
range,
const T& value, Proj proj)
171 [&](
const auto& e) {
return std::invoke(proj, e) == value; });
174template<
typename InputRange,
typename UnaryPredicate>
177 auto it = std::begin(
range);
178 auto et = std::end(
range);
179 for (; it != et; ++it) {
180 if (std::invoke(pred, *it)) {
187template<
typename InputRange,
typename UnaryPredicate>
188[[nodiscard]]
constexpr bool all_of(InputRange&&
range, UnaryPredicate pred)
191 auto it = std::begin(
range);
192 auto et = std::end(
range);
193 for (; it != et; ++it) {
194 if (!std::invoke(pred, *it))
return false;
199template<
typename InputRange,
typename UnaryPredicate>
200[[nodiscard]]
constexpr bool any_of(InputRange&&
range, UnaryPredicate pred)
203 auto it = std::begin(
range);
204 auto et = std::end(
range);
205 for (; it != et; ++it) {
206 if (std::invoke(pred, *it))
return true;
211template<
typename InputRange,
typename UnaryPredicate>
212[[nodiscard]]
constexpr bool none_of(InputRange&&
range, UnaryPredicate pred)
215 auto it = std::begin(
range);
216 auto et = std::end(
range);
217 for (; it != et; ++it) {
218 if (std::invoke(pred, *it))
return false;
223template<
typename ForwardRange>
226 return std::unique(std::begin(
range), std::end(
range));
229template<
typename ForwardRange,
typename BinaryPredicate>
230[[nodiscard]]
auto unique(ForwardRange&&
range, BinaryPredicate pred)
232 return std::unique(std::begin(
range), std::end(
range), pred);
235template<
typename RAIter,
typename Compare = std::equal_to<>,
typename Proj>
236[[nodiscard]]
auto unique(RAIter first, RAIter last, Compare comp, Proj proj)
238 return std::unique(first, last,
239 [&](
const auto& x,
const auto& y) {
240 return comp(std::invoke(proj, x), std::invoke(proj, y));
244template<
typename RandomAccessRange,
typename Compare = std::equal_to<>,
typename Proj>
245[[nodiscard]]
auto unique(RandomAccessRange&&
range, Compare comp, Proj proj)
250template<
typename InputRange,
typename OutputIter>
251 requires(!range<OutputIter>)
254 return std::copy(std::begin(
range), std::end(
range), out);
257template<sized_range Input, sized_range Output>
258constexpr auto copy(Input&& in, Output&& out)
260 assert(std::size(in) <= std::size(out));
263 auto f = std::begin(in);
264 auto l = std::end(in);
265 auto o = std::begin(out);
272template<
typename InputRange,
typename OutputIter,
typename UnaryPredicate>
275 return std::copy_if(std::begin(
range), std::end(
range), out, pred);
278template<
typename InputRange,
typename OutputIter,
typename UnaryOperation>
281 return std::transform(std::begin(
range), std::end(
range), out, op);
284template<
typename ForwardRange,
typename Generator>
287 std::generate(std::begin(
range), std::end(
range), std::forward<Generator>(
g));
290template<
typename ForwardRange,
typename T>
293 return std::remove(std::begin(
range), std::end(
range), value);
296template<
typename ForwardRange,
typename UnaryPredicate>
299 return std::remove_if(std::begin(
range), std::end(
range), pred);
302template<
typename ForwardRange,
typename T>
303constexpr void replace(ForwardRange&&
range,
const T& old_value,
const T& new_value)
305 std::replace(std::begin(
range), std::end(
range), old_value, new_value);
308template<
typename ForwardRange,
typename UnaryPredicate,
typename T>
311 std::replace_if(std::begin(
range), std::end(
range), pred, new_value);
314template<
typename ForwardRange,
typename T>
315constexpr void fill(ForwardRange&&
range,
const T& value)
317 std::fill(std::begin(
range), std::end(
range), value);
321template<
typename ForwardIt,
typename T>
322constexpr void iota(ForwardIt first, ForwardIt last, T value)
324 while (first != last) {
330template<
typename ForwardRange,
typename T>
336template<
typename InputRange,
typename T>
339 return std::accumulate(std::begin(
range), std::end(
range), init);
342template<
typename InputRange,
typename T,
typename BinaryOperation>
345 return std::accumulate(std::begin(
range), std::end(
range), init, op);
348template<
typename InputRange,
typename T>
351 return std::count(std::begin(
range), std::end(
range), value);
354template<
typename InputRange,
typename UnaryPredicate>
357 auto first = std::begin(
range);
358 auto last = std::end(
range);
359 typename std::iter_difference_t<
decltype(first)>
count = 0;
360 while (first != last) {
361 if (std::invoke(pred, *first++)) ++
count;
367template<
typename InputRange1,
typename InputRange2,
typename OutputIter>
370 return std::set_difference(std::begin(range1), std::end(range1),
371 std::begin(range2), std::end(range2),
375template<range InputRange1, range InputRange2,
376 typename Pred = std::equal_to<void>,
377 typename Proj1 = std::identity,
typename Proj2 = std::identity>
378[[nodiscard]]
constexpr bool equal(InputRange1&& range1, InputRange2&& range2, Pred pred = {},
379 Proj1 proj1 = {}, Proj2 proj2 = {})
381 auto it1 = std::begin(range1);
382 auto it2 = std::begin(range2);
383 auto et1 = std::end(range1);
384 auto et2 = std::end(range2);
385 for (; (it1 != et1) && (it2 != et2); ++it1, ++it2) {
386 if (!std::invoke(pred, std::invoke(proj1, *it1), std::invoke(proj2, *it2))) {
390 return (it1 == et1) && (it2 == et2);
393template<sized_range SizedRange1, sized_range SizedRange2,
394 typename Pred = std::equal_to<void>,
395 typename Proj1 = std::identity,
typename Proj2 = std::identity>
396[[nodiscard]]
constexpr bool equal(SizedRange1&& range1, SizedRange2&& range2, Pred pred = {},
397 Proj1 proj1 = {}, Proj2 proj2 = {})
399 if (std::size(range1) != std::size(range2))
return false;
401 auto it1 = std::begin(range1);
402 auto it2 = std::begin(range2);
403 auto et1 = std::end(range1);
404 for (; it1 != et1; ++it1, ++it2) {
405 if (!std::invoke(pred, std::invoke(proj1, *it1), std::invoke(proj2, *it2))) {
414template<
typename InputRange,
typename Proj = std::
identity>
417 auto it = std::begin(range);
418 auto et = std::end(range);
419 if (it == et)
return true;
421 auto val = std::invoke(proj, *it);
422 for (++it; it != et; ++it) {
423 if (std::invoke(proj, *it) != val) {
447template<
typename ForwardRange,
typename T,
typename Compare = std::less<>,
typename Proj = std::
identity>
448[[nodiscard]]
auto*
binary_find(ForwardRange&& range,
const T& value, Compare comp = {}, Proj proj = {})
451 return ((it != std::end(range)) && (!std::invoke(comp, value, std::invoke(proj, *it))))
461template<
typename Range>
464#ifndef _LIBCPP_VERSION
467 return std::span(range);
476 return std::span(&*std::begin(range), std::size(range));
480template<
typename Range>
481[[nodiscard]]
constexpr auto subspan(Range&& range,
size_t offset,
size_t count = std::dynamic_extent)
483 return make_span(std::forward<Range>(range)).subspan(offset, count);
486template<
size_t Count,
typename Range>
487[[nodiscard]]
constexpr auto subspan(Range&& range,
size_t offset = 0)
489 return make_span(std::forward<Range>(range)).subspan(offset).template first<Count>();
492template<
typename T,
size_t Size>
495 return std::span{std::bit_cast<const uint8_t*>(s.data()), s.size_bytes()};
bool comp(const uint8_t *p, const uint8_t *q)
bool is_sorted(ForwardRange &&range, Compare comp={}, Proj proj={})
constexpr bool all_of(InputRange &&range, UnaryPredicate pred)
bool binary_search(ForwardRange &&range, const T &value)
auto unique(ForwardRange &&range)
constexpr void fill(ForwardRange &&range, const T &value)
auto remove(ForwardRange &&range, const T &value)
constexpr bool none_of(InputRange &&range, UnaryPredicate pred)
void replace_if(ForwardRange &&range, UnaryPredicate pred, const T &new_value)
bool all_equal(InputRange &&range, Proj proj={})
auto find_if(InputRange &&range, UnaryPredicate pred)
auto count(InputRange &&range, const T &value)
auto remove_if(ForwardRange &&range, UnaryPredicate pred)
constexpr void iota(ForwardIt first, ForwardIt last, T value)
T accumulate(InputRange &&range, T init)
void stable_sort(RandomAccessRange &&range)
auto find(InputRange &&range, const T &value)
auto upper_bound(ForwardRange &&range, const T &value, Compare comp={}, Proj proj={})
auto equal_range(ForwardRange &&range, const T &value, Compare comp={})
constexpr bool equal(InputRange1 &&range1, InputRange2 &&range2, Pred pred={}, Proj1 proj1={}, Proj2 proj2={})
auto set_difference(InputRange1 &&range1, InputRange2 &&range2, OutputIter out)
void generate(ForwardRange &&range, Generator &&g)
auto transform(InputRange &&range, OutputIter out, UnaryOperation op)
auto copy_if(InputRange &&range, OutputIter out, UnaryPredicate pred)
constexpr auto copy(InputRange &&range, OutputIter out)
constexpr void replace(ForwardRange &&range, const T &old_value, const T &new_value)
constexpr bool any_of(InputRange &&range, UnaryPredicate pred)
constexpr void sort(RandomAccessRange &&range)
auto lower_bound(ForwardRange &&range, const T &value, Compare comp={}, Proj proj={})
auto count_if(InputRange &&range, UnaryPredicate pred)
auto as_byte_span(std::span< T, Size > s)
constexpr auto make_span(Range &&range)
constexpr auto subspan(Range &&range, size_t offset, size_t count=std::dynamic_extent)
auto * binary_find(ForwardRange &&range, const T &value, Compare comp={}, Proj proj={})