95#ifndef TPL_SORT_UTILS_H
96#define TPL_SORT_UTILS_H
109#include <type_traits>
166 template <
template <
typename>
class Container,
typename T,
174 const T & first = it.get_curr();
175 const T *prev = &first;
177 for (; it.has_curr(); it.next_ne())
179 const T & curr = it.get_curr();
180 if (
cmp(curr, *prev))
209 template <
template <
typename>
class Container,
typename T,
212 const Compare &
cmp = Compare())
215 return std::make_pair(
true, 0);
218 const T & first = it.get_curr();
219 const T *prev = &first;
222 for (; it.has_curr(); it.next_ne(), ++i)
224 const T & curr = it.get_curr();
225 if (
cmp(curr, *prev))
226 return std::make_pair(
false, i);
230 return std::make_pair(
true, i);
252 template <
template <
typename>
class Container,
typename T,
260 const T & first = it.get_curr();
261 const T *prev = &first;
263 for (; it.has_curr(); it.next_ne())
265 const T & curr = it.get_curr();
266 if (
cmp(*prev, curr))
295 template <
template <
typename>
class Container,
typename T,
304 const T & first = it.get_curr();
305 const T *prev = &first;
308 for (; it.has_curr(); it.next_ne(), ++i)
310 const T & curr = it.get_curr();
311 if (
cmp(curr, *prev))
352 template <
typename T,
class Compare = Aleph::less<T>>
360 for (
size_t i = 0,
min, j; i < n - 1; ++i)
362 for (
min = i, j = i + 1; j < n; ++j)
367 std::swap(a[
min], a[i]);
393 template <
class Link,
class Compare>
397 typename Link::Iterator it(
const_cast<Link &
>(list));
400 for (it.next(); it.has_curr(); it.next_ne())
402 Link *curr = it.get_curr();
410 template <
typename T,
class Compare = Aleph::less<T>>
430 template <
class Compare>
437 template <
class Compare>
453 template <
class Compare>
477 template <
typename Tlink,
478 template <
class>
class Tnode,
479 typename T,
class Compare>
493 noexcept(
noexcept(std::declval<const Compare &>()(std::declval<const T &>(), std::declval<const T &>())))
500 return cmp(n1->get_data(), n2->get_data());
505 noexcept(
noexcept(std::declval<const Compare &>()(std::declval<const T &>(), std::declval<const T &>())))
511 return cmp(n->get_data(), x);
518 template <
typename T,
class Compare>
531 template <
typename T,
class Compare>
542 template <
typename T,
class Compare = Aleph::less<T>>
570 template <
typename T,
class Equal = Aleph::equal_to<T>>
575 for (
long i =
l; i <=
r; ++i)
576 if (
eq(a[i], x))
return i;
598 template <
typename T,
class Equal = Aleph::equal_to<T>>
601 const long l,
const long r, Equal
eq = Equal())
603 for (
long i =
l; i <=
r; ++i)
623 template <
class Link,
typename T,
class Equal>
626 for (
typename Link::Iterator it(
const_cast<Link &
>(list));
627 it.has_curr(); it.next_ne())
628 if (
Link *curr = it.get_curr();
eq(curr, x))
640 template <
typename T,
class Equal = Aleph::equal_to<T>>
654 template <
typename T,
class Equal = Aleph::equal_to<T>>
667 template <
typename T,
class Equal = Aleph::equal_to<T>>
678 template <
typename T,
class Equal = Aleph::equal_to<T>>
691 template <
typename T,
class Equal = Aleph::equal_to<T>>
696 const auto & base =
static_cast<const Dlink &
>(list);
703 template <
typename T,
class Equal = Aleph::equal_to<T>>
716 template <
typename T,
class Equal = Aleph::equal_to<T>>
721 return ret !=
nullptr ? &
ret->get_data() :
nullptr;
730 template <
typename T,
class Equal = Aleph::equal_to<T>>
735 return ret !=
nullptr ? &
ret->get_data() :
nullptr;
744 template <
typename T,
class Equal = Aleph::equal_to<T>>
750 T & curr = it.get_curr_ne();
763 template <
typename T,
class Equal = Aleph::equal_to<T>>
769 const T & curr = it.get_curr_ne();
791 template <
typename T,
class Compare = Aleph::less<T>>
796 for (
long i =
l + 1; i <=
r; ++i)
807 template <
typename T,
class Compare = Aleph::less<T>>
818 template <
typename T,
class Compare = Aleph::greater<T>>
828 template <
typename T,
class Compare = Aleph::less<T>>
850 template <
typename T,
class Compare = Aleph::less<T>>
854 const auto & base =
static_cast<const Dnode<T> &
>(list);
857 return ret !=
nullptr ? &(
ret->get_data()) :
nullptr;
861 template <
typename T,
class Compare = Aleph::less<T>>
865 const auto & base =
static_cast<const Dnode<T> &
>(list);
868 return ret !=
nullptr ? &(
ret->get_data()) :
nullptr;
876 template <
typename T,
class Compare = Aleph::less<T>>
901 template <
typename T,
class Compare = Aleph::less<T>>
909 template <
typename T,
class Compare = Aleph::less<T>>
921 template <
typename T,
class Compare = Aleph::greater<T>>
929 template <
typename T,
class Compare = Aleph::greater<T>>
971 template <
typename T,
class Compare = Aleph::less<T>>
974 const Compare &
cmp = Compare())
981 for (
long i =
l + 1, j; i <=
r; ++i)
983 T tmp = std::move(a[i]);
984 for (j = i; j >
l and cmp(
tmp, a[j - 1]); --j)
985 a[j] = std::move(a[j - 1]);
987 a[j] = std::move(
tmp);
1004 template <
class Compare>
1018 template <
class Compare>
1054 <<
"insert_sorted(): reached end of list traversal without inserting";
1064 template <
class ListType,
class Compare>
1068 if (list.is_empty())
1072 aux.append(list.remove_first());
1073 while (
not list.is_empty())
1086 template <
typename T,
class Compare = Aleph::less<T>>
1106 template <
typename T,
class Compare = Aleph::less<T>>
1113 return std::move(
l);
1123 template <
typename T,
class Compare = Aleph::less<T>>
1159 template <
typename T,
class Compare = Aleph::less<T>>
1162 std::vector<T> & buf,
const Compare &
cmp = Compare())
1164 const long s =
r -
l + 1;
1168 if (buf.size() <
static_cast<size_t>(s))
1169 buf.resize(
static_cast<size_t>(s));
1173 for (
long i =
l; i <=
m; ++i)
1174 buf[
buf_idx++] = std::move(a[i]);
1178 for (
long j =
m + 1; j <=
r; ++j)
1179 buf[
buf_idx--] = std::move(a[j]);
1185 for (
long k =
l;
k <=
r; ++
k)
1186 if (
not cmp(buf[j], buf[i]))
1187 a[
k] = std::move(buf[i++]);
1189 a[
k] = std::move(buf[j--]);
1206 template <
typename T,
class Compare = Aleph::less<T>>
1209 const Compare &
cmp = Compare())
1212 buf.reserve(
r -
l + 1);
1223 template <
typename T,
class Compare>
1229 const long m =
l + (
r -
l) / 2;
1274 template <
typename T,
class Compare = Aleph::less<T>>
1282 buf.reserve(
r -
l + 1);
1311 template <
typename Tlist,
class Compare>
1314 const Compare &
cmp = Compare())
1316 assert(result.is_empty());
1325 result.concat_list(
l2);
1327 result.concat_list(
l1);
1341 template <
typename T,
class Compare = Aleph::less<T>>
1344 const Compare &
cmp = Compare())
1379 template <
typename Tlist,
class Compare>
1383 if (list.is_unitarian_or_empty())
1413 template <
template <
typename>
class Tlist,
typename T,
1419 if (list.is_unitarian_or_empty())
1422 if (list.size() <=
lsz)
1445 template <
template <
typename>
class Tlist,
typename T,
1450 if (list.is_unitarian_or_empty())
1469 template <
typename T,
class Compare = Aleph::less<T>>
1483 template <
typename T,
class Compare = Aleph::less<T>>
1497 template <
typename T,
class Compare = Aleph::less<T>>
1515 template <
typename T,
class Compare = Aleph::less<T>>
1520 return std::move(list);
1530 template <
typename T,
class Compare = Aleph::less<T>>
1562 std::swap(a[p], a[
r]);
1571 while (
cmp(a[++i], a[
r])) {}
1573 while (
cmp(a[
r], a[--j]))
1581 std::swap(a[i], a[j]);
1584 std::swap(a[i], a[
r]);
1607 template <
typename T,
class Compare = Aleph::less<T>>
1633 template <
typename T,
class Compare = Aleph::less<T>>
1640 const long left_size =
pivot -
l;
1641 const long right_size =
r -
pivot;
1644 if (left_size < right_size)
1673 template <
typename T,
class Compare = Aleph::less<T>>
1676 const Compare &
cmp = Compare())
1694 template <
typename T,
class Compare>
1697 noexcept(
noexcept(
cmp(a[0], a[0])) && std::is_nothrow_swappable_v<T>)
1699 const long m =
l + (
r -
l) / 2;
1701 if (
cmp(a[
r], a[
l]))
1702 std::swap(a[
l], a[
r]);
1703 if (
cmp(a[
m], a[
l]))
1704 std::swap(a[
m], a[
l]);
1705 if (
cmp(a[
r], a[
m]))
1706 std::swap(a[
r], a[
m]);
1751 template <
typename T,
class Compare = Aleph::less<T>>
1761 const auto n =
static_cast<size_t>(
r -
l + 1);
1763 typedef std::pair<long, long>
Partition;
1767 while (stack.
size() > 0)
1818 template <
typename T,
class Compare>
1820 const Compare &
cmp)
1895 template <
typename T,
class Compare = Aleph::less<T>>
1902 const auto n =
static_cast<size_t>(
r -
l + 1);
1928 template <
typename T,
class Compare = Aleph::less<T>>
1964 template <
typename T,
class Compare = Aleph::less<T>>
1970 const auto n =
static_cast<size_t>(end - begin);
1981 template <
typename T,
class Compare = Aleph::less<T>>
1985 const size_t n = arr.
size();
2005 template <
class Compare>
2049 template <
typename T,
class Compare = Aleph::less<T>>
2059 template <
typename T,
class Compare>
2086 template <
typename T,
class Compare = Aleph::less<T>>
2130 template <
typename T,
class Compare = Aleph::less<T>>
2133 const Compare &
cmp = Compare())
2218 template <
typename T,
class Compare = Aleph::less<T>>
2221 const Compare &
cmp = Compare())
2244 template <
typename T,
class Compare = Aleph::less<T>>
2247 const Compare &
cmp = Compare())
2288 template <
typename T,
class Compare>
2291 const Compare &
cmp = Compare())
2320 list.
swap(&smaller);
2356 template <
typename T,
class Compare = Aleph::less<T>>
2391 template <
typename T,
class Compare = Aleph::less<T>>
2400 template <
typename T,
class Compare>
2402 std::pair<long, long>
2412 while (current <=
gt)
2413 if (
cmp(a[current], a[
r]))
2415 std::swap(a[
lt], a[current]);
2419 else if (
cmp(a[
r], a[current]))
2421 std::swap(a[current], a[
gt]);
2427 std::swap(a[current], a[
r]);
2428 return {
lt, current};
2431 template <
class Container,
typename T,
class Compare>
2433 std::pair<long, long>
2443 while (current <=
gt)
2444 if (
cmp(a(current), a(
r)))
2446 std::swap(a(
lt), a(current));
2450 else if (
cmp(a(
r), a(current)))
2452 std::swap(a(current), a(
gt));
2458 std::swap(a(current), a(
r));
2459 return {
lt, current};
2462 template <
typename T,
class Compare>
2465 const Compare &
cmp)
2477 if (i >=
lt and i <= current)
2497 template <
typename T,
class Compare,
typename Container>
2500 const Compare &
cmp)
2507 const long m =
l + (
r -
l) / 2;
2510 const T &
la = a(
l);
2511 const T &
ra = a(
r);
2512 const T &
ma = a(
m);
2532 template <
typename T,
class Compare = Aleph::less<T>>
2535 const Compare &
cmp = Compare())
2545 template <
typename T,
class Compare = Aleph::less<T>>
2548 const Compare &
cmp = Compare())
2561 template <
typename T,
class Compare,
typename Container>
2564 const Compare &
cmp)
2579 while (
cmp(a(++i), a(
r))) {}
2581 while (
cmp(a(
r), a(--j)))
2588 std::swap(a(i), a(j));
2591 std::swap(a(i), a(
r));
2603 template <
typename T,
class Compare = Aleph::less<T>>
2606 const Compare &
cmp = Compare())
2618 template <
typename T,
class Compare = Aleph::less<T>>
2621 const Compare &
cmp = Compare())
2626 template <
typename Container,
class Compare>
2630 using T =
typename Container::Item_Type;
2631 for (
long p =
l + 1; p <=
r; ++p)
2633 T key = std::move(a(p));
2635 while (j >=
l and cmp(key, a(j)))
2637 a(j + 1) = std::move(a(j));
2640 a(j + 1) = std::move(key);
2644 template <
typename T,
class Compare>
2648 const Compare &
cmp = Compare())
2662 if (i >=
lt and i <= current)
2674 template <
typename T,
class Compare>
2678 const Compare &
cmp = Compare())
2692 if (i >=
lt and i <= current)
2711 template <
typename T,
class Compare = Aleph::less<T>>
2717 const long n =
static_cast<long>(
n_sz) - 1;
2730 template <
typename T,
class Compare = Aleph::less<T>>
2736 const long n =
static_cast<long>(
n_sz) - 1;
2782 template <
typename T,
class Compare = Aleph::less<T>>
2784 const Compare &
cmp = Compare())
2800 template <
typename T,
class Compare = Aleph::less<T>>
2802 Compare &&
cmp = Compare())
2829 template <
class Compare>
2831 const Compare &
cmp = Compare())
2904 template <
typename T,
class Compare = Aleph::less<T>>
2935 template <
typename T,
class Compare = Aleph::less<T>>
2940 auto *p =
static_cast<Dnode<T> *
>(link);
2942 return p !=
nullptr ? &(p->get_data()) :
nullptr;
2964 template <
typename T,
class Compare = Aleph::less<T>>
2968 const long n =
static_cast<long>(a.
size());
2972 for (
long i = 0; i < n - 1; ++i)
2976 for (
long j = i + 1; j < n; ++j)
2981 std::swap(a(
min), a(i));
3015 template <
typename T,
class Compare = Aleph::less<T>>
3019 const long n =
static_cast<long>(a.
size());
3023 for (
long i = 0; i < n - 1; ++i)
3024 for (
long j = n - 1; j > i; --j)
3025 if (
cmp(a(j), a(j - 1)))
3026 std::swap(a(j - 1), a(j));
3055 template <
template <
typename>
class C,
typename T,
3060 for (
long i =
l + 1; i <=
r; i++)
3062 T tmp = std::move(a(i));
3065 a(j) = std::move(a(j - 1));
3067 a(j) = std::move(
tmp);
3075 template <
template <
typename>
class C,
typename T,
3080 const auto n = a.size();
3120 template <
typename T,
class Compare = Aleph::less<T>>
3124 const long n = a.
size();
3132 1, 4, 10, 23, 57, 132, 301, 701, 1750, 4024, 9233,
3133 21223, 48805, 112217, 258100, 593630, 1365513, 3140680
3146 for (
long i =
h; i < n; i++)
3148 T tmp = std::move(a(i));
3153 a(j) = std::move(a(j -
h));
3157 a(j) = std::move(
tmp);
3164 inline static long back_index(
const long i)
noexcept {
return i - 1; }
3172 template <
typename T,
class Compare>
3177 for (
long i = n; i > 1; i = p)
3195 template <
typename T,
class Compare>
3222 template <
typename T,
class Compare>
3241 template <
typename T,
class Compare>
3256 noexcept(
noexcept(std::declval<const Compare &>()(
e2,
e1)))
3302 template <
typename T,
class Compare = Aleph::less<T>>
3306 const long n = a.
size();
3314 for (
long i = n / 2; i >= 1; --i)
3318 for (
long i = n; i >= 2; --i)
3320 std::swap(a(0), a(i - 1));
3333 template <
template <
typename>
class C,
typename T,
3356 std::swap(a(i), a(j));
3359 std::swap(a(i), a(
r));
3370 template <
typename T,
class Compare = Aleph::less<T>>
3373 const Compare &
cmp = Compare())
3401 template <
class Stack,
class A,
class B>
3437 template <
typename T,
class Compare = Aleph::less<T>>
3441 long l = 0,
r = a.
size() - 1;
3443 const size_t n = a.
size();
3478 template <
typename T,
class Compare>
3485 long c = start << 1;
3518 template <
typename T,
class Compare>
3521 const Compare &
cmp)
3523 const long n =
r -
l + 1;
3530 for (
long i = n / 2; i >= 1; --i)
3534 for (
long i = n; i >= 2; --i)
3536 std::swap(a(
l), a(
l + i - 1));
3545 template <
typename T,
class Compare>
3547 const Compare &
cmp)
3606 template <
typename T,
class Compare = Aleph::less<T>>
3610 const long n = a.
size();
3641 template <
typename T,
class Compare = Aleph::less<T>>
3644 const Compare &
cmp = Compare())
3648 for (
long i =
l + 1; i <=
r; i++)
3659 template <
typename T,
class Compare = Aleph::greater<T>>
3662 const Compare &
cmp = Compare())
3712 template <
template <
typename>
class C,
typename T,
3716 const Compare &
cmp = Compare())
3722 if (
long m =
l + (
r -
l) / 2;
cmp(x, a(
m)))
3724 else if (
cmp(a(
m), x))
3749 template <
template <
typename>
class C,
typename T,
3753 const Compare &
cmp = Compare())
3759 if (
long m =
l + (
r -
l) / 2;
cmp(x, *a(
m)))
3761 else if (
cmp(*a(
m), x))
3780 template <
template <
typename>
class C,
typename T,
3785 const auto n = a.size();
3818 template <
template <
typename>
class C,
typename T,
3823 const auto n = a.size();
3843 template <
template <
typename>
class C,
typename T,
3847 const Compare &
cmp = Compare())
3850 const auto n = a.
size();
3862 for (
long i = idx - 1; i >= 0; --i)
3892 template <
template <
typename>
class C,
typename T,
3897 const size_t & n = a.
size();
3900 for (
size_t i = 0; i < n; ++i)
3925 template <
template <
typename>
class C,
typename T,
3939 for (
long i = idx - 1; i >= 0; --i)
3941 const T *ptr = &a(i);
3949 for (
long i = idx + 1, n = a.size(); i < n; ++i)
3951 const T *ptr = &a(i);
3971 template <
template <
typename>
class C,
typename T,
3984 template <
template <
typename>
class C,
typename T,
3992 const T *ptr = &a(i);
4007 template <
template <
typename>
class C,
typename T,
4030 template <
template <
typename>
class C,
typename T,
4044 for (
long i = idx - 1; i >= 0; --i)
4054 for (
long i = idx + 1, n = a.size(); i < n; ++i)
4076 template <
template <
typename>
class C,
typename T,
4082 const auto n = a.
size();
4094 for (
long i = idx - 1; i >= 0; --i)
4104 for (
long i = idx + 1, n = a.size(); i < n; ++i)
4148 template <
template <
typename>
class C,
typename T,
4185 template <
template <
typename>
class C,
typename T,
4198 const long mid = idx;
4200 for (
long i = idx - 1; i >= 0; --i)
4209 for (
long i = idx + 1, n = a.size(); i < n; ++i)
4230 template <
template <
typename>
class C,
typename T,
4244 for (
long i = idx - 1; i >= 0; --i)
4254 for (
long i = idx + 1, n = a.size(); i < n; ++i)
4300 template <
template <
typename>
class C,
typename T,
4305 const size_t & n = a.
size();
4308 for (
size_t i = 0; i < n; ++i)
4312 [&a, &
cmp](
size_t i,
size_t j) {
return cmp(a(i), a(j)); });
4342 template <
template <
typename>
class C,
typename T,
4347 const size_t & n = a.
size();
4350 for (
size_t i = 0; i < n; ++i)
4388 template <
template <
typename>
class C,
typename T,
4394 const size_t n = a.size();
4398 size_t l = 0,
r = n - 1;
4409 const size_t partition_size =
r -
l + 1;
4410 if (partition_size <= 1)
4413 if (partition_size <= threshold)
4421 static_cast<long>(
l),
4422 static_cast<long>(
r),
4425 const size_t left_size = i >
l ? i -
l : 0;
4426 const size_t right_size =
r > i ?
r - i : 0;
4428 if (left_size > right_size)
4453 template <
typename T,
class Compare = Aleph::less<T>>
4456 const Compare &
cmp = Compare())
4461 const long m =
l + (
r -
l) / 2;
4479 template <
typename T,
class Compare = Aleph::less<T>>
4482 const Compare &
cmp = Compare())
4486 long m =
l + (
r -
l) / 2;
4489 else if (
cmp(a[
m], x))
4524 template <
typename KeyFn>
4525 requires std::invocable<const KeyFn &, size_t>
and
4526 std::convertible_to<std::invoke_result_t<const KeyFn &, size_t>,
int>
4535 <<
"counting_sort_indices(): max_key < min_key";
4541 <<
"counting_sort_indices(): sa/tmp size is smaller than n";
4544 static_cast<unsigned long long>(
static_cast<long long>(max_key) -
4545 static_cast<long long>(min_key));
4547 static_cast<unsigned long long>(std::numeric_limits<size_t>::max() - size_t(1));
4549 <<
"counting_sort_indices(): key range is too large";
4553 for (
size_t i = 0; i <
k; ++i)
4556 for (
size_t i = 0; i < n; ++i)
4558 const int key =
key_of(sa[i]);
4560 <<
"counting_sort_indices(): key out of expected range";
4562 static_cast<size_t>(
static_cast<unsigned long long>(
4563 static_cast<long long>(key) -
static_cast<long long>(min_key)));
4567 for (
size_t j = 1; j <
k; ++j)
4570 for (
size_t i = n; i > 0; --i)
4572 const int key =
key_of(sa[i - 1]);
4574 static_cast<size_t>(
static_cast<unsigned long long>(
4575 static_cast<long long>(key) -
static_cast<long long>(min_key)));
4579 for (
size_t i = 0; i < n; ++i)
4584 namespace sort_utils_detail
4590 template <
typename T>
4598 template <
typename T>
4602 template <
typename IntT>
4606 template <
typename IntT>
4619 template <
typename IntT>
4627 static_cast<U>(max_key) -
static_cast<U>(min_key);
4629 if constexpr (
sizeof(
U) >=
sizeof(
size_t))
4632 std::numeric_limits<size_t>::max() -
static_cast<size_t>(1);
4634 <<
"counting_sort(): key range is too large";
4648 template <
typename IntT>
4652 return static_cast<size_t>(
4665 template <
typename IntT>
4670 return static_cast<IntT>(
static_cast<U>(min_key) +
static_cast<U>(bucket));
4680 template <
template <
typename>
class C,
typename IntT>
4684 const size_t n = a.size();
4688 IntT min_key = a(0), max_key = a(0);
4689 for (
size_t i = 1; i < n; ++i)
4699 for (
size_t i = 0; i <
k; ++i)
4702 for (
size_t i = 0; i < n; ++i)
4705 for (
size_t i = 1; i <
k; ++i)
4709 for (
size_t i = n; i > 0; --i)
4715 for (
size_t i = 0; i < n; ++i)
4720 template <
typename IntT>
4727 IntT min_key = a[0], max_key = a[0];
4728 for (
size_t i = 1; i < n; ++i)
4738 for (
size_t i = 0; i <
k; ++i)
4741 for (
size_t i = 0; i < n; ++i)
4744 for (
size_t i = 1; i <
k; ++i)
4748 for (
size_t i = n; i > 0; --i)
4754 for (
size_t i = 0; i < n; ++i)
4759 template <
typename IntT>
4763 const size_t n = list.
size();
4769 IntT max_key = min_key;
4773 if (value < min_key)
4775 if (value > max_key)
4781 for (
size_t i = 0; i <
k; ++i)
4788 for (
size_t bucket = 0; bucket <
k; ++bucket)
4795 for (
size_t c = 0; c <
times; ++c)
4797 out.get_curr_ne() = value;
4804 template <
typename IntT>
4808 const size_t n = list.
size();
4814 IntT max_key = min_key;
4818 if (value < min_key)
4820 if (value > max_key)
4826 for (
size_t i = 0; i <
k; ++i)
4833 for (
size_t bucket = 0; bucket <
k; ++bucket)
4840 for (
size_t c = 0; c <
times; ++c)
4842 out.get_curr_ne() = value;
4849 template <
typename IntT>
4854 if constexpr (std::is_signed_v<std::remove_cv_t<IntT>>)
4855 return static_cast<U>(value) ^
4856 (
U{1} << (std::numeric_limits<U>::digits - 1));
4858 return static_cast<U>(value);
4862 template <
template <
typename>
class C,
typename IntT>
4868 const size_t n = a.size();
4877 for (
size_t i = 0; i < 256; ++i)
4880 const size_t shift =
pass * 8;
4881 for (
size_t i = 0; i < n; ++i)
4884 const auto bucket =
static_cast<size_t>((key >> shift) &
U{0xFF});
4888 for (
size_t i = 1; i < 256; ++i)
4891 for (
size_t i = n; i > 0; --i)
4894 const auto bucket =
static_cast<size_t>((key >> shift) &
U{0xFF});
4898 for (
size_t i = 0; i < n; ++i)
4912 template <
typename IntT>
4926 for (
size_t i = 0; i < 256; ++i)
4929 const size_t shift =
pass * 8;
4930 for (
size_t i = 0; i < n; ++i)
4933 const auto bucket =
static_cast<size_t>((key >> shift) &
U{0xFF});
4937 for (
size_t i = 1; i < 256; ++i)
4940 for (
size_t i = n; i > 0; --i)
4943 const auto bucket =
static_cast<size_t>((key >> shift) &
U{0xFF});
4947 for (
size_t i = 0; i < n; ++i)
4961 template <
typename IntT>
4967 if (
const size_t n = list.
size(); n < 2)
4972 for (
size_t i = 0; i < 256; ++i)
4977 const size_t shift =
pass * 8;
4981 Slinknc *link = list.HTList::remove_first_ne();
4984 const auto bucket =
static_cast<size_t>((key >> shift) &
U{0xFF});
4985 buckets[bucket].
append(link);
4988 for (
auto & bucket: buckets)
4989 list.HTList::append(bucket);
5001 template <
typename IntT>
5007 if (
const size_t n = list.
size(); n < 2)
5012 for (
size_t i = 0; i < 256; ++i)
5017 const size_t shift =
pass * 8;
5023 const auto bucket =
static_cast<size_t>((key >> shift) &
U{0xFF});
5024 buckets[bucket].
append(node);
5027 for (
auto & bucket: buckets)
5038 template <
typename T>
5046 template <
typename T>
5065 template <
typename T>
5088 template <
typename T>
5115 template <
typename T>
5142 template <
typename T>
5164 template <
typename T>
5169 <<
"counting_sort(): null pointer with non-zero length";
5183 template <
typename T,
size_t N>
5205 template <
typename T>
5227 template <
typename T>
5245 template <
typename T>
5263 template <
typename T>
5283 template <
typename T>
5288 <<
"radix_sort(): null pointer with non-zero length";
5302 template <
typename T,
size_t N>
5314 namespace bucket_sort_detail
5319 template <
typename T,
class Compare>
5321 const Compare &
cmp)
5322 noexcept(std::is_nothrow_move_constructible_v<T>
and
5323 std::is_nothrow_move_assignable_v<T>
and
5324 noexcept(std::declval<const Compare &>()(std::declval<const T &>(),
5325 std::declval<const T &>())))
5327 for (
size_t i = lo + 1; i < hi; ++i)
5329 T tmp = std::move(a[i]);
5333 a[j] = std::move(a[j - 1]);
5336 a[j] = std::move(
tmp);
5351 template <
typename T,
class Compare,
class BucketKey>
5359 <<
"bucket_sort: num_buckets must be > 0";
5363 for (
size_t i = 0; i < num_buckets; ++i)
5366 for (
size_t i = 0; i < n; ++i)
5368 const size_t b = bucket_key(a[i]);
5370 <<
"bucket_sort: bucket_key returned " << b
5371 <<
" which is >= num_buckets (" << num_buckets <<
")";
5378 for (
size_t i = 1; i < num_buckets; ++i)
5384 for (
size_t i = 0; i < num_buckets; ++i)
5387 for (
size_t i = 0; i < n; ++i)
5389 const size_t b = bucket_key(a[i]);
5395 for (
size_t b = 0; b < num_buckets; ++b)
5401 for (
size_t i = 0; i < n; ++i)
5402 a[i] = std::move(
tmp[i]);
5413 template <
typename T,
class Container,
class SortFn,
class Compare>
5416 const size_t n = a.size();
5422 for (
auto it = a.get_it(); it.has_curr(); it.next_ne())
5423 tmp[i++] = std::move(it.get_curr_ne());
5428 for (
auto it = a.get_it(); it.has_curr(); it.next_ne())
5429 it.get_curr_ne() = std::move(
tmp[i++]);
5433 template <auto SortFn>
5436 template <
class Compare>
5439 return [](
auto *p,
size_t n,
const Compare & c) {
SortFn(p, n, c); };
5444 template <
class BucketKey>
5450 template <
class Compare>
5453 return [
this](
auto *p,
size_t n,
const Compare & c)
5495 template <
typename T,
class Compare = Aleph::less<T>,
class BucketKey>
5498 const Compare &
cmp = Compare())
5501 <<
"bucket_sort(): null pointer with non-zero length";
5531 template <
typename T,
class Compare = Aleph::less<T>>
5532 requires std::floating_point<T>
5536 <<
"bucket_sort(): null pointer with non-zero length";
5541 T min_val = a[0], max_val = a[0];
5542 for (
size_t i = 0; i < n; ++i)
5549 if (a[i] < min_val) min_val = a[i];
5550 if (a[i] > max_val) max_val = a[i];
5553 const T range = max_val - min_val;
5561 if constexpr (std::is_same_v<Compare, Aleph::less<T>>
or
5562 std::is_same_v<Compare, Aleph::greater<T>>)
5565 const size_t num_buckets = n;
5566 auto key = [min_val,
range, num_buckets,
descending](
const T & val) ->
size_t
5568 auto b =
static_cast<size_t>((val - min_val) /
range *
5569 static_cast<T>(num_buckets - 1));
5570 if (b >= num_buckets)
5571 b = num_buckets - 1;
5574 b = (num_buckets - 1) - b;
5602 template <
typename T,
class Compare = Aleph::less<T>>
5603 requires std::floating_point<T>
5606 bucket_sort_detail::apply_sort_with_temp<T>(a,
5621 template <
typename T,
class Compare = Aleph::less<T>>
5622 requires std::floating_point<T>
5641 template <
typename T,
size_t N,
class Compare = Aleph::less<T>>
5642 requires std::floating_point<T>
5661 template <
typename T,
class Compare = Aleph::less<T>>
5662 requires std::floating_point<T>
5665 bucket_sort_detail::apply_sort_with_temp<T>(list,
5683 template <
typename T,
class Compare = Aleph::less<T>,
class BucketKey>
5686 const Compare &
cmp = Compare())
5688 bucket_sort_detail::apply_sort_with_temp<T>(a,
5706 template <
typename T,
class Compare = Aleph::less<T>,
class BucketKey>
5709 const Compare &
cmp = Compare())
5721 namespace timsort_detail
5744 template <
typename T>
5746 noexcept(std::is_nothrow_swappable_v<T>)
5750 std::swap(a[lo], a[hi - 1]);
5765 template <
typename T,
class Compare>
5768 const Compare &
cmp)
5795 template <
typename T,
class Compare>
5797 const size_t start,
const Compare &
cmp)
5798 noexcept(std::is_nothrow_move_constructible_v<T>
and
5799 std::is_nothrow_move_assignable_v<T>
and
5800 noexcept(std::declval<const Compare &>()(std::declval<const T &>(),
5801 std::declval<const T &>())))
5804 size_t i = (start <= lo) ? lo + 1 : start;
5807 T pivot = std::move(a[i]);
5812 while (left < right)
5814 const size_t mid = left + (right - left) / 2;
5822 for (
size_t p = i; p > left; --p)
5823 a[p] = std::move(a[p - 1]);
5824 a[left] = std::move(
pivot);
5846 template <
typename T,
class Compare>
5848 const size_t hint,
const Compare &
cmp)
5849 noexcept(
noexcept(std::declval<const Compare &>()(std::declval<const T &>(),
5850 std::declval<const T &>())))
5916 template <
typename T,
class Compare>
5918 const size_t hint,
const Compare &
cmp)
5919 noexcept(
noexcept(std::declval<const Compare &>()(std::declval<const T &>(),
5920 std::declval<const T &>())))
5975 template <
typename T,
class Compare>
5981 for (
size_t i = 0; i <
len1; ++i)
5992 a[
dest++] = std::move(a[
c2++]);
6007 template <
typename T,
class Compare>
6013 for (
size_t i = 0; i <
len2; ++i)
6023 a[--
dest] = std::move(a[--
c1]);
6039 template <
typename T,
class Compare>
6085 template <
typename T,
class Compare>
6088 const Compare &
cmp)
6109 template <
typename T,
class Compare>
6112 const Compare &
cmp)
6138 template <
typename T,
class Compare>
6167 size_t remaining = n;
6169 while (remaining > 0)
6185 <<
"timsort: run stack overflow (stack_size=" <<
stack_size
6186 <<
" >= MAX_STACK=" <<
MAX_STACK <<
"); this should never happen";
6231 template <
typename T,
class Compare = Aleph::less<T>>
6238 <<
"timsort(): null pointer with non-zero length";
6259 template <
typename T,
class Compare = Aleph::less<T>>
6261 const Compare &
cmp = Compare())
6264 <<
"timsort(): negative bounds [" <<
l <<
", " <<
r <<
"] are not allowed";
6270 <<
"timsort(): null pointer contract violation for range ["
6271 <<
l <<
", " <<
r <<
"]; cannot call timsort_detail::timsort_impl()";
6286 template <
typename T,
class Compare = Aleph::less<T>>
6289 bucket_sort_detail::apply_sort_with_temp<T>(a,
6304 template <
typename T,
class Compare = Aleph::less<T>>
6323 template <
typename T,
size_t N,
class Compare = Aleph::less<T>>
6324 requires std::is_invocable_r_v<bool, Compare, const T &, const T &>
6343 template <
typename T,
class Compare = Aleph::less<T>>
6346 bucket_sort_detail::apply_sort_with_temp<T>(list,
6364 template <
typename T,
class Compare = Aleph::less<T>>
6367 bucket_sort_detail::apply_sort_with_temp<T>(list,
C++20 concepts for constraining comparison functors.
Exception handling system with formatted messages for Aleph-w.
#define ah_runtime_error_unless(C)
Throws std::runtime_error if condition does NOT hold.
#define ah_out_of_range_error_if(C)
Throws std::out_of_range if condition holds.
#define ah_domain_error_if(C)
Throws std::domain_error if condition holds.
#define ah_logic_error()
Throws std::logic_error unconditionally.
#define ah_invalid_argument_if(C)
Throws std::invalid_argument if condition holds.
#define ah_range_error_if(C)
Throws std::range_error if condition holds.
#define ah_out_of_range_error()
Throws std::out_of_range unconditionally.
Functional programming utilities for Aleph-w containers.
General utility functions and helpers.
Simple dynamic array with automatic resizing and functional operations.
static Array create(size_t n)
Create an array with n logical elements.
constexpr size_t size() const noexcept
Return the number of elements stored in the stack.
T & append(const T &data)
Append a copy of data
void reserve(size_t cap)
Reserves cap cells into the array.
Helper class to compare nodes of a linked list.
bool operator()(Tlink *l1, Tlink *l2) const noexcept(noexcept(std::declval< const Compare & >()(std::declval< const T & >(), std::declval< const T & >())))
Compares two nodes based on their data.
Compare_Tnode(Compare cmp_fct=Compare()) noexcept(std::is_nothrow_copy_constructible_v< Compare >)
Construct from a comparison functor.
void next_ne() noexcept
Move the iterator one position backward guaranteeing no exception.
bool has_curr() const noexcept
Return true if the iterator has current item.
Dlink * get_curr() const
Return the current node of iterator.
Doubly linked circular list node.
Dlink * remove_next() noexcept
Remove the item that is after this
void concat_list(Dlink *head) noexcept
Concatenate list head to list this
constexpr bool is_unitarian_or_empty() const noexcept
Return true if this (as header node) has zero or one element.
constexpr bool is_empty() const noexcept
Return true if this (as header node) is empty.
void append(Dlink *node) noexcept
Insert node before this.
void swap(Dlink *link) noexcept
Swap this with list whose header is link.
Node belonging to a double circular linked list with header node.
Dnode< T > * remove_first_ne() noexcept
Remove the first node and return its address.
T & get_data() noexcept
Return a modifiable reference to the data contained in the node.
size_t size() const noexcept
Return the current dimension of array.
bool exist(const size_t i) const
Return true if the i-th entry is accessible.
void reserve(const size_t l, const size_t r)
Allocate a range of entries.
void next_ne() noexcept
Move the iterator one position forward guaranteeing no exception.
T & get_curr_ne() const noexcept
Dynamic doubly linked list with O(1) size and bidirectional access.
const size_t & size() const noexcept
Return the number of elements (constant time)
Iterator on the items of list.
T & get_curr() const
Return the current item.
T & get_curr_ne() const noexcept
Return the current link guaranteeing no exception. Be careful.
Dynamic singly linked list with functional programming support.
T remove_first_ne() noexcept
T & get_first_ne() const noexcept
Return the first item of the list without exception.
size_t size() const noexcept
Return the number of elements stored in the stack.
bool is_empty() const noexcept
Return true if stack is empty.
T pop() noexcept
Pop by moving the top of stack.
T & push(const T &data) noexcept(std::is_nothrow_copy_assignable_v< T >)
Push a copy of data
void next_ne() noexcept
Move the iterator one position forward guaranteeing no exception.
Slinknc * get_curr() const
bool has_curr() const noexcept
Single linked list of nodes.
Slinknc * get_first() const noexcept
constexpr bool is_empty() const noexcept
void concat_list(HTList &l) noexcept
void append(Slinknc *link) noexcept
size_t split_list(HTList &l, HTList &r) noexcept
It divides 'this' into two equal lists without modifying.
Slinknc * remove_first_ne() noexcept
size_t size() const noexcept
Count the number of elements of the list.
void insert(Slinknc *link) noexcept
Slinknc * get_last() const noexcept
Return the last item of the list (nullptr if the list is empty)
size_t split_list_ne(HTList &l, HTList &r) noexcept
bool is_unitarian_or_empty() const noexcept
Return true if list contains one element or is empty.
Comparator wrapper that inverts the comparison order.
Negate_Compare(Compare __cmp=Compare()) noexcept(std::is_nothrow_copy_assignable_v< Compare >)
Construct from a comparator.
bool operator()(const T &e1, const T &e2) const noexcept(noexcept(std::declval< const Compare & >()(e2, e1)))
Compare in reverse order: returns cmp(e2, e1).
Link of a single linked list non-circular and without header node.
void insert(Slinknc *p) noexcept
insert(p) inserts the node pointed by p after this.
Value concept accepted by counting sort overloads.
Integral value accepted by linear-time integer sorting algorithms.
Value concept accepted by radix sort overloads.
Value concept for counting sort.
Value concept for radix sort.
__gmp_expr< typename __gmp_resolve_expr< T, V >::value_type, __gmp_binary_expr< __gmp_expr< T, U >, __gmp_expr< V, W >, __gmp_min_function > > min(const __gmp_expr< T, U > &expr1, const __gmp_expr< V, W > &expr2)
int cmp(const __gmp_expr< T, U > &expr1, const __gmp_expr< V, W > &expr2)
Singly linked list implementations with head-tail access.
const long double offset[]
Offset values indexed by symbol string length (bounded by MAX_OFFSET_INDEX)
void insertion_sort_range(T *a, const size_t lo, const size_t hi, const Compare &cmp) noexcept(std::is_nothrow_move_constructible_v< T > and std::is_nothrow_move_assignable_v< T > and noexcept(std::declval< const Compare & >()(std::declval< const T & >(), std::declval< const T & >())))
Insertion sort a sub-array [lo, hi).
void apply_sort_with_temp(Container &a, SortFn sort_fn, const Compare &cmp)
Helper to sort any container by copying to a temporary array.
void bucket_sort_impl(T *a, const size_t n, const size_t num_buckets, const BucketKey &bucket_key, const Compare &cmp)
Core bucket sort implementation on a raw pointer range.
constexpr radix_unsigned_t< IntT > radix_key(const IntT value) noexcept
IntT counting_value_from_bucket(const size_t bucket, const IntT min_key) noexcept
Retrieve the original value from a bucket index in counting sort.
std::make_unsigned_t< std::remove_cv_t< IntT > > counting_unsigned_t
void counting_sort_impl(C< IntT > &a)
Internal implementation of counting sort for containers.
std::make_unsigned_t< std::remove_cv_t< IntT > > radix_unsigned_t
size_t counting_bucket(const IntT value, const IntT min_key) noexcept
Map a value to its bucket index in counting sort.
size_t counting_bucket_count(const IntT min_key, const IntT max_key)
Compute the number of buckets required for a counting sort range.
void radix_sort_impl(C< IntT > &a)
void merge_force_collapse(T *a, size_t *run_base, size_t *run_len, size_t &stack_size, T *tmp, const Compare &cmp)
Force-merge all remaining runs at the end.
void merge_at(T *a, size_t *run_base, size_t *run_len, size_t &stack_size, const size_t at, T *tmp, const Compare &cmp)
Merge runs[at] with runs[at+1].
void binary_insertion_sort(T *a, const size_t lo, const size_t hi, const size_t start, const Compare &cmp) noexcept(std::is_nothrow_move_constructible_v< T > and std::is_nothrow_move_assignable_v< T > and noexcept(std::declval< const Compare & >()(std::declval< const T & >(), std::declval< const T & >())))
Binary insertion sort on [lo, hi) starting from start.
void timsort_impl(T *a, const size_t n, const Compare &cmp)
Core Timsort implementation.
size_t count_run_and_make_ascending(T *a, const size_t lo, const size_t hi, const Compare &cmp)
Find the length of the natural run starting at lo.
size_t gallop_left(const T &key, const T *a, const size_t len, const size_t hint, const Compare &cmp) noexcept(noexcept(std::declval< const Compare & >()(std::declval< const T & >(), std::declval< const T & >())))
Gallop left: find the insertion point for a key in a sorted range.
void merge_hi(T *a, const size_t base1, const size_t len1, const size_t base2, const size_t len2, T *tmp, const Compare &cmp)
Merge two adjacent sorted runs where len1 >= len2.
void merge_collapse(T *a, size_t *run_base, size_t *run_len, size_t &stack_size, T *tmp, const Compare &cmp)
Maintain the timsort run stack invariants.
void merge_lo(T *a, const size_t base1, const size_t len1, const size_t base2, const size_t len2, T *tmp, const Compare &cmp)
Merge two adjacent sorted runs a[base1..base1+len1) and a[base2..base2+len2) using temporary buffer.
size_t gallop_right(const T &key, const T *a, const size_t len, const size_t hint, const Compare &cmp) noexcept(noexcept(std::declval< const Compare & >()(std::declval< const T & >(), std::declval< const T & >())))
Gallop right: find the insertion point for a key in a sorted range.
constexpr size_t compute_minrun(size_t n) noexcept
Compute the minimum run length for timsort.
void reverse_range(T *a, size_t lo, size_t hi) noexcept(std::is_nothrow_swappable_v< T >)
Reverse elements in [lo, hi).
Main namespace for Aleph-w library functions.
and
Check uniqueness with explicit hash + equality functors.
DynList< size_t > binary_search_dup(const C< T > &a, const T &x, const Compare &cmp=Compare())
Binary search for all occurrences of a value.
and std::convertible_to< std::invoke_result_t< const KeyFn &, size_t >, int > void counting_sort_indices(Array< size_t > &sa, Array< size_t > &tmp, const size_t n, const int min_key, const int max_key, const KeyFn &key_of)
Stable counting sort on an index array by integer keys.
long search_min(T *a, const long l, const long r, const Compare &cmp=Compare())
Returns the smallest element of the array a between l and r.
bool is_sorted(const Container< T > &cont, const Compare &cmp=Compare())
Check if a container is sorted in ascending order.
static std::pair< long, long > partition_three_way(T *a, long l, long r, const Compare &cmp)
long select_pivot(T *a, long l, long r, const Compare &cmp=Compare()) noexcept(noexcept(cmp(a[0], a[0])) &&std::is_nothrow_swappable_v< T >)
Select a pivot for partitioning using median-of-three.
static void insertion_sort_range(Container &a, long l, long r, const Compare &cmp)
long select_pivot_op_impl(const Container &a, const long l, const long r, const Compare &cmp)
Implementation of pivot selection using operator().
std::pair< bool, size_t > search_inversion(const Container< T > &cont, const Compare &cmp=Compare())
Find the first inversion in a container.
void heapsort_subrange(DynArray< T > &a, const long l, const long r, const Compare &cmp)
Heapsort implementation for a subrange of a DynArray.
size_t introsort_depth_limit(size_t n) noexcept
Forward declaration.
bool eq(const C1 &c1, const C2 &c2, Eq e=Eq())
Check equality of two containers using a predicate.
long select_pivot_op(const DynArray< T > &a, const long l, const long r, const Compare &cmp=Compare())
Selects a pivot element as the median between the ends and the center.
Dnode< T > * dlink_random_search(Dlink &list, const T &x, const Compare &cmp=Compare())
Random search for an element in a dlink list.
void sift_down(T *ptr, const size_t l, const size_t r, Compare &cmp)
Restore the heap property by moving the element at position l downwards.
void sift_down_subrange(DynArray< T > &a, long start, const long n, const long offset, const Compare &cmp)
Sift down operation for heapsort on a DynArray subrange.
void quicksort_no_tail(T *a, long l, long r, const Compare &cmp=Compare())
Quicksort implementation with tail-recursion optimization.
long random_search(T *a, const T &x, const long l, const long r, const Compare &cmp=Compare())
Random search for an element in an array.
size_t Quicksort_Threshold
Threshold for using quicksort vs simpler algorithms.
void insertion_sort(T *a, const long l, const long r, const Compare &cmp=Compare()) noexcept(noexcept(cmp(std::declval< T & >(), std::declval< T & >())) and std::is_nothrow_move_constructible_v< T > and std::is_nothrow_move_assignable_v< T >)
Sort an array using insertion sort.
const int Not_Found
Return value for search functions when element is not found.
void counting_sort(DynArray< T > &a)
Stable counting sort for integral DynArray values.
std::pair< TgtContainer< typename SrcContainer::Item_Type >, TgtContainer< typename SrcContainer::Item_Type > > partition(const SrcContainer &c, std::function< bool(const typename SrcContainer::Item_Type &)> operation)
Partition a container into two based on a predicate.
std::pair< bool, size_t > test_sorted(const Container< T > &cont, const Compare &cmp=Compare())
Test if a container is sorted, returning the inversion position.
void introsort_loop(T *a, long l, long r, size_t depth_limit, const Compare &cmp)
Internal recursive function for introsort.
long search_max(T *a, const long l, const long r, const Compare &cmp=Compare())
Returns the maximum element of the array a between l and r.
void timsort(T *a, const size_t n, const Compare &cmp=Compare())
Timsort — adaptive, stable, natural merge sort.
void mergeinsertsort(Tlist< T > &list, const Compare &cmp=Compare(), const size_t lsz=Aleph::Insertion_Threshold)
Sort a list by mergesort combined with the insert method.
void insert_sorted(Dlink &list, Dlink *p, const Compare &cmp)
Inserts a node orderly into a doubly linked list.
Dlink * dlink_random_select(Dlink &list, const size_t i, const Compare &cmp=Compare())
Random selection of the ith element from a list based on Dlink.
void heapsort(T *array, const size_t n, const Compare &cmp=Compare())
Sort an array using the heapsort algorithm.
void faster_heapsort(T *array, const size_t n, const Compare &cmp=Compare())
Optimized version of heapsort.
void mergesort(T *a, const long l, const long r, std::vector< T > &buf, Compare cmp)
Sort an array using merge sort with a reusable buffer.
Divide_Conquer_DP_Result< Cost > divide_and_conquer_partition_dp(const size_t groups, const size_t n, Transition_Cost_Fn transition_cost, const Cost inf=dp_optimization_detail::default_inf< Cost >())
Optimize partition DP using divide-and-conquer optimization.
std::decay_t< typename HeadC::Item_Type > T
T * bsearch(C< T > &a, const T &x, const Compare &cmp=Compare())
Search for a value in a sorted container returning a pointer.
DynArray< size_t > build_index(const C< T > &a, const Compare &cmp=Compare())
Build an index array for indirect sorting.
void list_insertion_sort(ListType &list, const Compare &cmp)
Generic insertion sort for linked lists.
const T & random_select(DynArray< T > &a, const long i, const Compare &cmp=Compare())
Select the i-th smallest element in a DynArray.
void bucket_sort(T *a, const size_t n, const size_t num_buckets, const BucketKey &bucket_key, const Compare &cmp=Compare())
Bucket sort with user-supplied bucket mapping.
static long back_index(const long i) noexcept
Convert a 1-based heap index to a 0-based array index.
void bubble_sort(DynArray< T > &a, const Compare &cmp=Compare())
Sort a dynamic array using bubble sort.
bool diff(const C1 &c1, const C2 &c2, Eq e=Eq())
Check if two containers differ.
void quicksort(T *a, const long l, const long r, const Compare &cmp=Compare())
Sort an array using iterative quicksort with optimizations.
void radix_sort(DynArray< T > &a)
LSD radix sort for integral DynArray values.
void shellsort(DynArray< T > &a, const Compare &cmp=Compare())
Sort a dynamic array using Shell sort.
bool are_equals(const T &op1, const T &op2, Compare &&cmp=Compare())
Determines if operands are equal using a comparison operator.
static std::pair< long, long > partition_three_way_op(Container &a, long l, long r, const Compare &cmp)
DynArray< const T * > build_index_ptr(const C< T > &a, const Compare &cmp=Compare())
Build an index array of pointers for indirect sorting (const version).
Itor3 merge(Itor1 source1Beg, Itor1 source1End, Itor2 source2Beg, Itor2 source2End, Itor3 destBeg)
Merge two sorted ranges.
void quicksort_rec_min(T *a, const long l, const long r, const Compare &cmp=Compare())
Sorts an array according to the quicksort method with minimum space consumption.
long sequential_search(T *a, const T &x, const long l, const long r, Equal eq=Equal())
Linear search for an element in an array.
Link * search_extreme(const Link &list, const Compare &cmp)
Find the extreme (minimum or maximum) element in a linked list.
bool binary_search(Itor beg, Itor end, const T &value)
Binary search for a value.
static const T & __random_select(T *a, const long i, long l, long r, const Compare &cmp)
void quicksort_rec(T *a, const long l, const long r, const Compare &cmp=Compare())
Recursively sort an array using quicksort.
DynList< long > binindex_dup(const C< T > &a, const T &x, const Compare &cmp=Compare())
Returns the indices of all occurrences of a value in a sorted container.
bool is_inversely_sorted(const Container< T > &cont, const Compare &cmp=Compare())
Check if a container is sorted in descending order.
DynList< const T * > bsearch_dup(const C< T > &a, const T &x, const Compare &cmp=Compare())
Search for all occurrences of a value returning pointers (const version).
long partition_op_impl(Container &a, const long l, const long r, const Compare &cmp)
Implementation of partitioning using operator().
Container< T > range(const T start, const T end, const T step=1)
Generate a range of values [start, end] with a given step.
void selection_sort(T *a, const size_t n, const Compare &cmp=Compare()) noexcept(noexcept(cmp(a[0], a[0])) &&std::is_nothrow_swappable_v< T >)
Sort an array using the selection sort algorithm.
void introsort(T *a, const long l, const long r, const Compare &cmp=Compare())
Sort an array using introsort (introspective sort).
long binindex(const C< T > &a, const T &x, const Compare &cmp=Compare())
Returns the index where a value appears (or should be inserted) in a sorted container.
void quicksort_insertion(T *a, const long l, const long r, const Compare &cmp=Compare())
Sorts an array by the improved quicksort method.
size_t Insertion_Threshold
Threshold for switching to insertion sort in hybrid algorithms.
long binary_search_rec(T *a, const T &x, const long l, const long r, const Compare &cmp=Compare())
Recursive binary search on an ordered array.
long partition_op(DynArray< T > &a, const long l, const long r, const Compare &cmp=Compare())
Partition a DynArray using operator().
T & sift_up(T *ptr, const size_t l, const size_t r, Compare &cmp)
Restore the heap property by moving the element at position r upwards.
void merge_lists(Tlist &l1, Tlist &l2, Tlist &result, const Compare &cmp=Compare())
Merge two sorted lists into a single sorted list.
Itor::difference_type count(const Itor &beg, const Itor &end, const T &value)
Count elements equal to a value.
void push2(Stack &stack, const A &a, const B &b)
Push two values onto a stack.
void quicksort_op(C< T > &a, const Compare &cmp=Compare(), const size_t threshold=Quicksort_Threshold)
Optimized quicksort for containers using operator().
Comparator specialization for Dnode objects.
Compare_Dnode(const Compare &cmp=Compare()) noexcept(std::is_nothrow_copy_constructible_v< Compare >)
Factory for bucket_sort with extra parameters.
const BucketKey & bucket_key
auto operator()(const Compare &) const
Factory for lambdas that forward to a sort function.
auto operator()(const Compare &) const
FooMap m(5, fst_unit_pair_hash, snd_unit_pair_hash)
Fixed-capacity binary heap and heapsort algorithms.
Stack implementations backed by dynamic or fixed arrays.
Dynamic array container with automatic resizing.
Lazy and scalable dynamic array implementation.
Dynamic doubly linked list implementation.