94#ifndef TPL_SORT_UTILS_H
95#define TPL_SORT_UTILS_H
108#include <type_traits>
169 const T &first = it.get_curr();
170 const T *prev = &first;
172 for (; it.has_curr(); it.next_ne())
174 const T &curr = it.get_curr();
175 if (
cmp(curr, *prev))
206 const Compare &
cmp = Compare())
209 return std::make_pair(
true, 0);
212 const T &first = it.get_curr();
213 const T *prev = &first;
216 for (; it.has_curr(); it.next_ne(), ++i)
218 const T &curr = it.get_curr();
219 if (
cmp(curr, *prev))
220 return std::make_pair(
false, i);
224 return std::make_pair(
true, i);
253 const T &first = it.get_curr();
254 const T *prev = &first;
256 for (; it.has_curr(); it.next_ne())
258 const T &curr = it.get_curr();
259 if (
cmp(*prev, curr))
290 const Compare &
cmp = Compare())
296 const T &first = it.get_curr();
297 const T *prev = &first;
300 for (; it.has_curr(); it.next_ne(), ++i)
302 const T &curr = it.get_curr();
303 if (
cmp(curr, *prev))
343template <
typename T, StrictWeakOrder<T> Compare = Aleph::less<T>>
351 for (
size_t i = 0,
min, j; i < n - 1; ++i)
353 for (
min = i, j = i + 1; j < n; ++j)
358 std::swap(a[
min], a[i]);
384template <
class Link,
class Compare>
389 typename Link::Iterator it(
const_cast<Link &
>(list));
392 for (it.next(); it.has_curr(); it.next_ne())
394 Link *curr = it.get_curr();
402template <
typename T, StrictWeakOrder<T> Compare = Aleph::less<T>>
422template <
class Compare>
428template <
class Compare>
443template <
class Compare>
466template <
typename Tlink,
template <
class>
class Tnode,
typename T,
class Compare>
480 noexcept(
noexcept(std::declval<const Compare &>()(std::declval<const T &>(),
481 std::declval<const T &>())))
488 return cmp(n1->get_data(), n2->get_data());
493 noexcept(
noexcept(std::declval<const Compare &>()(std::declval<const T &>(),
494 std::declval<const T &>())))
500 return cmp(n->get_data(), x);
507template <
typename T,
class Compare>
519template <
typename T,
class Compare>
529template <
typename T, StrictWeakOrder<T> Compare = Aleph::less<T>>
556template <
typename T,
class Equal = Aleph::equal_to<T>>
560 for (
long i =
l; i <=
r; ++i)
584template <
typename T,
class Equal = Aleph::equal_to<T>>
588 for (
long i =
l; i <=
r; ++i)
608template <
class Link,
typename T,
class Equal>
611 for (
typename Link::Iterator it(
const_cast<Link &
>(list)); it.has_curr(); it.next_ne())
612 if (
Link *curr = it.get_curr();
eq(curr, x))
624template <
typename T,
class Equal = Aleph::equal_to<T>>
638template <
typename T,
class Equal = Aleph::equal_to<T>>
652template <
typename T,
class Equal = Aleph::equal_to<T>>
663template <
typename T,
class Equal = Aleph::equal_to<T>>
675template <
typename T,
class Equal = Aleph::equal_to<T>>
680 const auto &base =
static_cast<const Dlink &
>(list);
683 return ret ==
nullptr ? nullptr :
static_cast<const Dnode<T> *
>(
ret);
687template <
typename T,
class Equal = Aleph::equal_to<T>>
699template <
typename T,
class Equal = Aleph::equal_to<T>>
703 return ret !=
nullptr ? &
ret->get_data() :
nullptr;
712template <
typename T,
class Equal = Aleph::equal_to<T>>
716 return ret !=
nullptr ? &
ret->get_data() :
nullptr;
725template <
typename T,
class Equal = Aleph::equal_to<T>>
730 T &curr = it.get_curr_ne();
743template <
typename T,
class Equal = Aleph::equal_to<T>>
748 const T &curr = it.get_curr_ne();
769template <
typename T, StrictWeakOrder<T> Compare = Aleph::less<T>>
773 for (
long i =
l + 1; i <=
r; ++i)
784template <
typename T, StrictWeakOrder<T> Compare = Aleph::less<T>>
794template <
typename T, StrictWeakOrder<T> Compare = Aleph::greater<T>>
803template <
typename T, StrictWeakOrder<T> Compare = Aleph::less<T>>
823template <
typename T, StrictWeakOrder<T> Compare = Aleph::less<T>>
826 const auto &base =
static_cast<const Dnode<T> &
>(list);
829 return ret !=
nullptr ? &(
ret->get_data()) :
nullptr;
833template <
typename T, StrictWeakOrder<T> Compare = Aleph::less<T>>
836 const auto &base =
static_cast<const Dnode<T> &
>(list);
839 return ret !=
nullptr ? &(
ret->get_data()) :
nullptr;
847template <
typename T, StrictWeakOrder<T> Compare = Aleph::less<T>>
871template <
typename T, StrictWeakOrder<T> Compare = Aleph::less<T>>
878template <
typename T, StrictWeakOrder<T> Compare = Aleph::less<T>>
889template <
typename T, StrictWeakOrder<T> Compare = Aleph::greater<T>>
896template <
typename T, StrictWeakOrder<T> Compare = Aleph::greater<T>>
937template <
typename T, StrictWeakOrder<T> Compare = Aleph::less<T>>
944 for (
long i =
l + 1, j; i <=
r; ++i)
946 T tmp = std::move(a[i]);
947 for (j = i; j >
l and cmp(
tmp, a[j - 1]); --j)
948 a[j] = std::move(a[j - 1]);
950 a[j] = std::move(
tmp);
967template <
class Compare>
980template <
class Compare>
1014 ah_logic_error() <<
"insert_sorted(): reached end of list traversal without inserting";
1024template <
class ListType,
class Compare>
1027 if (list.is_empty())
1031 aux.append(list.remove_first());
1032 while (
not list.is_empty())
1045template <
typename T, StrictWeakOrder<T> Compare = Aleph::less<T>>
1064template <
typename T, StrictWeakOrder<T> Compare = Aleph::less<T>>
1070 return std::move(
l);
1080template <
typename T, StrictWeakOrder<T> Compare = Aleph::less<T>>
1116template <
typename T, StrictWeakOrder<T> Compare = Aleph::less<T>>
1118 const Compare &
cmp = Compare())
1120 const long s =
r -
l + 1;
1129 if (buf.
size() <
static_cast<size_t>(s))
1130 buf.
putn(
static_cast<size_t>(s) - buf.
size());
1134 for (
long i =
l; i <=
m; ++i)
1135 buf[
buf_idx++] = std::move(a[i]);
1139 for (
long j =
m + 1; j <=
r; ++j)
1140 buf[
buf_idx--] = std::move(a[j]);
1146 for (
long k =
l;
k <=
r; ++
k)
1147 if (
not cmp(buf[j], buf[i]))
1148 a[
k] = std::move(buf[i++]);
1150 a[
k] = std::move(buf[j--]);
1167template <
typename T, StrictWeakOrder<T> Compare = Aleph::less<T>>
1168inline void merge(
T *a,
const long l,
const long m,
const long r,
const Compare &
cmp = Compare())
1170 Array<T> buf(
static_cast<size_t>(
r -
l + 1));
1181template <
typename T,
class Compare>
1187 const long m =
l + (
r -
l) / 2;
1232template <
typename T, StrictWeakOrder<T> Compare = Aleph::less<T>>
1238 Array<T> buf(
static_cast<size_t>(
r -
l + 1));
1267template <
typename Tlist,
class Compare>
1270 assert(result.is_empty());
1279 result.concat_list(
l2);
1281 result.concat_list(
l1);
1295template <
typename T, StrictWeakOrder<T> Compare = Aleph::less<T>>
1331template <
typename Tlist,
class Compare>
1334 if (list.is_unitarian_or_empty())
1368 if (list.is_unitarian_or_empty())
1371 if (list.size() <=
lsz)
1397 if (list.is_unitarian_or_empty())
1416template <
typename T, StrictWeakOrder<T> Compare = Aleph::less<T>>
1429template <
typename T, StrictWeakOrder<T> Compare = Aleph::less<T>>
1442template <
typename T, StrictWeakOrder<T> Compare = Aleph::less<T>>
1458template <
typename T, StrictWeakOrder<T> Compare = Aleph::less<T>>
1462 return std::move(list);
1472template <
typename T, StrictWeakOrder<T> Compare = Aleph::less<T>>
1504 std::swap(a[p], a[
r]);
1513 while (
cmp(a[++i], a[
r]))
1516 while (
cmp(a[
r], a[--j]))
1524 std::swap(a[i], a[j]);
1528 std::swap(a[i], a[
r]);
1551template <
typename T, StrictWeakOrder<T> Compare = Aleph::less<T>>
1576template <
typename T, StrictWeakOrder<T> Compare = Aleph::less<T>>
1582 const long left_size =
pivot -
l;
1583 const long right_size =
r -
pivot;
1586 if (left_size < right_size)
1615template <
typename T, StrictWeakOrder<T> Compare = Aleph::less<T>>
1634template <
typename T, StrictWeakOrder<T> Compare>
1636 const Compare &
cmp)
noexcept(
noexcept(
cmp(a[0], a[0])) &&
1637 std::is_nothrow_swappable_v<T>)
1639 const long m =
l + (
r -
l) / 2;
1643 if (
cmp(a[
r], a[
l]))
1644 std::swap(a[
l], a[
r]);
1646 if (
cmp(a[
m], a[
l]))
1647 std::swap(a[
m], a[
l]);
1649 if (
cmp(a[
r], a[
m]))
1650 std::swap(a[
r], a[
m]);
1695template <
typename T, StrictWeakOrder<T> Compare = Aleph::less<T>>
1704 const auto n =
static_cast<size_t>(
r -
l + 1);
1706 typedef std::pair<long, long>
Partition;
1711 while (stack.
size() > 0)
1762template <
typename T,
class Compare>
1838template <
typename T, StrictWeakOrder<T> Compare = Aleph::less<T>>
1844 const auto n =
static_cast<size_t>(
r -
l + 1);
1870template <
typename T, StrictWeakOrder<T> Compare = Aleph::less<T>>
1905template <
typename T, StrictWeakOrder<T> Compare = Aleph::less<T>>
1910 const auto n =
static_cast<size_t>(end - begin);
1921template <
typename T, StrictWeakOrder<T> Compare = Aleph::less<T>>
1924 const size_t n = arr.
size();
1944template <
class Compare>
1988template <
typename T, StrictWeakOrder<T> Compare = Aleph::less<T>>
1998template <
typename T,
class Compare>
2009 cmp(p->get_data(),
pivot->get_data()))
2026template <
typename T, StrictWeakOrder<T> Compare = Aleph::less<T>>
2070template <
typename T, StrictWeakOrder<T> Compare = Aleph::less<T>>
2156template <
typename T, StrictWeakOrder<T> Compare = Aleph::less<T>>
2158 const Compare &
cmp = Compare())
2181template <
typename T, StrictWeakOrder<T> Compare = Aleph::less<T>>
2183 const Compare &
cmp = Compare())
2224template <
typename T,
class Compare>
2256 list.
swap(&smaller);
2292template <
typename T, StrictWeakOrder<T> Compare = Aleph::less<T>>
2327template <
typename T, StrictWeakOrder<T> Compare = Aleph::less<T>>
2332 return p ==
nullptr ? nullptr : &(p->
get_data());
2335template <
typename T,
class Compare>
2346 while (current <=
gt)
2347 if (
cmp(a[current], a[
r]))
2349 std::swap(a[
lt], a[current]);
2353 else if (
cmp(a[
r], a[current]))
2355 std::swap(a[current], a[
gt]);
2362 std::swap(a[current], a[
r]);
2363 return {
lt, current};
2366template <
class Container,
typename T,
class Compare>
2378 while (current <=
gt)
2379 if (
cmp(a(current), a(
r)))
2381 std::swap(a(
lt), a(current));
2385 else if (
cmp(a(
r), a(current)))
2387 std::swap(a(current), a(
gt));
2394 std::swap(a(current), a(
r));
2395 return {
lt, current};
2398template <
typename T,
class Compare>
2411 if (i >=
lt and i <= current)
2431template <
typename T,
class Compare,
typename Container>
2439 const long m =
l + (
r -
l) / 2;
2464template <
typename T, StrictWeakOrder<T> Compare = Aleph::less<T>>
2466 const Compare &
cmp = Compare())
2476template <
typename T, StrictWeakOrder<T> Compare = Aleph::less<T>>
2478 const Compare &
cmp = Compare())
2491template <
typename T,
class Compare,
typename Container>
2508 while (
cmp(a(++i), a(
r)))
2511 while (
cmp(a(
r), a(--j)))
2518 std::swap(a(i), a(j));
2522 std::swap(a(i), a(
r));
2534template <
typename T, StrictWeakOrder<T> Compare = Aleph::less<T>>
2547template <
typename T, StrictWeakOrder<T> Compare = Aleph::less<T>>
2553template <
typename Container,
class Compare>
2556 using T =
typename Container::Item_Type;
2557 for (
long p =
l + 1; p <=
r; ++p)
2559 T key = std::move(a(p));
2561 while (j >=
l and cmp(key, a(j)))
2563 a(j + 1) = std::move(a(j));
2566 a(j + 1) = std::move(key);
2570template <
typename T,
class Compare>
2572 const Compare &
cmp = Compare())
2586 if (i >=
lt and i <= current)
2598template <
typename T,
class Compare>
2600 const Compare &
cmp = Compare())
2614 if (i >=
lt and i <= current)
2633template <
typename T, StrictWeakOrder<T> Compare = Aleph::less<T>>
2639 const long n =
static_cast<long>(
n_sz) - 1;
2652template <
typename T, StrictWeakOrder<T> Compare = Aleph::less<T>>
2658 const long n =
static_cast<long>(
n_sz) - 1;
2704template <
typename T, StrictWeakOrder<T> Compare = Aleph::less<T>>
2721template <
typename T, StrictWeakOrder<T> Compare = Aleph::less<T>>
2749template <
class Compare>
2823template <
typename T, StrictWeakOrder<T> Compare = Aleph::less<T>>
2854template <
typename T, StrictWeakOrder<T> Compare = Aleph::less<T>>
2859 auto *p =
static_cast<Dnode<T> *
>(link);
2861 return p !=
nullptr ? &(p->get_data()) :
nullptr;
2883template <
typename T, StrictWeakOrder<T> Compare = Aleph::less<T>>
2886 const long n =
static_cast<long>(a.
size());
2890 for (
long i = 0; i < n - 1; ++i)
2894 for (
long j = i + 1; j < n; ++j)
2899 std::swap(a(
min), a(i));
2933template <
typename T, StrictWeakOrder<T> Compare = Aleph::less<T>>
2936 const long n =
static_cast<long>(a.
size());
2940 for (
long i = 0; i < n - 1; ++i)
2941 for (
long j = n - 1; j > i; --j)
2942 if (
cmp(a(j), a(j - 1)))
2944 std::swap(a(j - 1), a(j));
2976 for (
long i =
l + 1; i <=
r; i++)
2978 T tmp = std::move(a(i));
2981 a(j) = std::move(a(j - 1));
2983 a(j) = std::move(
tmp);
2994 const auto n = a.size();
3034template <
typename T, StrictWeakOrder<T> Compare = Aleph::less<T>>
3037 const long n = a.
size();
3043 static constexpr long ciura_gaps[] = {1, 4, 10, 23, 57, 132,
3044 301, 701, 1750, 4024, 9233, 21223,
3045 48805, 112217, 258100, 593630, 1365513, 3140680};
3057 for (
long i =
h; i < n; i++)
3059 T tmp = std::move(a(i));
3064 a(j) = std::move(a(j -
h));
3068 a(j) = std::move(
tmp);
3085template <
typename T,
class Compare>
3089 for (
long i = n; i > 1; i = p)
3107template <
typename T,
class Compare>
3133template <
typename T,
class Compare>
3151template <
typename T,
class Compare>
3165 noexcept(
noexcept(std::declval<const Compare &>()(
e2,
e1)))
3211template <
typename T, StrictWeakOrder<T> Compare = Aleph::less<T>>
3214 const long n = a.
size();
3222 for (
long i = n / 2; i >= 1; --i)
3226 for (
long i = n; i >= 2; --i)
3228 std::swap(a(0), a(i - 1));
3263 std::swap(a(i), a(j));
3266 std::swap(a(i), a(
r));
3277template <
typename T, StrictWeakOrder<T> Compare = Aleph::less<T>>
3306template <
class Stack,
class A,
class B>
3341template <
typename T, StrictWeakOrder<T> Compare = Aleph::less<T>>
3344 long l = 0,
r = a.
size() - 1;
3346 const size_t n = a.
size();
3382template <
typename T,
class Compare>
3388 long c = start << 1;
3421template <
typename T,
class Compare>
3424 const long n =
r -
l + 1;
3431 for (
long i = n / 2; i >= 1; --i)
3435 for (
long i = n; i >= 2; --i)
3437 std::swap(a(
l), a(
l + i - 1));
3446template <
typename T,
class Compare>
3506template <
typename T, StrictWeakOrder<T> Compare = Aleph::less<T>>
3509 const long n = a.
size();
3540template <
typename T, StrictWeakOrder<T> Compare = Aleph::less<T>>
3542 const Compare &
cmp = Compare())
3546 for (
long i =
l + 1; i <=
r; i++)
3557template <
typename T, StrictWeakOrder<T> Compare = Aleph::greater<T>>
3559 const Compare &
cmp = Compare())
3616 if (
long m =
l + (
r -
l) / 2;
cmp(x, a(
m)))
3618 else if (
cmp(a(
m), x))
3650 if (
long m =
l + (
r -
l) / 2;
cmp(x, *a(
m)))
3652 else if (
cmp(*a(
m), x))
3674 const auto n = a.size();
3710 const auto n = a.size();
3734 const auto n = a.
size();
3746 for (
long i = idx - 1; i >= 0; --i)
3786 const size_t n = a.
size();
3788 for (
size_t i = 0; i < n; ++i)
3825 for (
long i = idx - 1; i >= 0; --i)
3827 const T *ptr = &a(i);
3835 for (
long i = idx + 1, n = a.size(); i < n; ++i)
3837 const T *ptr = &a(i);
3874 const T *ptr = &a(i);
3922 for (
long i = idx - 1; i >= 0; --i)
3932 for (
long i = idx + 1, n = a.size(); i < n; ++i)
3958 const auto n = a.
size();
3970 for (
long i = idx - 1; i >= 0; --i)
3980 for (
long i = idx + 1, n = a.size(); i < n; ++i)
4070 const long mid = idx;
4072 for (
long i = idx - 1; i >= 0; --i)
4081 for (
long i = idx + 1, n = a.size(); i < n; ++i)
4114 for (
long i = idx - 1; i >= 0; --i)
4124 for (
long i = idx + 1, n = a.size(); i < n; ++i)
4143namespace sort_utils_detail {
4159 if constexpr (
requires { c(i); })
4175 std::remove_cvref_t<decltype(indexed_value(std::declval<const C &>(),
size_t{}))>;
4192template <
class C,
class Compare>
4253template <
class C, StrictWeakOrder<sort_utils_detail::Indexed_Value_Type<C>> Compare = Aleph::less<sort_utils_detail::Indexed_Value_Type<C>>>
4256 const size_t n = a.
size();
4258 for (
size_t i = 0; i < n; ++i)
4263 return cmp(sort_utils_detail::indexed_value(a, i), sort_utils_detail::indexed_value(a, j));
4308template <
class C, StrictWeakOrder<sort_utils_detail::Indexed_Value_Type<C>> Compare = Aleph::less<sort_utils_detail::Indexed_Value_Type<C>>>
4311 const size_t n = a.
size();
4313 for (
size_t i = 0; i < n; ++i)
4318 return sort_utils_detail::stable_index_less(a, i, j,
cmp);
4359 const size_t n = a.
size();
4361 for (
size_t i = 0; i < n; ++i)
4403 const size_t n = a.
size();
4405 for (
size_t i = 0; i < n; ++i)
4410 return sort_utils_detail::stable_index_less(a, i, j,
cmp);
4414 for (
size_t i = 0; i < n; ++i)
4415 ret(i) = &a(idx(i));
4441 const size_t n = a.
size();
4443 for (
size_t i = 0; i < n; ++i)
4448 return sort_utils_detail::stable_index_less(a, i, j,
cmp);
4452 for (
size_t i = 0; i < n; ++i)
4453 ret(i) = &a(idx(i));
4489 const size_t n = a.size();
4493 size_t l = 0,
r = n - 1;
4504 const size_t partition_size =
r -
l + 1;
4505 if (partition_size <= 1)
4508 if (partition_size <= threshold)
4514 const auto i =
static_cast<size_t>(
4517 const size_t left_size = i >
l ? i -
l : 0;
4518 const size_t right_size =
r > i ?
r - i : 0;
4520 if (left_size > right_size)
4545template <
typename T, StrictWeakOrder<T> Compare = Aleph::less<T>>
4547 const Compare &
cmp = Compare())
4552 const long m =
l + (
r -
l) / 2;
4570template <
typename T, StrictWeakOrder<T> Compare = Aleph::less<T>>
4575 long m =
l + (
r -
l) / 2;
4578 else if (
cmp(a[
m], x))
4612template <
typename KeyFn>
4613 requires std::invocable<const KeyFn &, size_t>
and
4614 std::convertible_to<std::invoke_result_t<const KeyFn &, size_t>,
int>
4618 ah_domain_error_if(max_key < min_key) <<
"counting_sort_indices(): max_key < min_key";
4624 <<
"counting_sort_indices(): sa/tmp size is smaller than n";
4626 const auto range_minus_one =
static_cast<unsigned long long>(
static_cast<long long>(max_key) -
4627 static_cast<long long>(min_key));
4629 constexpr auto max_count =
static_cast<unsigned long long>(std::numeric_limits<size_t>::max() - size_t(1));
4631 <<
"counting_sort_indices(): key range is too large";
4635 for (
size_t i = 0; i <
k; ++i)
4638 for (
size_t i = 0; i < n; ++i)
4640 const int key =
key_of(sa[i]);
4642 <<
"counting_sort_indices(): key out of expected range";
4643 const auto bucket =
static_cast<size_t>(
static_cast<unsigned long long>(
4644 static_cast<long long>(key) -
static_cast<long long>(min_key)));
4648 for (
size_t j = 1; j <
k; ++j)
4651 for (
size_t i = n; i > 0; --i)
4653 const int key =
key_of(sa[i - 1]);
4654 const auto idx =
static_cast<size_t>(
static_cast<unsigned long long>(
4655 static_cast<long long>(key) -
static_cast<long long>(min_key)));
4659 for (
size_t i = 0; i < n; ++i)
4663namespace sort_utils_detail {
4672template <
typename IntT>
4683template <
typename IntT>
4695template <
typename IntT>
4703 if constexpr (
sizeof(
U) >=
sizeof(
size_t))
4705 constexpr size_t max_count = std::numeric_limits<size_t>::max() -
static_cast<size_t>(1);
4707 <<
"counting_sort(): key range is too large";
4720template <
typename IntT>
4734template <
typename IntT>
4738 return static_cast<IntT>(
static_cast<U>(min_key) +
static_cast<U>(bucket));
4747template <
template <
typename>
class C,
typename IntT>
4751 const size_t n = a.size();
4755 IntT min_key = a(0), max_key = a(0);
4756 for (
size_t i = 1; i < n; ++i)
4766 for (
size_t i = 0; i <
k; ++i)
4769 for (
size_t i = 0; i < n; ++i)
4772 for (
size_t i = 1; i <
k; ++i)
4776 for (
size_t i = n; i > 0; --i)
4782 for (
size_t i = 0; i < n; ++i)
4795template <
typename IntT>
4802 IntT min_key = a[0], max_key = a[0];
4803 for (
size_t i = 1; i < n; ++i)
4813 for (
size_t i = 0; i <
k; ++i)
4816 for (
size_t i = 0; i < n; ++i)
4819 for (
size_t i = 1; i <
k; ++i)
4823 for (
size_t i = n; i > 0; --i)
4829 for (
size_t i = 0; i < n; ++i)
4841template <
typename IntT>
4845 const size_t n = list.
size();
4851 IntT max_key = min_key;
4855 if (
value < min_key)
4857 if (
value > max_key)
4863 for (
size_t i = 0; i <
k; ++i)
4870 for (
size_t bucket = 0; bucket <
k; ++bucket)
4877 for (
size_t c = 0; c <
times; ++c)
4893template <
typename IntT>
4897 const size_t n = list.
size();
4903 IntT max_key = min_key;
4907 if (
value < min_key)
4909 if (
value > max_key)
4915 for (
size_t i = 0; i <
k; ++i)
4922 for (
size_t bucket = 0; bucket <
k; ++bucket)
4929 for (
size_t c = 0; c <
times; ++c)
4947template <
typename IntT>
4951 if constexpr (std::is_signed_v<std::remove_cv_t<IntT>>)
4952 return static_cast<U>(
value) ^ (
U{1} << (std::numeric_limits<U>::digits - 1));
4954 return static_cast<U>(
value);
4966template <
template <
typename>
class C,
typename IntT>
4972 const size_t n = a.size();
4981 for (
size_t i = 0; i < 256; ++i)
4984 const size_t shift =
pass * 8;
4985 for (
size_t i = 0; i < n; ++i)
4988 const auto bucket =
static_cast<size_t>((key >> shift) &
U{0xFF});
4992 for (
size_t i = 1; i < 256; ++i)
4995 for (
size_t i = n; i > 0; --i)
4998 const auto bucket =
static_cast<size_t>((key >> shift) &
U{0xFF});
5002 for (
size_t i = 0; i < n; ++i)
5015template <
typename IntT>
5029 for (
size_t i = 0; i < 256; ++i)
5032 const size_t shift =
pass * 8;
5033 for (
size_t i = 0; i < n; ++i)
5036 const auto bucket =
static_cast<size_t>((key >> shift) &
U{0xFF});
5040 for (
size_t i = 1; i < 256; ++i)
5043 for (
size_t i = n; i > 0; --i)
5046 const auto bucket =
static_cast<size_t>((key >> shift) &
U{0xFF});
5050 for (
size_t i = 0; i < n; ++i)
5063template <
typename IntT>
5069 if (
const size_t n = list.
size(); n < 2)
5074 for (
size_t i = 0; i < 256; ++i)
5079 const size_t shift =
pass * 8;
5083 Slinknc *link = list.HTList::remove_first_ne();
5086 const auto bucket =
static_cast<size_t>((key >> shift) &
U{0xFF});
5087 buckets[bucket].
append(link);
5090 for (
auto &bucket : buckets)
5091 list.HTList::append(bucket);
5102template <
typename IntT>
5108 if (
const size_t n = list.
size(); n < 2)
5113 for (
size_t i = 0; i < 256; ++i)
5118 const size_t shift =
pass * 8;
5124 const auto bucket =
static_cast<size_t>((key >> shift) &
U{0xFF});
5125 buckets[bucket].
append(node);
5128 for (
auto &bucket : buckets)
5138template <
typename T>
5145template <
typename T>
5176template <
typename T>
5199template <
typename T>
5226template <
typename T>
5253template <
typename T>
5275template <
typename T>
5280 <<
"counting_sort(): null pointer with non-zero length";
5294template <
typename T,
size_t N>
5331template <
typename T>
5353template <
typename T>
5371template <
typename T>
5389template <
typename T>
5409template <
typename T>
5414 <<
"radix_sort(): null pointer with non-zero length";
5428template <
typename T,
size_t N>
5439namespace bucket_sort_detail {
5443template <
typename T,
class Compare>
5445 std::is_nothrow_move_constructible_v<T>
and std::is_nothrow_move_assignable_v<T>
and
5446 noexcept(std::declval<const Compare &>()(std::declval<const T &>(), std::declval<const T &>())))
5448 for (
size_t i = lo + 1; i < hi; ++i)
5450 T tmp = std::move(a[i]);
5454 a[j] = std::move(a[j - 1]);
5457 a[j] = std::move(
tmp);
5471template <
typename T,
class Compare,
class BucketKey>
5482 for (
size_t i = 0; i < num_buckets; ++i)
5485 for (
size_t i = 0; i < n; ++i)
5487 const size_t b = bucket_key(a[i]);
5489 <<
" which is >= num_buckets (" << num_buckets <<
")";
5496 for (
size_t i = 1; i < num_buckets; ++i)
5497 offsets[i] = offsets[i - 1] + counts[i - 1];
5502 for (
size_t i = 0; i < num_buckets; ++i)
5505 for (
size_t i = 0; i < n; ++i)
5507 const size_t b = bucket_key(a[i]);
5508 tmp[offsets[b] + counts[b]] = std::move(a[i]);
5513 for (
size_t b = 0; b < num_buckets; ++b)
5518 for (
size_t i = 0; i < n; ++i)
5519 a[i] = std::move(
tmp[i]);
5530template <
typename T,
class Container,
class SortFn,
class Compare>
5533 const size_t n = a.size();
5539 for (
auto it = a.get_it(); it.has_curr(); it.next_ne())
5540 tmp[i++] = std::move(it.get_curr_ne());
5545 for (
auto it = a.get_it(); it.has_curr(); it.next_ne())
5546 it.get_curr_ne() = std::move(
tmp[i++]);
5550template <auto SortFn>
5553 template <
class Compare>
5556 return [](
auto *p,
size_t n,
const Compare &c)
5564template <
class BucketKey>
5570 template <
class Compare>
5573 return [
this](
auto *p,
size_t n,
const Compare &c)
5629template <
typename T, StrictWeakOrder<T> Compare = Aleph::less<T>,
class BucketKey>
5631 const Compare &
cmp = Compare())
5634 <<
"bucket_sort(): null pointer with non-zero length";
5672template <
typename T, StrictWeakOrder<T> Compare = Aleph::less<T>>
5673 requires std::floating_point<T>
5677 <<
"bucket_sort(): null pointer with non-zero length";
5682 T min_val = a[0], max_val = a[0];
5683 for (
size_t i = 0; i < n; ++i)
5696 const T range = max_val - min_val;
5704 if constexpr (std::is_same_v<Compare, Aleph::less<T>>
or std::is_same_v<Compare, Aleph::greater<T>>)
5707 const size_t num_buckets = n;
5708 auto key = [min_val,
range, num_buckets,
descending](
const T &val) ->
size_t
5710 auto b =
static_cast<size_t>((val - min_val) /
range *
static_cast<T>(num_buckets - 1));
5711 if (b >= num_buckets)
5712 b = num_buckets - 1;
5715 b = (num_buckets - 1) - b;
5742template <
typename T, StrictWeakOrder<T> Compare = Aleph::less<T>>
5743 requires std::floating_point<T>
5746 bucket_sort_detail::apply_sort_with_temp<T>(
5762template <
typename T, StrictWeakOrder<T> Compare = Aleph::less<T>>
5763 requires std::floating_point<T>
5781template <
typename T,
size_t N, StrictWeakOrder<T> Compare = Aleph::less<T>>
5782 requires std::floating_point<T>
5800template <
typename T, StrictWeakOrder<T> Compare = Aleph::less<T>>
5801 requires std::floating_point<T>
5804 bucket_sort_detail::apply_sort_with_temp<T>(
5823template <
typename T, StrictWeakOrder<T> Compare = Aleph::less<T>,
class BucketKey>
5825 const Compare &
cmp = Compare())
5827 bucket_sort_detail::apply_sort_with_temp<T>(
5843template <
typename T, StrictWeakOrder<T> Compare = Aleph::less<T>,
class BucketKey>
5845 const Compare &
cmp = Compare())
5856namespace timsort_detail {
5877template <
typename T>
5878void reverse_range(
T *a,
size_t lo,
size_t hi)
noexcept(std::is_nothrow_swappable_v<T>)
5882 std::swap(a[lo], a[hi - 1]);
5896template <
typename T,
class Compare>
5923template <
typename T,
class Compare>
5925 T *a,
const size_t lo,
const size_t hi,
const size_t start,
5926 const Compare &
cmp)
noexcept(std::is_nothrow_move_constructible_v<T>
and
5927 std::is_nothrow_move_assignable_v<T>
and
5928 noexcept(std::declval<const Compare &>()(std::declval<const T &>(),
5929 std::declval<const T &>())))
5932 size_t i = (start <= lo) ? lo + 1 : start;
5935 T pivot = std::move(a[i]);
5940 while (left < right)
5942 const size_t mid = left + (right - left) / 2;
5950 for (
size_t p = i; p > left; --p)
5951 a[p] = std::move(a[p - 1]);
5952 a[left] = std::move(
pivot);
5973template <
typename T,
class Compare>
5975 const T &key,
const T *a,
const size_t len,
const size_t hint,
5976 const Compare &
cmp)
noexcept(
noexcept(std::declval<const Compare &>()(std::declval<const T &>(),
5977 std::declval<const T &>())))
6042template <
typename T,
class Compare>
6044 const T &key,
const T *a,
const size_t len,
const size_t hint,
6045 const Compare &
cmp)
noexcept(
noexcept(std::declval<const Compare &>()(std::declval<const T &>(),
6046 std::declval<const T &>())))
6100template <
typename T,
class Compare>
6105 for (
size_t i = 0; i <
len1; ++i)
6116 a[
dest++] = std::move(a[
c2++]);
6130template <
typename T,
class Compare>
6135 for (
size_t i = 0; i <
len2; ++i)
6145 a[--
dest] = std::move(a[--
c1]);
6160template <
typename T,
class Compare>
6203template <
typename T,
class Compare>
6225template <
typename T,
class Compare>
6252template <
typename T,
class Compare>
6281 size_t remaining = n;
6283 while (remaining > 0)
6298 <<
"timsort: run stack overflow (stack_size=" <<
stack_size <<
" >= MAX_STACK=" <<
MAX_STACK
6299 <<
"); this should never happen";
6343template <
typename T, StrictWeakOrder<T> Compare = Aleph::less<T>>
6370template <
typename T, StrictWeakOrder<T> Compare = Aleph::less<T>>
6374 <<
"timsort(): negative bounds [" <<
l <<
", " <<
r <<
"] are not allowed";
6380 <<
"timsort(): null pointer contract violation for range [" <<
l <<
", " <<
r
6381 <<
"]; cannot call timsort_detail::timsort_impl()";
6396template <
typename T, StrictWeakOrder<T> Compare = Aleph::less<T>>
6399 bucket_sort_detail::apply_sort_with_temp<T>(
6415template <
typename T, StrictWeakOrder<T> Compare = Aleph::less<T>>
6433template <
typename T,
size_t N, StrictWeakOrder<T> Compare = Aleph::less<T>>
6434 requires std::is_invocable_r_v<bool, Compare, const T &, const T &>
6452template <
typename T, StrictWeakOrder<T> Compare = Aleph::less<T>>
6455 bucket_sort_detail::apply_sort_with_temp<T>(
6474template <
typename T, StrictWeakOrder<T> Compare = Aleph::less<T>>
6477 bucket_sort_detail::apply_sort_with_temp<T>(
C++20 concepts hub: comparison, BST policy, and Aleph container concepts.
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.
size_t size_t int32_t value
size_t size_t int32_t * out
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.
void putn(const size_t n)
Reserve n additional logical slots in the array without value-initializing them.
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 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.
Doubly-linked list (defined in tpl_dynList.H).
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.
__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)
size_t blossom_maximum_cardinality_matching(const GT &g, DynDlist< typename GT::Arc * > &matching, SA sa=SA())
Alias of compute_maximum_cardinality_general_matching().
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.
void radix_sort_impl(C< IntT > &a)
Internal radix-sort implementation for array-like containers.
constexpr radix_unsigned_t< IntT > radix_key(const IntT value) noexcept
Map an integer value to an unsigned radix key.
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
Unsigned counterpart used to measure counting-sort key ranges.
std::make_unsigned_t< std::remove_cv_t< IntT > > radix_unsigned_t
Unsigned key type used by radix sort passes.
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 counting_sort_impl(C< IntT > &a)
Internal implementation of counting sort for containers.
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.
Array< const T * > build_index_ptr(const C< T > &a, const Compare &cmp=Compare())
Build an index array of pointers for indirect sorting (const version).
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.
Array< const T * > stable_build_index_ptr(const C< T > &a, const Compare &cmp=Compare())
Build a stable index array of pointers for indirect sorting (const version).
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.
void heapsort(T *array, const size_t n, const Compare &cmp=Compare())
Sort an array using the heapsort algorithm.
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.
void faster_heapsort(T *array, const size_t n, const Compare &cmp=Compare())
Optimized version of heapsort.
Dnode< T > * dlink_random_search(Dlink &list, const T &x, const Compare &cmp=Compare())
Random search for an element in a dlink list.
Array< size_t > stable_build_index(const C &a, const Compare &cmp=Compare())
Build a stable index array for indirect sorting.
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.
and
Check uniqueness with explicit hash + equality functors.
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.
Array< size_t > build_index(const C &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 mergesort(T *a, const long l, const long r, Array< T > &buf, Compare cmp)
Sort an array using merge sort with a reusable buffer.
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)
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.