56template <
typename RandomAccessIt,
typename Compare = std::less<>>
58 const RandomAccessIt begin,
const RandomAccessIt end,
60 = {})
noexcept(
noexcept(
swap(*begin, *begin)) and
noexcept(compare(*begin,
64 if (end - begin <= 1) {
67 for (
auto pos = begin + 1; pos != end; ++pos) {
70 auto index =
kblib::find_if(begin, pos, [&compare, pos](
const auto&
a) {
71 return compare(*pos,
a);
91template <
typename RandomAccessIt,
typename RandomAccessIt2,
92 typename Compare = std::less<>>
94 const RandomAccessIt begin,
const RandomAccessIt end,
95 const RandomAccessIt2 d_begin,
const RandomAccessIt2 d_end,
97 = {})
noexcept(
noexcept(detail_algorithm::
99 d_end)) and
noexcept(*d_begin
102 const auto dist = end - begin;
103 assert(end - begin == d_end - d_begin);
106 }
else if (dist == 1) {
110 }
else if (dist == 2) {
113 if (compare(*begin, *(begin + 1))) {
115 *(d_begin + 1) = *(begin + 1);
118 *d_begin = *(begin + 1);
119 *(d_begin + 1) = *begin;
126 auto read = std::prev(end);
127 auto write = std::prev(d_end);
138 [&compare, read](
const auto&
a) {
return not compare(
a, *read); });
141 [&compare, read](
const auto&
a) {
145 return compare(*read,
a);
149 return ! compare(
a, *read);
154 *(index - 1) = *read;
155 }
while (write != d_begin);
176template <
typename RandomAccessIt,
typename RandomAccessIt2,
177 typename Compare = std::less<>>
179 const RandomAccessIt begin,
const RandomAccessIt end,
180 const RandomAccessIt2 d_begin,
const RandomAccessIt2 d_end,
182 = {})
noexcept(
noexcept(detail_algorithm::
184 d_end)) and
noexcept(*d_begin
187 const auto dist = end - begin;
191 std::forward<Compare>(compare));
198 +
static_cast<std::ptrdiff_t
>(std::sqrt(
static_cast<float>(dist)));
199 std::ptrdiff_t dir{};
200 for (
auto pos = begin; pos != scan_end - 1; ++pos) {
201 if (compare(*pos, *(pos + 1))) {
203 }
else if (compare(*(pos + 1), *pos)) {
209 std::forward<Compare>(compare));
214 std::make_reverse_iterator(begin), d_begin, d_end,
215 std::forward<Compare>(compare));
219template <
typename T,
typename =
void>
230template <std::
size_t B>
236 T> and
std::is_integral<typename T::value_type>::value>>
245 = std::is_same<typename std::remove_cv<T>::type, std::byte>::value;
255 =
kblib::div(kblib::bits_of<T> + std::is_signed<T>::value, CHAR_BIT);
260 -> enable_if_t<std::is_enum<T>::value, std::size_t> {
261 using U =
typename std::underlying_type<T>::type;
263 =
kblib::div(kblib::bits_of<U> + std::is_signed<U>::value, CHAR_BIT);
277 is_linear_container_v<
278 T> and (std::is_integral<typename T::value_type>::value or is_byte_v<T>)
279 and
sizeof(
typename T::value_type) == 1,
285 is_linear_container_v<T> and std::is_integral<typename T::value_type>::value
286 and (
sizeof(
typename T::value_type) > 1),
288 using value_type =
typename T::value_type;
301 return static_cast<unsigned char>(x >> (idx * CHAR_BIT));
305 std::size_t idx)
noexcept
307 return static_cast<unsigned char>(
etoi(x) >> (idx * CHAR_BIT));
318 std::size_t idx)
noexcept ->
unsigned char {
324 is_linear_container_v<
325 T> and (std::is_integral<typename T::value_type>::value or is_byte_v<T>)
326 and
sizeof(
typename T::value_type) == 1,
328 return static_cast<unsigned char>(x[idx]);
332 std::size_t idx)
noexcept
334 T> and std::is_integral<typename T::value_type>::value
335 and (
sizeof(
typename T::value_type) > 1),
337 using value_type =
typename T::value_type;
339 return static_cast<unsigned char>(
to_unsigned(x[idx / bytes_per])
340 >> (idx % bytes_per * CHAR_BIT));
344 std::size_t idx)
noexcept
346 T> and std::is_enum<typename T::value_type>::value,
348 using U =
typename std::underlying_type<typename T::U>::type;
350 return static_cast<unsigned char>(
to_unsigned(
etoi(x[idx / bytes_per]))
351 >> (idx % bytes_per * CHAR_BIT));
361namespace detail_sort {
363 template <
typename RandomAccessIt,
typename Compare>
364 constexpr auto sort(RandomAccessIt,
const RandomAccessIt, Compare) ->
void {}
365 template <
typename RandomAccessIt,
typename Compare>
366 constexpr auto stable_sort(RandomAccessIt,
const RandomAccessIt, Compare)
369 template <
typename RandomAccessIt,
typename Compare, std::
size_t small_size>
370 constexpr auto merge_sort(RandomAccessIt begin,
const RandomAccessIt end,
371 Compare cmp) ->
void {
372 if (end - begin <= small_size) {
376 auto middle = begin + (end - begin) / 2;
379 std::inplace_merge(begin, middle, end, cmp);
384 template <
typename RandomAccessIt,
typename Compare, std::
size_t small_size>
385 constexpr auto heap_sort(RandomAccessIt begin,
const RandomAccessIt end,
386 Compare cmp) ->
void {
387 std::make_heap(begin, end, cmp);
388 while (begin != end) {
389 std::pop_heap(begin, end--, cmp);
396 template <sort_direction dir,
typename RandomAccessIt,
typename Projection>
397 constexpr auto radix_sort_i(RandomAccessIt begin,
const RandomAccessIt end,
398 Projection proj) ->
void {
399 using E =
decay_t<
decltype(proj(*begin))>;
401 for (
const auto byte :
range(max_bytes)) {
402 for (
auto it = begin; it != end; ++it) {
406 template <sort_direction dir,
typename RandomAccessIt,
typename Projection>
407 constexpr auto radix_sort_s(RandomAccessIt begin,
const RandomAccessIt end,
408 Projection proj) ->
void {
411 begin, end, std::size_t{}, [&](
auto m,
const auto& el) {
415 const auto max_bytes = [&] {
416 std::size_t max_bytes{};
417 for (
const auto v :
indirect(begin, end)) {
424 template <std::
size_t size>
429 template <std::
size_t size>
436 typename RandomAccessIt2,
typename Projection>
438 const RandomAccessIt1 end,
439 RandomAccessIt2 d_begin, Projection proj)
441 using E =
decay_t<
decltype(proj(*begin))>;
442 constexpr auto size = std::numeric_limits<std::make_unsigned_t<E>>
::max();
445 for (
auto cur = begin; cur != end; ++cur) {
446 ++count->at(proj(*cur));
449 std::size_t{}, std::plus<>{}, proj);
451 for (
auto cur = end; cur != begin; --cur) {
452 auto el = std::prev(cur);
453 d_begin[--count->at(proj(*el))] = *el;
464 template <
typename RandomAccessIt,
typename UnaryOperation,
465 typename BinaryPredicate,
typename SortKey,
466 std::size_t small_size = 8,
468 bool = std::is_fundamental<SortKey>::value,
469 bool = is_radix_sortable_v<SortKey>,
470 bool = std::is_integral<SortKey>::value>
472 static constexpr auto inplace(RandomAccessIt begin,
473 const RandomAccessIt end,
475 BinaryPredicate&& compare) ->
void {
477 = [&compare, &
transform](RandomAccessIt
a, RandomAccessIt b) {
481 if (end - begin < small_size) {
489 static constexpr auto scratch(RandomAccessIt begin,
490 const RandomAccessIt end,
492 BinaryPredicate&& compare) ->
void {
494 = [&compare, &
transform](RandomAccessIt
a, RandomAccessIt b) {
498 if (end - begin < small_size) {
506 template <
typename RandomAccessIt2>
507 static constexpr auto copy(RandomAccessIt begin,
const RandomAccessIt end,
508 RandomAccessIt2 d_begin, RandomAccessIt2 d_end,
510 BinaryPredicate&& compare) ->
void {
512 = [&compare, &
transform](RandomAccessIt
a, RandomAccessIt b) {
516 if (end - begin < small_size) {
531 template <
typename RandomAccessIt,
typename UnaryOperation,
532 typename BinaryPredicate,
typename SortKey, std::size_t small_size>
534 SortKey, small_size, true, false, false, false> {
541 = [&compare, &
transform](RandomAccessIt
a, RandomAccessIt b) {
555 template <
typename RandomAccessIt,
typename UnaryOperation,
typename LessT,
556 typename SortKey, std::size_t small_size>
558 SortKey, small_size, true, true, false, false> {
572 template <
typename RandomAccessIt,
typename UnaryOperation,
typename LessT,
573 typename SortKey, std::size_t small_size>
575 std::greater<LessT>, SortKey, small_size, true,
576 true, false, false> {
590 template <
typename RandomAccessIt,
typename UnaryOperation,
typename LessT,
591 typename SortKey, std::size_t small_size>
593 SortKey, small_size, true, true, true, true> {
606 template <
typename RandomAccessIt,
typename UnaryOperation,
typename LessT,
607 typename SortKey, std::size_t small_size>
609 std::greater<LessT>, SortKey, small_size, true,
625 template <typename RandomAccessIt, typename UnaryOperation, typename LessT,
626 typename SortKey, std::size_t small_size,
bool M>
628 SortKey, small_size, M, false, true, false> {
641 template <
typename RandomAccessIt,
typename UnaryOperation,
typename LessT,
642 typename SortKey, std::size_t small_size,
bool M>
644 std::greater<LessT>, SortKey, small_size, M,
645 false, true, false> {
672template <
typename RandomAccessIt,
typename UnaryOperation,
673 typename BinaryPredicate>
676 BinaryPredicate&& compare) ->
void {
678 RandomAccessIt, UnaryOperation, BinaryPredicate,
680 inplace(begin, end, std::forward<UnaryOperation>(
transform),
681 std::forward<BinaryPredicate>(compare));
690template <
typename RandomAccessIt,
typename UnaryOperation>
694 RandomAccessIt, UnaryOperation, std::less<>,
696 *begin))>::inplace(begin, end,
697 std::forward<UnaryOperation>(
714template <
typename RandomAccessIt,
typename BinaryPredicate>
715constexpr auto sort(RandomAccessIt begin, RandomAccessIt end,
716 BinaryPredicate&& compare) ->
void {
718 RandomAccessIt,
identity, BinaryPredicate,
720 *begin))>::inplace(begin, end,
identity{},
721 std::forward<BinaryPredicate>(
730template <
typename RandomAccessIt>
731constexpr auto sort(RandomAccessIt begin, RandomAccessIt end) ->
void {
733 RandomAccessIt,
identity, std::less<>,
Provides general-purpose algorithms, similar to the <algorithms> header.
Provides bit-manipulation functions and classes.
This header provides some features of C++17 <type_traits> and other headers for C++14,...
constexpr auto shift_backward(ForwardIt first, ForwardIt n_first, ForwardIt last) noexcept(noexcept(*first=std::move(*first))) -> void
Implementation function for insertion_sort_copy. Like std::move(begin, end, d_begin) but using the in...
constexpr auto merge_sort(RandomAccessIt begin, const RandomAccessIt end, Compare cmp) -> void
constexpr auto counting_sort(RandomAccessIt1 begin, const RandomAccessIt1 end, RandomAccessIt2 d_begin, Projection proj) -> void
constexpr auto radix_sort_i(RandomAccessIt begin, const RandomAccessIt end, Projection proj) -> void
constexpr auto heap_sort(RandomAccessIt begin, const RandomAccessIt end, Compare cmp) -> void
constexpr auto radix_sort_s(RandomAccessIt begin, const RandomAccessIt end, Projection proj) -> void
auto make_array_for(std::true_type) -> kblib::heap_value< std::array< std::size_t, size+1 > >
constexpr auto stable_sort(RandomAccessIt, const RandomAccessIt, Compare) -> void
constexpr auto size(const C &c) -> decltype(c.size())
constexpr struct kblib::nums::max_t max
constexpr auto a(const std::initializer_list< T > &a) -> auto
Index an array literal without naming its type.
typename std::enable_if< B, T >::type enable_if_t
constexpr auto sort(RandomAccessIt begin, RandomAccessIt end) -> void
constexpr auto insertion_sort(const RandomAccessIt begin, const RandomAccessIt end, Compare &&compare={}) noexcept(noexcept(swap(*begin, *begin)) and noexcept(compare(*begin, *begin))) -> void
In-place insertion sort. As is usual, it is stable. Provides as a guarantee that it will perform no m...
constexpr auto sort_transform(RandomAccessIt begin, RandomAccessIt end, UnaryOperation &&transform) -> void
constexpr auto find_if(ForwardIt begin, EndIt end, UnaryPredicate &&pred) noexcept(noexcept(kblib::invoke(pred, *begin))) -> ForwardIt
Finds the first value in range [begin, end) for which pred returns true. If not found,...
constexpr auto insertion_sort_copy(const RandomAccessIt begin, const RandomAccessIt end, const RandomAccessIt2 d_begin, const RandomAccessIt2 d_end, Compare &&compare={}) noexcept(noexcept(detail_algorithm::shift_backward(d_begin, d_begin, d_end)) and noexcept(*d_begin= *begin)) -> void
Out-of-place insertion sort, which does not modify the input. Provides as a guarantee that it will pe...
constexpr auto adaptive_insertion_sort_copy(const RandomAccessIt begin, const RandomAccessIt end, const RandomAccessIt2 d_begin, const RandomAccessIt2 d_end, Compare &&compare={}) noexcept(noexcept(detail_algorithm::shift_backward(d_begin, d_begin, d_end)) and noexcept(*d_begin= *begin)) -> void
An adaptive sort which, at the cost of some additional work (time complexity Θ(sqrt(n))),...
constexpr auto range(Value min, Value max, Delta step=0) -> range_t< Value, Delta >
Constructs a range from beginning, end, and step amount. The range is half-open, that is min is in th...
constexpr auto byte_count(...) -> void=delete
constexpr auto indirect(Iter1 begin, Iter2 end) noexcept(noexcept(indirect_range< Iter1, Iter2 >{begin, end})) -> indirect_range< Iter1, Iter2 >
Create a range from an iterator pair. Primarily useful for range-for loops.
constexpr auto invoke(F &&f, Args &&... args) noexcept(noexcept(detail::do_invoke(std::forward< F >(f), std::forward< Args >(args)...))) -> decltype(auto)
typename std::decay< T >::type decay_t
constexpr auto transform_exclusive_scan(InputIt first, EndIt last, OutputIt d_first, T init, BinaryAccumulation accum, UnaryTransform proj) -> OutputIt
std::integral_constant< bool, v > bool_constant
typename void_if< b >::type void_if_t
constexpr bool is_radix_sortable_v
constexpr auto div(T num, U den) noexcept -> decltype(std::div(num, den))
constexpr auto rotate(ForwardIt first, ForwardIt n_first, ForwardIt last) noexcept(noexcept(swap(*first, *first))) -> ForwardIt
Rotates the input range. This is just a constexpr-in-C++14 version of std::rotate.
constexpr auto accumulate(InputIt first, InputIt last, T init) -> T
A constexpr version of std::accumulate.
auto get_byte_index(const std::unique_ptr< T > &x, std::size_t idx) noexcept -> unsigned char
constexpr auto etoi(E e) -> auto
constexpr struct kblib::in_place_agg_t in_place_agg
constexpr auto to_unsigned(I x) -> std::make_unsigned_t< I >
Cast integral argument to corresponding unsigned type.
constexpr auto transform(InputIt first, EndIt last, OutputIt d_first, UnaryOperation unary_op) -> OutputIt
transform applies the given function to a range and stores the result in another range,...
Provides general utilities which do not fit in any more specific header.
A smart pointer to an object contained inside the smart pointer object.
The identity function, as a function object.
#define KBLIB_UNUSED
This internal macro is used to provide a fallback for [[maybe_unused]] in C++14.
#define KBLIB_NODISCARD
This internal macro is used to provide a fallback for [[nodiscard]] in C++14.