[libcxx-commits] [libcxx] [libcxx][algorithm] Optimize std::stable_sort via radix sort algorithm (PR #104683)

Дмитрий Изволов via libcxx-commits libcxx-commits at lists.llvm.org
Mon Nov 11 23:31:04 PST 2024


https://github.com/izvolov updated https://github.com/llvm/llvm-project/pull/104683

>From e4bfe792056eecdf3db35b32b94630c66cc96ab4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=94=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9=20=D0=98=D0=B7?=
 =?UTF-8?q?=D0=B2=D0=BE=D0=BB=D0=BE=D0=B2?= <dmitriy at izvolov.ru>
Date: Sun, 5 May 2024 11:08:26 +0300
Subject: [PATCH 01/46] radix-sort

---
 libcxx/include/CMakeLists.txt            |   1 +
 libcxx/include/__algorithm/radix_sort.h  | 410 +++++++++++++++++++++++
 libcxx/include/__algorithm/stable_sort.h | 111 ++++--
 3 files changed, 490 insertions(+), 32 deletions(-)
 create mode 100644 libcxx/include/__algorithm/radix_sort.h

diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index dd774b25a81eda..5ebeec597c15ed 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -73,6 +73,7 @@ set(files
   __algorithm/prev_permutation.h
   __algorithm/pstl.h
   __algorithm/push_heap.h
+  __algorithm/radix_sort.h
   __algorithm/ranges_adjacent_find.h
   __algorithm/ranges_all_of.h
   __algorithm/ranges_any_of.h
diff --git a/libcxx/include/__algorithm/radix_sort.h b/libcxx/include/__algorithm/radix_sort.h
new file mode 100644
index 00000000000000..5e14dec9df0918
--- /dev/null
+++ b/libcxx/include/__algorithm/radix_sort.h
@@ -0,0 +1,410 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP___ALGORITHM_RADIX_SORT_H
+#define _LIBCPP___ALGORITHM_RADIX_SORT_H
+
+#include <__algorithm/copy.h>
+#include <__algorithm/for_each.h>
+#include <__config>
+#include <__iterator/iterator_traits.h>
+#include <__iterator/move_iterator.h>
+#include <__iterator/next.h>
+#include <__numeric/partial_sum.h>
+#include <__type_traits/decay.h>
+#include <__type_traits/enable_if.h>
+#include <__type_traits/invoke.h>
+#include <__type_traits/is_assignable.h>
+#include <__type_traits/is_integral.h>
+#include <__type_traits/is_unsigned.h>
+#include <__type_traits/make_unsigned.h>
+#include <__utility/forward.h>
+#include <__utility/integer_sequence.h>
+#include <__utility/move.h>
+#include <__utility/pair.h>
+#include <climits>
+#include <cstdint>
+#include <initializer_list>
+#include <limits>
+#include <stdexcept>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#  pragma GCC system_header
+#endif
+
+_LIBCPP_PUSH_MACROS
+#include <__undef_macros>
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+#if _LIBCPP_STD_VER > 14
+
+inline void __variadic_expansion_dummy(initializer_list<int>) {}
+
+#  define EXPAND_VARIADIC(expression) __variadic_expansion_dummy({(expression, 0)...})
+
+template <typename _Iterator>
+constexpr auto __move_assign_please(_Iterator __i)
+    -> enable_if_t<is_move_assignable<typename iterator_traits<_Iterator>::value_type>::value,
+                   move_iterator<_Iterator> > {
+  return make_move_iterator(std::move(__i));
+}
+
+template <typename _Iterator>
+constexpr auto __move_assign_please(_Iterator __i)
+    -> enable_if_t<not is_move_assignable<typename iterator_traits<_Iterator>::value_type>::value, _Iterator> {
+  return __i;
+}
+
+template <typename _Integer>
+constexpr _Integer __intlog2_impl(_Integer __integer) {
+  auto __degree = _Integer{0};
+
+  while ((__integer >>= 1) > 0) {
+    ++__degree;
+  }
+
+  return __degree;
+}
+
+template <typename _Integer>
+constexpr _Integer __intlog2(_Integer __integer) {
+  static_assert(is_integral<_Integer>::value, "Must be an integral type");
+
+  return __integer > 0 ? __intlog2_impl(__integer)
+                       : throw domain_error("The binary logarithm is not defined on non-positive numbers");
+}
+
+template <typename _InputIterator, typename _OutputIterator>
+pair<_OutputIterator, typename iterator_traits<_InputIterator>::value_type>
+__partial_sum_max(_InputIterator __first, _InputIterator __last, _OutputIterator __result) {
+  if (__first == __last)
+    return {__result, 0};
+
+  auto __max                                                 = *__first;
+  typename iterator_traits<_InputIterator>::value_type __sum = *__first;
+  *__result                                                  = __sum;
+
+  while (++__first != __last) {
+    if (__max < *__first) {
+      __max = *__first;
+    }
+    __sum       = std::move(__sum) + *__first;
+    *++__result = __sum;
+  }
+  return {++__result, __max};
+}
+
+template <typename _Value, typename _Map, typename _Radix>
+struct __radix_sort_traits {
+  using image_type = decay_t<invoke_result_t<_Map, _Value> >;
+  static_assert(is_integral<image_type>::value, "");
+  static_assert(is_unsigned<image_type>::value, "");
+
+  using radix_type = decay_t<invoke_result_t<_Radix, image_type> >;
+  static_assert(is_integral<radix_type>::value, "");
+
+  constexpr static auto radix_value_range = numeric_limits<radix_type>::max() + 1;
+  constexpr static auto radix_size        = __intlog2<uint64_t>(radix_value_range);
+  constexpr static auto radix_count       = sizeof(image_type) * CHAR_BIT / radix_size;
+};
+
+template <typename _Value, typename _Map>
+struct __counting_sort_traits {
+  using image_type = decay_t<invoke_result_t<_Map, _Value> >;
+  static_assert(is_integral<image_type>::value, "");
+  static_assert(is_unsigned<image_type>::value, "");
+
+  constexpr static const auto value_range = numeric_limits<image_type>::max() + 1;
+  constexpr static auto radix_size        = __intlog2<uint64_t>(value_range);
+};
+
+template <typename _Radix>
+auto __nth_radix(size_t __radix_number, _Radix __radix) {
+  return [__radix_number, __radix = std::move(__radix)](auto __n) {
+    using value_type = decltype(__n);
+    static_assert(is_integral<value_type>::value, "");
+    static_assert(is_unsigned<value_type>::value, "");
+    using traits = __counting_sort_traits<value_type, _Radix>;
+
+    return __radix(static_cast<value_type>(__n >> traits::radix_size * __radix_number));
+  };
+}
+
+template <typename _ForwardIterator, typename _Map, typename _RandomAccessIterator>
+void __count(_ForwardIterator __first, _ForwardIterator __last, _Map __map, _RandomAccessIterator __counters) {
+  std::for_each(__first, __last, [&__counters, &__map](const auto& __preimage) { ++__counters[__map(__preimage)]; });
+}
+
+template <typename _ForwardIterator, typename _Map, typename _RandomAccessIterator>
+void __collect(_ForwardIterator __first, _ForwardIterator __last, _Map __map, _RandomAccessIterator __counters) {
+  using value_type = typename iterator_traits<_ForwardIterator>::value_type;
+  using traits     = __counting_sort_traits<value_type, _Map>;
+
+  __count(__first, __last, __map, __counters);
+
+  const auto __counters_end = __counters + traits::value_range;
+  partial_sum(__counters, __counters_end, __counters);
+}
+
+template <typename _ForwardIterator, typename _RandomAccessIterator1, typename _Map, typename _RandomAccessIterator2>
+void __dispose(_ForwardIterator __first,
+               _ForwardIterator __last,
+               _RandomAccessIterator1 __result,
+               _Map __map,
+               _RandomAccessIterator2 __counters) {
+  std::for_each(__first, __last, [&__result, &__counters, &__map](auto&& __preimage) {
+    auto __index      = __counters[__map(__preimage)]++;
+    __result[__index] = std::forward<decltype(__preimage)>(__preimage);
+  });
+}
+
+template <typename _BidirectionalIterator,
+          typename _RandomAccessIterator1,
+          typename _Map,
+          typename _RandomAccessIterator2>
+void dispose_backward(_BidirectionalIterator __first,
+                      _BidirectionalIterator __last,
+                      _RandomAccessIterator1 __result,
+                      _Map __map,
+                      _RandomAccessIterator2 __counters) {
+  std::for_each(make_reverse_iterator(__last),
+                make_reverse_iterator(__first),
+                [&__result, &__counters, &__map](auto&& __preimage) {
+                  auto __index      = --__counters[__map(__preimage)];
+                  __result[__index] = std::forward<decltype(__preimage)>(__preimage);
+                });
+}
+
+template <typename _ForwardIterator,
+          typename _Map,
+          typename _Radix,
+          typename _RandomAccessIterator1,
+          typename _RandomAccessIterator2,
+          size_t... _Radices>
+bool __collect_impl(
+    _ForwardIterator __first,
+    _ForwardIterator __last,
+    _Map __map,
+    _Radix __radix,
+    _RandomAccessIterator1 __counters,
+    _RandomAccessIterator2 __maximums,
+    index_sequence<_Radices...>) {
+  using value_type                   = typename iterator_traits<_ForwardIterator>::value_type;
+  constexpr auto __radix_value_range = __radix_sort_traits<value_type, _Map, _Radix>::radix_value_range;
+
+  auto __previous  = numeric_limits<invoke_result_t<_Map, value_type> >::min();
+  auto __is_sorted = true;
+  for_each(__first, __last, [&__counters, &__map, &__radix, &__previous, &__is_sorted](const auto& value) {
+    auto __current = __map(value);
+    __is_sorted &= (__current >= __previous);
+    __previous = __current;
+
+    EXPAND_VARIADIC(++__counters[_Radices][__nth_radix(_Radices, __radix)(__current)]);
+  });
+
+  EXPAND_VARIADIC(
+      __maximums[_Radices] =
+          __partial_sum_max(__counters[_Radices], __counters[_Radices] + __radix_value_range, __counters[_Radices])
+              .second);
+
+  return __is_sorted;
+}
+
+template <typename _ForwardIterator,
+          typename _Map,
+          typename _Radix,
+          typename _RandomAccessIterator1,
+          typename _RandomAccessIterator2>
+bool __collect(_ForwardIterator __first,
+               _ForwardIterator __last,
+               _Map __map,
+               _Radix __radix,
+               _RandomAccessIterator1 __counters,
+               _RandomAccessIterator2 __maximums) {
+  using value_type             = typename iterator_traits<_ForwardIterator>::value_type;
+  constexpr auto __radix_count = __radix_sort_traits<value_type, _Map, _Radix>::radix_count;
+  return __collect_impl(__first, __last, __map, __radix, __counters, __maximums, make_index_sequence<__radix_count>());
+}
+
+template <typename _BidirectionalIterator,
+          typename _RandomAccessIterator1,
+          typename _Map,
+          typename _RandomAccessIterator2>
+void __dispose_backward(_BidirectionalIterator __first,
+                        _BidirectionalIterator __last,
+                        _RandomAccessIterator1 __result,
+                        _Map __map,
+                        _RandomAccessIterator2 __counters) {
+  for_each(
+      make_reverse_iterator(__last), make_reverse_iterator(__first), [&__result, &__counters, &__map](auto&& preimage) {
+        auto __index      = --__counters[__map(preimage)];
+        __result[__index] = std::forward<decltype(preimage)>(preimage);
+      });
+}
+
+template <typename _ForwardIterator, typename _RandomAccessIterator, typename _Map>
+_RandomAccessIterator
+__counting_sort_impl(_ForwardIterator __first, _ForwardIterator __last, _RandomAccessIterator __result, _Map __map) {
+  using value_type = typename iterator_traits<_ForwardIterator>::value_type;
+  using traits     = __counting_sort_traits<value_type, _Map>;
+
+  using difference_type = typename iterator_traits<_RandomAccessIterator>::difference_type;
+  difference_type __counters[traits::value_range + 1] = {0};
+
+  __collect(__first, __last, __map, next(std::begin(__counters)));
+  __dispose(__first, __last, __result, __map, std::begin(__counters));
+
+  return __result + __counters[traits::value_range];
+}
+
+template <typename _RandomAccessIterator1, typename _RandomAccessIterator2, typename _Map, typename _Radix>
+typename enable_if<
+    __radix_sort_traits<typename iterator_traits<_RandomAccessIterator1>::value_type, _Map, _Radix>::radix_count == 1,
+    void>::type
+__radix_sort_impl(_RandomAccessIterator1 __first,
+                  _RandomAccessIterator1 __last,
+                  _RandomAccessIterator2 buffer,
+                  _Map __map,
+                  _Radix __radix) {
+  auto __buffer_end = __counting_sort_impl(
+      __move_assign_please(__first), __move_assign_please(__last), buffer, [&__map, &__radix](const auto& value) {
+        return __radix(__map(value));
+      });
+
+  std::copy(__move_assign_please(buffer), __move_assign_please(__buffer_end), __first);
+}
+
+template <typename _RandomAccessIterator1, typename _RandomAccessIterator2, typename _Map, typename _Radix>
+typename enable_if<
+    __radix_sort_traits<typename iterator_traits<_RandomAccessIterator1>::value_type, _Map, _Radix>::radix_count % 2 ==
+        0,
+    void>::type
+__radix_sort_impl(_RandomAccessIterator1 __first,
+                  _RandomAccessIterator1 __last,
+                  _RandomAccessIterator2 __buffer_begin,
+                  _Map __map,
+                  _Radix __radix) {
+  using value_type = typename iterator_traits<_RandomAccessIterator1>::value_type;
+  using traits     = __radix_sort_traits<value_type, _Map, _Radix>;
+
+  using difference_type = typename iterator_traits<_RandomAccessIterator1>::difference_type;
+  difference_type __counters[traits::radix_count][traits::radix_value_range] = {{0}};
+  difference_type __maximums[traits::radix_count]                            = {0};
+  const auto __is_sorted = __collect(__first, __last, __map, __radix, __counters, __maximums);
+  if (not __is_sorted) {
+    const auto __range_size = distance(__first, __last);
+    auto __buffer_end       = __buffer_begin + __range_size;
+    for (size_t __radix_number = 0; __radix_number < traits::radix_count; __radix_number += 2) {
+      const auto __n0th_is_single = __maximums[__radix_number] == __range_size;
+      const auto __n1th_is_single = __maximums[__radix_number + 1] == __range_size;
+
+      if (__n0th_is_single && __n1th_is_single) {
+        continue;
+      }
+
+      if (__n0th_is_single) {
+        copy(__move_assign_please(__first), __move_assign_please(__last), __buffer_begin);
+      } else {
+        auto __n0th = [__radix_number, &__map, &__radix](const auto& __v) {
+          return __nth_radix(__radix_number, __radix)(__map(__v));
+        };
+        __dispose_backward(
+            __move_assign_please(__first),
+            __move_assign_please(__last),
+            __buffer_begin,
+            __n0th,
+            __counters[__radix_number]);
+      }
+
+      if (__n1th_is_single) {
+        copy(__move_assign_please(__buffer_begin), __move_assign_please(__buffer_end), __first);
+      } else {
+        auto __n1th = [__radix_number, &__map, &__radix](const auto& __v) {
+          return __nth_radix(__radix_number + 1, __radix)(__map(__v));
+        };
+        __dispose_backward(
+            __move_assign_please(__buffer_begin),
+            __move_assign_please(__buffer_end),
+            __first,
+            __n1th,
+            __counters[__radix_number + 1]);
+      }
+    }
+  }
+}
+
+constexpr auto __to_unsigned(bool __b) { return __b; }
+
+template <typename _Ip>
+constexpr auto __to_unsigned(_Ip __n) {
+  constexpr const auto __min_value = numeric_limits<_Ip>::min();
+  return static_cast<make_unsigned_t<_Ip> >(__n ^ __min_value);
+}
+
+struct __identity_fn {
+  template <typename _Tp>
+  constexpr decltype(auto) operator()(_Tp&& __value) const {
+    return std::forward<_Tp>(__value);
+  }
+};
+
+struct __low_byte_fn {
+  template <typename _Ip>
+  constexpr uint8_t operator()(_Ip __integer) const {
+    static_assert(is_integral<_Ip>::value, "");
+    static_assert(is_unsigned<_Ip>::value, "");
+
+    return static_cast<uint8_t>(__integer & 0xff);
+  }
+};
+
+template <typename _RandomAccessIterator1, typename _RandomAccessIterator2, typename _Map, typename _Radix>
+void __radix_sort(_RandomAccessIterator1 __first,
+                  _RandomAccessIterator1 __last,
+                  _RandomAccessIterator2 buffer,
+                  _Map __map,
+                  _Radix __radix) {
+  auto __map_to_unsigned = [__map = std::move(__map)](const auto& x) { return __to_unsigned(__map(x)); };
+  __radix_sort_impl(__first, __last, buffer, __map_to_unsigned, __radix);
+}
+
+template <typename _RandomAccessIterator1, typename _RandomAccessIterator2>
+void __radix_sort(_RandomAccessIterator1 __first, _RandomAccessIterator1 __last, _RandomAccessIterator2 buffer) {
+  __radix_sort(__first, __last, buffer, __identity_fn{}, __low_byte_fn{});
+}
+
+template <typename _RandomAccessIterator1, typename _RandomAccessIterator2>
+bool __radix_sort(
+    _RandomAccessIterator1 __first, _RandomAccessIterator1 __last, _RandomAccessIterator2 buffer, _BoolConstant<true>) {
+  __radix_sort(__first, __last, buffer, __identity_fn{}, __low_byte_fn{});
+  return true;
+}
+
+template <typename _RandomAccessIterator1, typename _RandomAccessIterator2>
+bool __radix_sort(_RandomAccessIterator1, _RandomAccessIterator1, _RandomAccessIterator2, _BoolConstant<false>) {
+  return false;
+}
+
+#  undef EXPAND_VARIADIC
+
+#else // _LIBCPP_STD_VER > 14
+
+template <typename _RandomAccessIterator1, typename _RandomAccessIterator2, bool _B>
+bool __radix_sort(_RandomAccessIterator1, _RandomAccessIterator1, _RandomAccessIterator2, _BoolConstant<_B>) {
+  return false;
+}
+
+#endif // _LIBCPP_STD_VER > 14
+
+_LIBCPP_END_NAMESPACE_STD
+
+_LIBCPP_POP_MACROS
+
+#endif // _LIBCPP___ALGORITHM_RADIX_SORT_H
diff --git a/libcxx/include/__algorithm/stable_sort.h b/libcxx/include/__algorithm/stable_sort.h
index 43f591ac02b01d..fb48af307508cc 100644
--- a/libcxx/include/__algorithm/stable_sort.h
+++ b/libcxx/include/__algorithm/stable_sort.h
@@ -13,6 +13,7 @@
 #include <__algorithm/comp_ref_type.h>
 #include <__algorithm/inplace_merge.h>
 #include <__algorithm/iterator_operations.h>
+#include <__algorithm/radix_sort.h>
 #include <__algorithm/sort.h>
 #include <__config>
 #include <__cstddef/ptrdiff_t.h>
@@ -21,6 +22,9 @@
 #include <__memory/destruct_n.h>
 #include <__memory/unique_ptr.h>
 #include <__memory/unique_temporary_buffer.h>
+#include <__type_traits/integral_constant.h>
+#include <__type_traits/is_integral.h>
+#include <__type_traits/is_same.h>
 #include <__type_traits/is_trivially_assignable.h>
 #include <__utility/move.h>
 #include <__utility/pair.h>
@@ -134,20 +138,24 @@ _LIBCPP_HIDE_FROM_ABI void __merge_move_assign(
     *__result = _Ops::__iter_move(__first2);
 }
 
-template <class _AlgPolicy, class _Compare, class _RandomAccessIterator>
-void __stable_sort(_RandomAccessIterator __first,
-                   _RandomAccessIterator __last,
-                   _Compare __comp,
-                   typename iterator_traits<_RandomAccessIterator>::difference_type __len,
-                   typename iterator_traits<_RandomAccessIterator>::value_type* __buff,
-                   ptrdiff_t __buff_size);
+template <class _AlgPolicy, class _Compare, class _RandomAccessIterator, bool _EnableRadixSort>
+void __stable_sort(
+    _RandomAccessIterator __first,
+    _RandomAccessIterator __last,
+    _Compare __comp,
+    typename iterator_traits<_RandomAccessIterator>::difference_type __len,
+    typename iterator_traits<_RandomAccessIterator>::value_type* __buff,
+    ptrdiff_t __buff_size,
+    _BoolConstant<_EnableRadixSort>);
 
-template <class _AlgPolicy, class _Compare, class _RandomAccessIterator>
-void __stable_sort_move(_RandomAccessIterator __first1,
-                        _RandomAccessIterator __last1,
-                        _Compare __comp,
-                        typename iterator_traits<_RandomAccessIterator>::difference_type __len,
-                        typename iterator_traits<_RandomAccessIterator>::value_type* __first2) {
+template <class _AlgPolicy, class _Compare, class _RandomAccessIterator, bool _EnableRadixSort>
+void __stable_sort_move(
+    _RandomAccessIterator __first1,
+    _RandomAccessIterator __last1,
+    _Compare __comp,
+    typename iterator_traits<_RandomAccessIterator>::difference_type __len,
+    typename iterator_traits<_RandomAccessIterator>::value_type* __first2,
+    _BoolConstant<_EnableRadixSort> __rs) {
   using _Ops = _IterOps<_AlgPolicy>;
 
   typedef typename iterator_traits<_RandomAccessIterator>::value_type value_type;
@@ -180,8 +188,8 @@ void __stable_sort_move(_RandomAccessIterator __first1,
   }
   typename iterator_traits<_RandomAccessIterator>::difference_type __l2 = __len / 2;
   _RandomAccessIterator __m                                             = __first1 + __l2;
-  std::__stable_sort<_AlgPolicy, _Compare>(__first1, __m, __comp, __l2, __first2, __l2);
-  std::__stable_sort<_AlgPolicy, _Compare>(__m, __last1, __comp, __len - __l2, __first2 + __l2, __len - __l2);
+  std::__stable_sort<_AlgPolicy, _Compare>(__first1, __m, __comp, __l2, __first2, __l2, __rs);
+  std::__stable_sort<_AlgPolicy, _Compare>(__m, __last1, __comp, __len - __l2, __first2 + __l2, __len - __l2, __rs);
   std::__merge_move_construct<_AlgPolicy, _Compare>(__first1, __m, __m, __last1, __first2, __comp);
 }
 
@@ -190,13 +198,35 @@ struct __stable_sort_switch {
   static const unsigned value = 128 * is_trivially_copy_assignable<_Tp>::value;
 };
 
-template <class _AlgPolicy, class _Compare, class _RandomAccessIterator>
-void __stable_sort(_RandomAccessIterator __first,
-                   _RandomAccessIterator __last,
-                   _Compare __comp,
-                   typename iterator_traits<_RandomAccessIterator>::difference_type __len,
-                   typename iterator_traits<_RandomAccessIterator>::value_type* __buff,
-                   ptrdiff_t __buff_size) {
+template <class _Tp, class = void>
+struct __radix_sort_min_switch {
+  static const unsigned value = (1 << 10);
+};
+
+template <class _Int8>
+struct __radix_sort_min_switch<_Int8, enable_if_t<is_integral_v<_Int8> && sizeof(_Int8) == 1>> {
+  static const unsigned value = (1 << 8);
+};
+
+template <class _Tp, class = void>
+struct __radix_sort_max_switch {
+  static const unsigned value = (1 << 16);
+};
+
+template <class _Int64>
+struct __radix_sort_max_switch<_Int64, enable_if_t<is_integral_v<_Int64> && sizeof(_Int64) == 8>> {
+  static const unsigned value = (1 << 15);
+};
+
+template <class _AlgPolicy, class _Compare, class _RandomAccessIterator, bool _EnableRadixSort>
+void __stable_sort(
+    _RandomAccessIterator __first,
+    _RandomAccessIterator __last,
+    _Compare __comp,
+    typename iterator_traits<_RandomAccessIterator>::difference_type __len,
+    typename iterator_traits<_RandomAccessIterator>::value_type* __buff,
+    ptrdiff_t __buff_size,
+    _BoolConstant<_EnableRadixSort> __rs) {
   typedef typename iterator_traits<_RandomAccessIterator>::value_type value_type;
   typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type;
   switch (__len) {
@@ -212,14 +242,20 @@ void __stable_sort(_RandomAccessIterator __first,
     std::__insertion_sort<_AlgPolicy, _Compare>(__first, __last, __comp);
     return;
   }
+  if (__len <= __buff_size && __len >= static_cast<difference_type>(__radix_sort_min_switch<value_type>::value) &&
+      __len <= static_cast<difference_type>(__radix_sort_max_switch<value_type>::value)) {
+    if (std::__radix_sort(__first, __last, __buff, __rs)) {
+      return;
+    }
+  }
   typename iterator_traits<_RandomAccessIterator>::difference_type __l2 = __len / 2;
   _RandomAccessIterator __m                                             = __first + __l2;
   if (__len <= __buff_size) {
     __destruct_n __d(0);
     unique_ptr<value_type, __destruct_n&> __h2(__buff, __d);
-    std::__stable_sort_move<_AlgPolicy, _Compare>(__first, __m, __comp, __l2, __buff);
+    std::__stable_sort_move<_AlgPolicy, _Compare>(__first, __m, __comp, __l2, __buff, __rs);
     __d.__set(__l2, (value_type*)nullptr);
-    std::__stable_sort_move<_AlgPolicy, _Compare>(__m, __last, __comp, __len - __l2, __buff + __l2);
+    std::__stable_sort_move<_AlgPolicy, _Compare>(__m, __last, __comp, __len - __l2, __buff + __l2, __rs);
     __d.__set(__len, (value_type*)nullptr);
     std::__merge_move_assign<_AlgPolicy, _Compare>(
         __buff, __buff + __l2, __buff + __l2, __buff + __len, __first, __comp);
@@ -230,14 +266,17 @@ void __stable_sort(_RandomAccessIterator __first,
     //                                  __first, __comp);
     return;
   }
-  std::__stable_sort<_AlgPolicy, _Compare>(__first, __m, __comp, __l2, __buff, __buff_size);
-  std::__stable_sort<_AlgPolicy, _Compare>(__m, __last, __comp, __len - __l2, __buff, __buff_size);
+  std::__stable_sort<_AlgPolicy, _Compare>(__first, __m, __comp, __l2, __buff, __buff_size, __rs);
+  std::__stable_sort<_AlgPolicy, _Compare>(__m, __last, __comp, __len - __l2, __buff, __buff_size, __rs);
   std::__inplace_merge<_AlgPolicy>(__first, __m, __last, __comp, __l2, __len - __l2, __buff, __buff_size);
 }
 
-template <class _AlgPolicy, class _RandomAccessIterator, class _Compare>
-inline _LIBCPP_HIDE_FROM_ABI void
-__stable_sort_impl(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare& __comp) {
+template <class _AlgPolicy, class _RandomAccessIterator, class _Compare, bool _EnableRadixSort = false>
+inline _LIBCPP_HIDE_FROM_ABI void __stable_sort_impl(
+    _RandomAccessIterator __first,
+    _RandomAccessIterator __last,
+    _Compare& __comp,
+    _BoolConstant<_EnableRadixSort> __rs = _BoolConstant<false>{}) {
   using value_type      = typename iterator_traits<_RandomAccessIterator>::value_type;
   using difference_type = typename iterator_traits<_RandomAccessIterator>::difference_type;
 
@@ -250,19 +289,27 @@ __stable_sort_impl(_RandomAccessIterator __first, _RandomAccessIterator __last,
     __buf.second = __unique_buf.get_deleter().__count_;
   }
 
-  std::__stable_sort<_AlgPolicy, __comp_ref_type<_Compare> >(__first, __last, __comp, __len, __buf.first, __buf.second);
+  std::__stable_sort<_AlgPolicy, __comp_ref_type<_Compare> >(
+      __first, __last, __comp, __len, __buf.first, __buf.second, __rs);
   std::__check_strict_weak_ordering_sorted(__first, __last, __comp);
 }
 
 template <class _RandomAccessIterator, class _Compare>
 inline _LIBCPP_HIDE_FROM_ABI void
 stable_sort(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) {
-  std::__stable_sort_impl<_ClassicAlgPolicy>(std::move(__first), std::move(__last), __comp);
+  std::__stable_sort_impl<_ClassicAlgPolicy>(std::move(__first), std::move(__last), __comp, _BoolConstant<false>());
 }
 
 template <class _RandomAccessIterator>
 inline _LIBCPP_HIDE_FROM_ABI void stable_sort(_RandomAccessIterator __first, _RandomAccessIterator __last) {
-  std::stable_sort(__first, __last, __less<>());
+  using value_type     = typename iterator_traits<_RandomAccessIterator>::value_type;
+  using reference_type = typename iterator_traits<_RandomAccessIterator>::reference;
+  auto __comp          = __less<>();
+  std::__stable_sort_impl<_ClassicAlgPolicy>(
+      std::move(__first),
+      std::move(__last),
+      __comp,
+      _BoolConstant < is_integral<value_type>::value && is_same<value_type&, reference_type>::value > ());
 }
 
 _LIBCPP_END_NAMESPACE_STD

>From 64d8165cd56862c782fc117350be4a371dc29df9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=94=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9=20=D0=98=D0=B7?=
 =?UTF-8?q?=D0=B2=D0=BE=D0=BB=D0=BE=D0=B2?= <dmitriy at izvolov.ru>
Date: Sat, 17 Aug 2024 17:21:06 +0300
Subject: [PATCH 02/46] ranged

---
 libcxx/include/__algorithm/ranges_stable_sort.h | 15 ++++++++++++++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/libcxx/include/__algorithm/ranges_stable_sort.h b/libcxx/include/__algorithm/ranges_stable_sort.h
index 9c7df80ae98722..96d84b208687fc 100644
--- a/libcxx/include/__algorithm/ranges_stable_sort.h
+++ b/libcxx/include/__algorithm/ranges_stable_sort.h
@@ -24,6 +24,8 @@
 #include <__ranges/access.h>
 #include <__ranges/concepts.h>
 #include <__ranges/dangling.h>
+#include <__type_traits/is_integral.h>
+#include <__type_traits/is_same.h>
 #include <__utility/forward.h>
 #include <__utility/move.h>
 
@@ -45,7 +47,18 @@ struct __stable_sort {
     auto __last_iter = ranges::next(__first, __last);
 
     auto&& __projected_comp = std::__make_projected(__comp, __proj);
-    std::__stable_sort_impl<_RangeAlgPolicy>(std::move(__first), __last_iter, __projected_comp);
+    constexpr auto __default_comp        = is_same_v<_Comp, ranges::less>;
+    constexpr auto __default_proj        = is_same_v<_Proj, identity>;
+    constexpr auto __integral_value      = is_integral_v<iter_value_t<_Iter>>;
+    constexpr auto __integral_projection = __default_proj && __integral_value;
+    // constexpr auto __integral_projection = is_integral_v<remove_reference_t<invoke_result_t<_Proj&,
+    // iter_value_t<_Iter>>>>;
+    // TODO: Support projection in stable_sort
+    std::__stable_sort_impl<_RangeAlgPolicy>(
+        std::move(__first),
+        __last_iter,
+        __projected_comp,
+        _BoolConstant < __default_comp && __integral_projection > {});
 
     return __last_iter;
   }

>From 7f74592026ee76fb5c7e608f3bc17b31ede50d8f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=94=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9=20=D0=98=D0=B7?=
 =?UTF-8?q?=D0=B2=D0=BE=D0=BB=D0=BE=D0=B2?= <dmitriy at izvolov.ru>
Date: Sun, 18 Aug 2024 01:17:10 +0300
Subject: [PATCH 03/46] distance

---
 libcxx/include/__algorithm/radix_sort.h | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/libcxx/include/__algorithm/radix_sort.h b/libcxx/include/__algorithm/radix_sort.h
index 5e14dec9df0918..8b3dce525fbcf2 100644
--- a/libcxx/include/__algorithm/radix_sort.h
+++ b/libcxx/include/__algorithm/radix_sort.h
@@ -13,6 +13,7 @@
 #include <__algorithm/copy.h>
 #include <__algorithm/for_each.h>
 #include <__config>
+#include <__iterator/distance.h>
 #include <__iterator/iterator_traits.h>
 #include <__iterator/move_iterator.h>
 #include <__iterator/next.h>
@@ -299,7 +300,7 @@ __radix_sort_impl(_RandomAccessIterator1 __first,
   difference_type __maximums[traits::radix_count]                            = {0};
   const auto __is_sorted = __collect(__first, __last, __map, __radix, __counters, __maximums);
   if (not __is_sorted) {
-    const auto __range_size = distance(__first, __last);
+    const auto __range_size = std::distance(__first, __last);
     auto __buffer_end       = __buffer_begin + __range_size;
     for (size_t __radix_number = 0; __radix_number < traits::radix_count; __radix_number += 2) {
       const auto __n0th_is_single = __maximums[__radix_number] == __range_size;

>From cbca2f19c7ff8d7f3790ed8676de7feead348a91 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=94=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9=20=D0=98=D0=B7?=
 =?UTF-8?q?=D0=B2=D0=BE=D0=BB=D0=BE=D0=B2?= <dmitriy at izvolov.ru>
Date: Sun, 18 Aug 2024 01:17:24 +0300
Subject: [PATCH 04/46] c++03

---
 libcxx/include/__algorithm/stable_sort.h | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/libcxx/include/__algorithm/stable_sort.h b/libcxx/include/__algorithm/stable_sort.h
index fb48af307508cc..8a349959acd393 100644
--- a/libcxx/include/__algorithm/stable_sort.h
+++ b/libcxx/include/__algorithm/stable_sort.h
@@ -204,7 +204,7 @@ struct __radix_sort_min_switch {
 };
 
 template <class _Int8>
-struct __radix_sort_min_switch<_Int8, enable_if_t<is_integral_v<_Int8> && sizeof(_Int8) == 1>> {
+struct __radix_sort_min_switch<_Int8, enable_if_t<is_integral<_Int8>::value && sizeof(_Int8) == 1> > {
   static const unsigned value = (1 << 8);
 };
 
@@ -214,7 +214,7 @@ struct __radix_sort_max_switch {
 };
 
 template <class _Int64>
-struct __radix_sort_max_switch<_Int64, enable_if_t<is_integral_v<_Int64> && sizeof(_Int64) == 8>> {
+struct __radix_sort_max_switch<_Int64, enable_if_t<is_integral<_Int64>::value && sizeof(_Int64) == 8> > {
   static const unsigned value = (1 << 15);
 };
 
@@ -276,7 +276,7 @@ inline _LIBCPP_HIDE_FROM_ABI void __stable_sort_impl(
     _RandomAccessIterator __first,
     _RandomAccessIterator __last,
     _Compare& __comp,
-    _BoolConstant<_EnableRadixSort> __rs = _BoolConstant<false>{}) {
+    _BoolConstant<_EnableRadixSort> __rs = _BoolConstant<false>()) {
   using value_type      = typename iterator_traits<_RandomAccessIterator>::value_type;
   using difference_type = typename iterator_traits<_RandomAccessIterator>::difference_type;
 

>From 90ea7c63ff72d2faa8883b390efc8bbedebce00e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=94=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9=20=D0=98=D0=B7?=
 =?UTF-8?q?=D0=B2=D0=BE=D0=BB=D0=BE=D0=B2?= <dmitriy at izvolov.ru>
Date: Sun, 18 Aug 2024 08:24:41 +0300
Subject: [PATCH 05/46] more-c++03

---
 libcxx/include/__algorithm/stable_sort.h | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/libcxx/include/__algorithm/stable_sort.h b/libcxx/include/__algorithm/stable_sort.h
index 8a349959acd393..2df7456c2733ff 100644
--- a/libcxx/include/__algorithm/stable_sort.h
+++ b/libcxx/include/__algorithm/stable_sort.h
@@ -22,6 +22,7 @@
 #include <__memory/destruct_n.h>
 #include <__memory/unique_ptr.h>
 #include <__memory/unique_temporary_buffer.h>
+#include <__type_traits/enable_if.h>
 #include <__type_traits/integral_constant.h>
 #include <__type_traits/is_integral.h>
 #include <__type_traits/is_same.h>
@@ -204,7 +205,7 @@ struct __radix_sort_min_switch {
 };
 
 template <class _Int8>
-struct __radix_sort_min_switch<_Int8, enable_if_t<is_integral<_Int8>::value && sizeof(_Int8) == 1> > {
+struct __radix_sort_min_switch<_Int8, __enable_if_t<is_integral<_Int8>::value && sizeof(_Int8) == 1> > {
   static const unsigned value = (1 << 8);
 };
 
@@ -214,7 +215,7 @@ struct __radix_sort_max_switch {
 };
 
 template <class _Int64>
-struct __radix_sort_max_switch<_Int64, enable_if_t<is_integral<_Int64>::value && sizeof(_Int64) == 8> > {
+struct __radix_sort_max_switch<_Int64, __enable_if_t<is_integral<_Int64>::value && sizeof(_Int64) == 8> > {
   static const unsigned value = (1 << 15);
 };
 

>From d72d972ce8340ec81b97752f71621a8879061826 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=94=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9=20=D0=98=D0=B7?=
 =?UTF-8?q?=D0=B2=D0=BE=D0=BB=D0=BE=D0=B2?= <dmitriy at izvolov.ru>
Date: Sun, 18 Aug 2024 08:24:51 +0300
Subject: [PATCH 06/46] support -fno-exceptions

---
 libcxx/include/__algorithm/radix_sort.h | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/libcxx/include/__algorithm/radix_sort.h b/libcxx/include/__algorithm/radix_sort.h
index 8b3dce525fbcf2..3eb602d75a09a2 100644
--- a/libcxx/include/__algorithm/radix_sort.h
+++ b/libcxx/include/__algorithm/radix_sort.h
@@ -78,8 +78,9 @@ template <typename _Integer>
 constexpr _Integer __intlog2(_Integer __integer) {
   static_assert(is_integral<_Integer>::value, "Must be an integral type");
 
-  return __integer > 0 ? __intlog2_impl(__integer)
-                       : throw domain_error("The binary logarithm is not defined on non-positive numbers");
+  return __integer > 0
+           ? __intlog2_impl(__integer)
+           : (__throw_domain_error("The binary logarithm is not defined on non-positive numbers"), _Integer{0});
 }
 
 template <typename _InputIterator, typename _OutputIterator>

>From bd54c6689c8fe8b24df841a8f7e1f52a965fc572 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=94=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9=20=D0=98=D0=B7?=
 =?UTF-8?q?=D0=B2=D0=BE=D0=BB=D0=BE=D0=B2?= <dmitriy at izvolov.ru>
Date: Sun, 18 Aug 2024 16:01:47 +0300
Subject: [PATCH 07/46] naming

---
 libcxx/include/__algorithm/radix_sort.h | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/libcxx/include/__algorithm/radix_sort.h b/libcxx/include/__algorithm/radix_sort.h
index 3eb602d75a09a2..c4112c6edf02ad 100644
--- a/libcxx/include/__algorithm/radix_sort.h
+++ b/libcxx/include/__algorithm/radix_sort.h
@@ -398,8 +398,9 @@ bool __radix_sort(_RandomAccessIterator1, _RandomAccessIterator1, _RandomAccessI
 
 #else // _LIBCPP_STD_VER > 14
 
-template <typename _RandomAccessIterator1, typename _RandomAccessIterator2, bool _B>
-bool __radix_sort(_RandomAccessIterator1, _RandomAccessIterator1, _RandomAccessIterator2, _BoolConstant<_B>) {
+template <typename _RandomAccessIterator1, typename _RandomAccessIterator2, bool _EnableRadixSort>
+bool __radix_sort(
+    _RandomAccessIterator1, _RandomAccessIterator1, _RandomAccessIterator2, _BoolConstant<_EnableRadixSort>) {
   return false;
 }
 

>From 5f2dabc2cad1fc0235b64125c08a4c86b809b657 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=94=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9=20=D0=98=D0=B7?=
 =?UTF-8?q?=D0=B2=D0=BE=D0=BB=D0=BE=D0=B2?= <dmitriy at izvolov.ru>
Date: Sun, 18 Aug 2024 22:48:44 +0300
Subject: [PATCH 08/46] no-exceptions

---
 libcxx/include/__algorithm/radix_sort.h | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/libcxx/include/__algorithm/radix_sort.h b/libcxx/include/__algorithm/radix_sort.h
index c4112c6edf02ad..c4f90e6a6888cd 100644
--- a/libcxx/include/__algorithm/radix_sort.h
+++ b/libcxx/include/__algorithm/radix_sort.h
@@ -33,7 +33,6 @@
 #include <cstdint>
 #include <initializer_list>
 #include <limits>
-#include <stdexcept>
 
 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
 #  pragma GCC system_header
@@ -78,9 +77,11 @@ template <typename _Integer>
 constexpr _Integer __intlog2(_Integer __integer) {
   static_assert(is_integral<_Integer>::value, "Must be an integral type");
 
-  return __integer > 0
-           ? __intlog2_impl(__integer)
-           : (__throw_domain_error("The binary logarithm is not defined on non-positive numbers"), _Integer{0});
+  if (__integer > 0) {
+    return __intlog2_impl(__integer);
+  }
+
+  return 0;
 }
 
 template <typename _InputIterator, typename _OutputIterator>

>From 8590a4e1a5bcea71925f943a1b6d0561d9d648ae Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=94=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9=20=D0=98=D0=B7?=
 =?UTF-8?q?=D0=B2=D0=BE=D0=BB=D0=BE=D0=B2?= <dmitriy at izvolov.ru>
Date: Tue, 20 Aug 2024 12:38:42 +0300
Subject: [PATCH 09/46] libcppver

---
 libcxx/include/__algorithm/radix_sort.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libcxx/include/__algorithm/radix_sort.h b/libcxx/include/__algorithm/radix_sort.h
index c4f90e6a6888cd..a67a32a6805aaf 100644
--- a/libcxx/include/__algorithm/radix_sort.h
+++ b/libcxx/include/__algorithm/radix_sort.h
@@ -43,7 +43,7 @@ _LIBCPP_PUSH_MACROS
 
 _LIBCPP_BEGIN_NAMESPACE_STD
 
-#if _LIBCPP_STD_VER > 14
+#if _LIBCPP_STD_VER >= 14
 
 inline void __variadic_expansion_dummy(initializer_list<int>) {}
 

>From 7e0e4ae5ca04576b0d543d86548d40e89ea51465 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=94=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9=20=D0=98=D0=B7?=
 =?UTF-8?q?=D0=B2=D0=BE=D0=BB=D0=BE=D0=B2?= <dmitriy at izvolov.ru>
Date: Tue, 20 Aug 2024 12:43:28 +0300
Subject: [PATCH 10/46] hide-from-abi

---
 libcxx/include/__algorithm/radix_sort.h | 120 +++++++++++++-----------
 1 file changed, 65 insertions(+), 55 deletions(-)

diff --git a/libcxx/include/__algorithm/radix_sort.h b/libcxx/include/__algorithm/radix_sort.h
index a67a32a6805aaf..26c49f232c05d8 100644
--- a/libcxx/include/__algorithm/radix_sort.h
+++ b/libcxx/include/__algorithm/radix_sort.h
@@ -45,25 +45,25 @@ _LIBCPP_BEGIN_NAMESPACE_STD
 
 #if _LIBCPP_STD_VER >= 14
 
-inline void __variadic_expansion_dummy(initializer_list<int>) {}
+inline _LIBCPP_HIDE_FROM_ABI void __variadic_expansion_dummy(initializer_list<int>) {}
 
 #  define EXPAND_VARIADIC(expression) __variadic_expansion_dummy({(expression, 0)...})
 
 template <typename _Iterator>
-constexpr auto __move_assign_please(_Iterator __i)
+_LIBCPP_HIDE_FROM_ABI constexpr auto __move_assign_please(_Iterator __i)
     -> enable_if_t<is_move_assignable<typename iterator_traits<_Iterator>::value_type>::value,
                    move_iterator<_Iterator> > {
   return make_move_iterator(std::move(__i));
 }
 
 template <typename _Iterator>
-constexpr auto __move_assign_please(_Iterator __i)
+_LIBCPP_HIDE_FROM_ABI constexpr auto __move_assign_please(_Iterator __i)
     -> enable_if_t<not is_move_assignable<typename iterator_traits<_Iterator>::value_type>::value, _Iterator> {
   return __i;
 }
 
 template <typename _Integer>
-constexpr _Integer __intlog2_impl(_Integer __integer) {
+_LIBCPP_HIDE_FROM_ABI constexpr _Integer __intlog2_impl(_Integer __integer) {
   auto __degree = _Integer{0};
 
   while ((__integer >>= 1) > 0) {
@@ -74,7 +74,7 @@ constexpr _Integer __intlog2_impl(_Integer __integer) {
 }
 
 template <typename _Integer>
-constexpr _Integer __intlog2(_Integer __integer) {
+_LIBCPP_HIDE_FROM_ABI constexpr _Integer __intlog2(_Integer __integer) {
   static_assert(is_integral<_Integer>::value, "Must be an integral type");
 
   if (__integer > 0) {
@@ -85,7 +85,7 @@ constexpr _Integer __intlog2(_Integer __integer) {
 }
 
 template <typename _InputIterator, typename _OutputIterator>
-pair<_OutputIterator, typename iterator_traits<_InputIterator>::value_type>
+_LIBCPP_HIDE_FROM_ABI pair<_OutputIterator, typename iterator_traits<_InputIterator>::value_type>
 __partial_sum_max(_InputIterator __first, _InputIterator __last, _OutputIterator __result) {
   if (__first == __last)
     return {__result, 0};
@@ -129,7 +129,7 @@ struct __counting_sort_traits {
 };
 
 template <typename _Radix>
-auto __nth_radix(size_t __radix_number, _Radix __radix) {
+_LIBCPP_HIDE_FROM_ABI auto __nth_radix(size_t __radix_number, _Radix __radix) {
   return [__radix_number, __radix = std::move(__radix)](auto __n) {
     using value_type = decltype(__n);
     static_assert(is_integral<value_type>::value, "");
@@ -141,12 +141,14 @@ auto __nth_radix(size_t __radix_number, _Radix __radix) {
 }
 
 template <typename _ForwardIterator, typename _Map, typename _RandomAccessIterator>
-void __count(_ForwardIterator __first, _ForwardIterator __last, _Map __map, _RandomAccessIterator __counters) {
+_LIBCPP_HIDE_FROM_ABI void
+__count(_ForwardIterator __first, _ForwardIterator __last, _Map __map, _RandomAccessIterator __counters) {
   std::for_each(__first, __last, [&__counters, &__map](const auto& __preimage) { ++__counters[__map(__preimage)]; });
 }
 
 template <typename _ForwardIterator, typename _Map, typename _RandomAccessIterator>
-void __collect(_ForwardIterator __first, _ForwardIterator __last, _Map __map, _RandomAccessIterator __counters) {
+_LIBCPP_HIDE_FROM_ABI void
+__collect(_ForwardIterator __first, _ForwardIterator __last, _Map __map, _RandomAccessIterator __counters) {
   using value_type = typename iterator_traits<_ForwardIterator>::value_type;
   using traits     = __counting_sort_traits<value_type, _Map>;
 
@@ -157,11 +159,12 @@ void __collect(_ForwardIterator __first, _ForwardIterator __last, _Map __map, _R
 }
 
 template <typename _ForwardIterator, typename _RandomAccessIterator1, typename _Map, typename _RandomAccessIterator2>
-void __dispose(_ForwardIterator __first,
-               _ForwardIterator __last,
-               _RandomAccessIterator1 __result,
-               _Map __map,
-               _RandomAccessIterator2 __counters) {
+_LIBCPP_HIDE_FROM_ABI void
+__dispose(_ForwardIterator __first,
+          _ForwardIterator __last,
+          _RandomAccessIterator1 __result,
+          _Map __map,
+          _RandomAccessIterator2 __counters) {
   std::for_each(__first, __last, [&__result, &__counters, &__map](auto&& __preimage) {
     auto __index      = __counters[__map(__preimage)]++;
     __result[__index] = std::forward<decltype(__preimage)>(__preimage);
@@ -172,13 +175,14 @@ template <typename _BidirectionalIterator,
           typename _RandomAccessIterator1,
           typename _Map,
           typename _RandomAccessIterator2>
-void dispose_backward(_BidirectionalIterator __first,
-                      _BidirectionalIterator __last,
-                      _RandomAccessIterator1 __result,
-                      _Map __map,
-                      _RandomAccessIterator2 __counters) {
-  std::for_each(make_reverse_iterator(__last),
-                make_reverse_iterator(__first),
+_LIBCPP_HIDE_FROM_ABI void dispose_backward(
+    _BidirectionalIterator __first,
+    _BidirectionalIterator __last,
+    _RandomAccessIterator1 __result,
+    _Map __map,
+    _RandomAccessIterator2 __counters) {
+  std::for_each(std::make_reverse_iterator(__last),
+                std::make_reverse_iterator(__first),
                 [&__result, &__counters, &__map](auto&& __preimage) {
                   auto __index      = --__counters[__map(__preimage)];
                   __result[__index] = std::forward<decltype(__preimage)>(__preimage);
@@ -191,7 +195,7 @@ template <typename _ForwardIterator,
           typename _RandomAccessIterator1,
           typename _RandomAccessIterator2,
           size_t... _Radices>
-bool __collect_impl(
+_LIBCPP_HIDE_FROM_ABI bool __collect_impl(
     _ForwardIterator __first,
     _ForwardIterator __last,
     _Map __map,
@@ -225,12 +229,13 @@ template <typename _ForwardIterator,
           typename _Radix,
           typename _RandomAccessIterator1,
           typename _RandomAccessIterator2>
-bool __collect(_ForwardIterator __first,
-               _ForwardIterator __last,
-               _Map __map,
-               _Radix __radix,
-               _RandomAccessIterator1 __counters,
-               _RandomAccessIterator2 __maximums) {
+_LIBCPP_HIDE_FROM_ABI bool
+__collect(_ForwardIterator __first,
+          _ForwardIterator __last,
+          _Map __map,
+          _Radix __radix,
+          _RandomAccessIterator1 __counters,
+          _RandomAccessIterator2 __maximums) {
   using value_type             = typename iterator_traits<_ForwardIterator>::value_type;
   constexpr auto __radix_count = __radix_sort_traits<value_type, _Map, _Radix>::radix_count;
   return __collect_impl(__first, __last, __map, __radix, __counters, __maximums, make_index_sequence<__radix_count>());
@@ -240,20 +245,22 @@ template <typename _BidirectionalIterator,
           typename _RandomAccessIterator1,
           typename _Map,
           typename _RandomAccessIterator2>
-void __dispose_backward(_BidirectionalIterator __first,
-                        _BidirectionalIterator __last,
-                        _RandomAccessIterator1 __result,
-                        _Map __map,
-                        _RandomAccessIterator2 __counters) {
-  for_each(
-      make_reverse_iterator(__last), make_reverse_iterator(__first), [&__result, &__counters, &__map](auto&& preimage) {
-        auto __index      = --__counters[__map(preimage)];
-        __result[__index] = std::forward<decltype(preimage)>(preimage);
-      });
+_LIBCPP_HIDE_FROM_ABI void __dispose_backward(
+    _BidirectionalIterator __first,
+    _BidirectionalIterator __last,
+    _RandomAccessIterator1 __result,
+    _Map __map,
+    _RandomAccessIterator2 __counters) {
+  std::for_each(std::make_reverse_iterator(__last),
+                std::make_reverse_iterator(__first),
+                [&__result, &__counters, &__map](auto&& preimage) {
+                  auto __index      = --__counters[__map(preimage)];
+                  __result[__index] = std::forward<decltype(preimage)>(preimage);
+                });
 }
 
 template <typename _ForwardIterator, typename _RandomAccessIterator, typename _Map>
-_RandomAccessIterator
+_LIBCPP_HIDE_FROM_ABI _RandomAccessIterator
 __counting_sort_impl(_ForwardIterator __first, _ForwardIterator __last, _RandomAccessIterator __result, _Map __map) {
   using value_type = typename iterator_traits<_ForwardIterator>::value_type;
   using traits     = __counting_sort_traits<value_type, _Map>;
@@ -268,7 +275,7 @@ __counting_sort_impl(_ForwardIterator __first, _ForwardIterator __last, _RandomA
 }
 
 template <typename _RandomAccessIterator1, typename _RandomAccessIterator2, typename _Map, typename _Radix>
-typename enable_if<
+_LIBCPP_HIDE_FROM_ABI typename enable_if<
     __radix_sort_traits<typename iterator_traits<_RandomAccessIterator1>::value_type, _Map, _Radix>::radix_count == 1,
     void>::type
 __radix_sort_impl(_RandomAccessIterator1 __first,
@@ -285,7 +292,7 @@ __radix_sort_impl(_RandomAccessIterator1 __first,
 }
 
 template <typename _RandomAccessIterator1, typename _RandomAccessIterator2, typename _Map, typename _Radix>
-typename enable_if<
+_LIBCPP_HIDE_FROM_ABI typename enable_if<
     __radix_sort_traits<typename iterator_traits<_RandomAccessIterator1>::value_type, _Map, _Radix>::radix_count % 2 ==
         0,
     void>::type
@@ -343,24 +350,24 @@ __radix_sort_impl(_RandomAccessIterator1 __first,
   }
 }
 
-constexpr auto __to_unsigned(bool __b) { return __b; }
+_LIBCPP_HIDE_FROM_ABI constexpr auto __to_unsigned(bool __b) { return __b; }
 
 template <typename _Ip>
-constexpr auto __to_unsigned(_Ip __n) {
+_LIBCPP_HIDE_FROM_ABI constexpr auto __to_unsigned(_Ip __n) {
   constexpr const auto __min_value = numeric_limits<_Ip>::min();
   return static_cast<make_unsigned_t<_Ip> >(__n ^ __min_value);
 }
 
 struct __identity_fn {
   template <typename _Tp>
-  constexpr decltype(auto) operator()(_Tp&& __value) const {
+  _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) operator()(_Tp&& __value) const {
     return std::forward<_Tp>(__value);
   }
 };
 
 struct __low_byte_fn {
   template <typename _Ip>
-  constexpr uint8_t operator()(_Ip __integer) const {
+  _LIBCPP_HIDE_FROM_ABI constexpr uint8_t operator()(_Ip __integer) const {
     static_assert(is_integral<_Ip>::value, "");
     static_assert(is_unsigned<_Ip>::value, "");
 
@@ -369,29 +376,32 @@ struct __low_byte_fn {
 };
 
 template <typename _RandomAccessIterator1, typename _RandomAccessIterator2, typename _Map, typename _Radix>
-void __radix_sort(_RandomAccessIterator1 __first,
-                  _RandomAccessIterator1 __last,
-                  _RandomAccessIterator2 buffer,
-                  _Map __map,
-                  _Radix __radix) {
+_LIBCPP_HIDE_FROM_ABI void
+__radix_sort(_RandomAccessIterator1 __first,
+             _RandomAccessIterator1 __last,
+             _RandomAccessIterator2 buffer,
+             _Map __map,
+             _Radix __radix) {
   auto __map_to_unsigned = [__map = std::move(__map)](const auto& x) { return __to_unsigned(__map(x)); };
   __radix_sort_impl(__first, __last, buffer, __map_to_unsigned, __radix);
 }
 
 template <typename _RandomAccessIterator1, typename _RandomAccessIterator2>
-void __radix_sort(_RandomAccessIterator1 __first, _RandomAccessIterator1 __last, _RandomAccessIterator2 buffer) {
+_LIBCPP_HIDE_FROM_ABI void
+__radix_sort(_RandomAccessIterator1 __first, _RandomAccessIterator1 __last, _RandomAccessIterator2 buffer) {
   __radix_sort(__first, __last, buffer, __identity_fn{}, __low_byte_fn{});
 }
 
 template <typename _RandomAccessIterator1, typename _RandomAccessIterator2>
-bool __radix_sort(
+_LIBCPP_HIDE_FROM_ABI bool __radix_sort(
     _RandomAccessIterator1 __first, _RandomAccessIterator1 __last, _RandomAccessIterator2 buffer, _BoolConstant<true>) {
   __radix_sort(__first, __last, buffer, __identity_fn{}, __low_byte_fn{});
   return true;
 }
 
 template <typename _RandomAccessIterator1, typename _RandomAccessIterator2>
-bool __radix_sort(_RandomAccessIterator1, _RandomAccessIterator1, _RandomAccessIterator2, _BoolConstant<false>) {
+_LIBCPP_HIDE_FROM_ABI bool
+__radix_sort(_RandomAccessIterator1, _RandomAccessIterator1, _RandomAccessIterator2, _BoolConstant<false>) {
   return false;
 }
 
@@ -400,8 +410,8 @@ bool __radix_sort(_RandomAccessIterator1, _RandomAccessIterator1, _RandomAccessI
 #else // _LIBCPP_STD_VER > 14
 
 template <typename _RandomAccessIterator1, typename _RandomAccessIterator2, bool _EnableRadixSort>
-bool __radix_sort(
-    _RandomAccessIterator1, _RandomAccessIterator1, _RandomAccessIterator2, _BoolConstant<_EnableRadixSort>) {
+_LIBCPP_HIDE_FROM_ABI bool
+__radix_sort(_RandomAccessIterator1, _RandomAccessIterator1, _RandomAccessIterator2, _BoolConstant<_EnableRadixSort>) {
   return false;
 }
 

>From 9ed417f758f46e747251e1fff9149ea70fbbab2a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=94=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9=20=D0=98=D0=B7?=
 =?UTF-8?q?=D0=B2=D0=BE=D0=BB=D0=BE=D0=B2?= <dmitriy at izvolov.ru>
Date: Tue, 20 Aug 2024 12:44:22 +0300
Subject: [PATCH 11/46] adl

---
 libcxx/include/__algorithm/radix_sort.h | 68 +++++++++++++------------
 1 file changed, 35 insertions(+), 33 deletions(-)

diff --git a/libcxx/include/__algorithm/radix_sort.h b/libcxx/include/__algorithm/radix_sort.h
index 26c49f232c05d8..4f41a302d226ee 100644
--- a/libcxx/include/__algorithm/radix_sort.h
+++ b/libcxx/include/__algorithm/radix_sort.h
@@ -47,13 +47,13 @@ _LIBCPP_BEGIN_NAMESPACE_STD
 
 inline _LIBCPP_HIDE_FROM_ABI void __variadic_expansion_dummy(initializer_list<int>) {}
 
-#  define EXPAND_VARIADIC(expression) __variadic_expansion_dummy({(expression, 0)...})
+#  define EXPAND_VARIADIC(expression) std::__variadic_expansion_dummy({(expression, 0)...})
 
 template <typename _Iterator>
 _LIBCPP_HIDE_FROM_ABI constexpr auto __move_assign_please(_Iterator __i)
     -> enable_if_t<is_move_assignable<typename iterator_traits<_Iterator>::value_type>::value,
                    move_iterator<_Iterator> > {
-  return make_move_iterator(std::move(__i));
+  return std::make_move_iterator(std::move(__i));
 }
 
 template <typename _Iterator>
@@ -78,7 +78,7 @@ _LIBCPP_HIDE_FROM_ABI constexpr _Integer __intlog2(_Integer __integer) {
   static_assert(is_integral<_Integer>::value, "Must be an integral type");
 
   if (__integer > 0) {
-    return __intlog2_impl(__integer);
+    return std::__intlog2_impl(__integer);
   }
 
   return 0;
@@ -114,7 +114,7 @@ struct __radix_sort_traits {
   static_assert(is_integral<radix_type>::value, "");
 
   constexpr static auto radix_value_range = numeric_limits<radix_type>::max() + 1;
-  constexpr static auto radix_size        = __intlog2<uint64_t>(radix_value_range);
+  constexpr static auto radix_size        = std::__intlog2<uint64_t>(radix_value_range);
   constexpr static auto radix_count       = sizeof(image_type) * CHAR_BIT / radix_size;
 };
 
@@ -125,7 +125,7 @@ struct __counting_sort_traits {
   static_assert(is_unsigned<image_type>::value, "");
 
   constexpr static const auto value_range = numeric_limits<image_type>::max() + 1;
-  constexpr static auto radix_size        = __intlog2<uint64_t>(value_range);
+  constexpr static auto radix_size        = std::__intlog2<uint64_t>(value_range);
 };
 
 template <typename _Radix>
@@ -152,10 +152,10 @@ __collect(_ForwardIterator __first, _ForwardIterator __last, _Map __map, _Random
   using value_type = typename iterator_traits<_ForwardIterator>::value_type;
   using traits     = __counting_sort_traits<value_type, _Map>;
 
-  __count(__first, __last, __map, __counters);
+  std::__count(__first, __last, __map, __counters);
 
   const auto __counters_end = __counters + traits::value_range;
-  partial_sum(__counters, __counters_end, __counters);
+  std::partial_sum(__counters, __counters_end, __counters);
 }
 
 template <typename _ForwardIterator, typename _RandomAccessIterator1, typename _Map, typename _RandomAccessIterator2>
@@ -208,17 +208,17 @@ _LIBCPP_HIDE_FROM_ABI bool __collect_impl(
 
   auto __previous  = numeric_limits<invoke_result_t<_Map, value_type> >::min();
   auto __is_sorted = true;
-  for_each(__first, __last, [&__counters, &__map, &__radix, &__previous, &__is_sorted](const auto& value) {
+  std::for_each(__first, __last, [&__counters, &__map, &__radix, &__previous, &__is_sorted](const auto& value) {
     auto __current = __map(value);
     __is_sorted &= (__current >= __previous);
     __previous = __current;
 
-    EXPAND_VARIADIC(++__counters[_Radices][__nth_radix(_Radices, __radix)(__current)]);
+    EXPAND_VARIADIC(++__counters[_Radices][std::__nth_radix(_Radices, __radix)(__current)]);
   });
 
   EXPAND_VARIADIC(
       __maximums[_Radices] =
-          __partial_sum_max(__counters[_Radices], __counters[_Radices] + __radix_value_range, __counters[_Radices])
+          std::__partial_sum_max(__counters[_Radices], __counters[_Radices] + __radix_value_range, __counters[_Radices])
               .second);
 
   return __is_sorted;
@@ -238,7 +238,8 @@ __collect(_ForwardIterator __first,
           _RandomAccessIterator2 __maximums) {
   using value_type             = typename iterator_traits<_ForwardIterator>::value_type;
   constexpr auto __radix_count = __radix_sort_traits<value_type, _Map, _Radix>::radix_count;
-  return __collect_impl(__first, __last, __map, __radix, __counters, __maximums, make_index_sequence<__radix_count>());
+  return std::__collect_impl(
+      __first, __last, __map, __radix, __counters, __maximums, make_index_sequence<__radix_count>());
 }
 
 template <typename _BidirectionalIterator,
@@ -268,8 +269,8 @@ __counting_sort_impl(_ForwardIterator __first, _ForwardIterator __last, _RandomA
   using difference_type = typename iterator_traits<_RandomAccessIterator>::difference_type;
   difference_type __counters[traits::value_range + 1] = {0};
 
-  __collect(__first, __last, __map, next(std::begin(__counters)));
-  __dispose(__first, __last, __result, __map, std::begin(__counters));
+  std::__collect(__first, __last, __map, std::next(std::begin(__counters)));
+  std::__dispose(__first, __last, __result, __map, std::begin(__counters));
 
   return __result + __counters[traits::value_range];
 }
@@ -283,12 +284,13 @@ __radix_sort_impl(_RandomAccessIterator1 __first,
                   _RandomAccessIterator2 buffer,
                   _Map __map,
                   _Radix __radix) {
-  auto __buffer_end = __counting_sort_impl(
-      __move_assign_please(__first), __move_assign_please(__last), buffer, [&__map, &__radix](const auto& value) {
-        return __radix(__map(value));
-      });
+  auto __buffer_end = std::__counting_sort_impl(
+      std::__move_assign_please(__first),
+      std::__move_assign_please(__last),
+      buffer,
+      [&__map, &__radix](const auto& value) { return __radix(__map(value)); });
 
-  std::copy(__move_assign_please(buffer), __move_assign_please(__buffer_end), __first);
+  std::copy(std::__move_assign_please(buffer), std::__move_assign_please(__buffer_end), __first);
 }
 
 template <typename _RandomAccessIterator1, typename _RandomAccessIterator2, typename _Map, typename _Radix>
@@ -307,7 +309,7 @@ __radix_sort_impl(_RandomAccessIterator1 __first,
   using difference_type = typename iterator_traits<_RandomAccessIterator1>::difference_type;
   difference_type __counters[traits::radix_count][traits::radix_value_range] = {{0}};
   difference_type __maximums[traits::radix_count]                            = {0};
-  const auto __is_sorted = __collect(__first, __last, __map, __radix, __counters, __maximums);
+  const auto __is_sorted = std::__collect(__first, __last, __map, __radix, __counters, __maximums);
   if (not __is_sorted) {
     const auto __range_size = std::distance(__first, __last);
     auto __buffer_end       = __buffer_begin + __range_size;
@@ -320,28 +322,28 @@ __radix_sort_impl(_RandomAccessIterator1 __first,
       }
 
       if (__n0th_is_single) {
-        copy(__move_assign_please(__first), __move_assign_please(__last), __buffer_begin);
+        std::copy(std::__move_assign_please(__first), std::__move_assign_please(__last), __buffer_begin);
       } else {
         auto __n0th = [__radix_number, &__map, &__radix](const auto& __v) {
-          return __nth_radix(__radix_number, __radix)(__map(__v));
+          return std::__nth_radix(__radix_number, __radix)(__map(__v));
         };
-        __dispose_backward(
-            __move_assign_please(__first),
-            __move_assign_please(__last),
+        std::__dispose_backward(
+            std::__move_assign_please(__first),
+            std::__move_assign_please(__last),
             __buffer_begin,
             __n0th,
             __counters[__radix_number]);
       }
 
       if (__n1th_is_single) {
-        copy(__move_assign_please(__buffer_begin), __move_assign_please(__buffer_end), __first);
+        std::copy(std::__move_assign_please(__buffer_begin), std::__move_assign_please(__buffer_end), __first);
       } else {
         auto __n1th = [__radix_number, &__map, &__radix](const auto& __v) {
-          return __nth_radix(__radix_number + 1, __radix)(__map(__v));
+          return std::__nth_radix(__radix_number + 1, __radix)(__map(__v));
         };
-        __dispose_backward(
-            __move_assign_please(__buffer_begin),
-            __move_assign_please(__buffer_end),
+        std::__dispose_backward(
+            std::__move_assign_please(__buffer_begin),
+            std::__move_assign_please(__buffer_end),
             __first,
             __n1th,
             __counters[__radix_number + 1]);
@@ -382,20 +384,20 @@ __radix_sort(_RandomAccessIterator1 __first,
              _RandomAccessIterator2 buffer,
              _Map __map,
              _Radix __radix) {
-  auto __map_to_unsigned = [__map = std::move(__map)](const auto& x) { return __to_unsigned(__map(x)); };
-  __radix_sort_impl(__first, __last, buffer, __map_to_unsigned, __radix);
+  auto __map_to_unsigned = [__map = std::move(__map)](const auto& x) { return std::__to_unsigned(__map(x)); };
+  std::__radix_sort_impl(__first, __last, buffer, __map_to_unsigned, __radix);
 }
 
 template <typename _RandomAccessIterator1, typename _RandomAccessIterator2>
 _LIBCPP_HIDE_FROM_ABI void
 __radix_sort(_RandomAccessIterator1 __first, _RandomAccessIterator1 __last, _RandomAccessIterator2 buffer) {
-  __radix_sort(__first, __last, buffer, __identity_fn{}, __low_byte_fn{});
+  std::__radix_sort(__first, __last, buffer, __identity_fn{}, __low_byte_fn{});
 }
 
 template <typename _RandomAccessIterator1, typename _RandomAccessIterator2>
 _LIBCPP_HIDE_FROM_ABI bool __radix_sort(
     _RandomAccessIterator1 __first, _RandomAccessIterator1 __last, _RandomAccessIterator2 buffer, _BoolConstant<true>) {
-  __radix_sort(__first, __last, buffer, __identity_fn{}, __low_byte_fn{});
+  std::__radix_sort(__first, __last, buffer, __identity_fn{}, __low_byte_fn{});
   return true;
 }
 

>From 7f68bc4c9be97df5d3138e62aab77dc02aa3a375 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=94=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9=20=D0=98=D0=B7?=
 =?UTF-8?q?=D0=B2=D0=BE=D0=BB=D0=BE=D0=B2?= <dmitriy at izvolov.ru>
Date: Tue, 20 Aug 2024 13:27:25 +0300
Subject: [PATCH 12/46] rev-iter

---
 libcxx/include/__algorithm/radix_sort.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/libcxx/include/__algorithm/radix_sort.h b/libcxx/include/__algorithm/radix_sort.h
index 4f41a302d226ee..73d03c9d43bdda 100644
--- a/libcxx/include/__algorithm/radix_sort.h
+++ b/libcxx/include/__algorithm/radix_sort.h
@@ -17,6 +17,7 @@
 #include <__iterator/iterator_traits.h>
 #include <__iterator/move_iterator.h>
 #include <__iterator/next.h>
+#include <__iterator/reverse_iterator.h>
 #include <__numeric/partial_sum.h>
 #include <__type_traits/decay.h>
 #include <__type_traits/enable_if.h>

>From cac1ea2f12a84e8d651c75e726ff5ece1e50c919 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=94=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9=20=D0=98=D0=B7?=
 =?UTF-8?q?=D0=B2=D0=BE=D0=BB=D0=BE=D0=B2?= <dmitriy at izvolov.ru>
Date: Tue, 20 Aug 2024 22:36:18 +0300
Subject: [PATCH 13/46] use-countl-zero-for-log

---
 libcxx/include/__algorithm/radix_sort.h | 25 ++++++-------------------
 1 file changed, 6 insertions(+), 19 deletions(-)

diff --git a/libcxx/include/__algorithm/radix_sort.h b/libcxx/include/__algorithm/radix_sort.h
index 73d03c9d43bdda..f6b4e775da7c31 100644
--- a/libcxx/include/__algorithm/radix_sort.h
+++ b/libcxx/include/__algorithm/radix_sort.h
@@ -12,6 +12,7 @@
 
 #include <__algorithm/copy.h>
 #include <__algorithm/for_each.h>
+#include <__bit/countl.h>
 #include <__config>
 #include <__iterator/distance.h>
 #include <__iterator/iterator_traits.h>
@@ -63,26 +64,12 @@ _LIBCPP_HIDE_FROM_ABI constexpr auto __move_assign_please(_Iterator __i)
   return __i;
 }
 
-template <typename _Integer>
-_LIBCPP_HIDE_FROM_ABI constexpr _Integer __intlog2_impl(_Integer __integer) {
-  auto __degree = _Integer{0};
+template <typename _UnsignedInteger>
+_LIBCPP_HIDE_FROM_ABI constexpr _UnsignedInteger __intlog2(_UnsignedInteger __n) {
+  static_assert(is_integral<_UnsignedInteger>::value, "Must be an integral type");
+  static_assert(is_unsigned<_UnsignedInteger>::value, "Must be unsigned");
 
-  while ((__integer >>= 1) > 0) {
-    ++__degree;
-  }
-
-  return __degree;
-}
-
-template <typename _Integer>
-_LIBCPP_HIDE_FROM_ABI constexpr _Integer __intlog2(_Integer __integer) {
-  static_assert(is_integral<_Integer>::value, "Must be an integral type");
-
-  if (__integer > 0) {
-    return std::__intlog2_impl(__integer);
-  }
-
-  return 0;
+  return numeric_limits<_UnsignedInteger>::digits - 1 - std::__countl_zero(__n);
 }
 
 template <typename _InputIterator, typename _OutputIterator>

>From 97e844faba6749ea6f645f2ba437638510811538 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=94=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9=20=D0=98=D0=B7?=
 =?UTF-8?q?=D0=B2=D0=BE=D0=BB=D0=BE=D0=B2?= <dmitriy at izvolov.ru>
Date: Tue, 20 Aug 2024 22:37:15 +0300
Subject: [PATCH 14/46] uglify-macro

---
 libcxx/include/__algorithm/radix_sort.h | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/libcxx/include/__algorithm/radix_sort.h b/libcxx/include/__algorithm/radix_sort.h
index f6b4e775da7c31..51f29a6fedace0 100644
--- a/libcxx/include/__algorithm/radix_sort.h
+++ b/libcxx/include/__algorithm/radix_sort.h
@@ -49,7 +49,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
 
 inline _LIBCPP_HIDE_FROM_ABI void __variadic_expansion_dummy(initializer_list<int>) {}
 
-#  define EXPAND_VARIADIC(expression) std::__variadic_expansion_dummy({(expression, 0)...})
+#  define _EXPAND_VARIADIC(expression) std::__variadic_expansion_dummy({(expression, 0)...})
 
 template <typename _Iterator>
 _LIBCPP_HIDE_FROM_ABI constexpr auto __move_assign_please(_Iterator __i)
@@ -201,10 +201,10 @@ _LIBCPP_HIDE_FROM_ABI bool __collect_impl(
     __is_sorted &= (__current >= __previous);
     __previous = __current;
 
-    EXPAND_VARIADIC(++__counters[_Radices][std::__nth_radix(_Radices, __radix)(__current)]);
+    _EXPAND_VARIADIC(++__counters[_Radices][std::__nth_radix(_Radices, __radix)(__current)]);
   });
 
-  EXPAND_VARIADIC(
+  _EXPAND_VARIADIC(
       __maximums[_Radices] =
           std::__partial_sum_max(__counters[_Radices], __counters[_Radices] + __radix_value_range, __counters[_Radices])
               .second);
@@ -395,7 +395,7 @@ __radix_sort(_RandomAccessIterator1, _RandomAccessIterator1, _RandomAccessIterat
   return false;
 }
 
-#  undef EXPAND_VARIADIC
+#  undef _EXPAND_VARIADIC
 
 #else // _LIBCPP_STD_VER > 14
 

>From e2f4e2fb30a4455a64a5019a9b0e47fa82773971 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=94=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9=20=D0=98=D0=B7?=
 =?UTF-8?q?=D0=B2=D0=BE=D0=BB=D0=BE=D0=B2?= <dmitriy at izvolov.ru>
Date: Tue, 20 Aug 2024 22:45:13 +0300
Subject: [PATCH 15/46] uglify-static-members

---
 libcxx/include/__algorithm/radix_sort.h | 33 +++++++++++++------------
 1 file changed, 17 insertions(+), 16 deletions(-)

diff --git a/libcxx/include/__algorithm/radix_sort.h b/libcxx/include/__algorithm/radix_sort.h
index 51f29a6fedace0..e3de71a417ceab 100644
--- a/libcxx/include/__algorithm/radix_sort.h
+++ b/libcxx/include/__algorithm/radix_sort.h
@@ -101,9 +101,9 @@ struct __radix_sort_traits {
   using radix_type = decay_t<invoke_result_t<_Radix, image_type> >;
   static_assert(is_integral<radix_type>::value, "");
 
-  constexpr static auto radix_value_range = numeric_limits<radix_type>::max() + 1;
-  constexpr static auto radix_size        = std::__intlog2<uint64_t>(radix_value_range);
-  constexpr static auto radix_count       = sizeof(image_type) * CHAR_BIT / radix_size;
+  constexpr static auto __radix_value_range = numeric_limits<radix_type>::max() + 1;
+  constexpr static auto __radix_size        = std::__intlog2<uint64_t>(__radix_value_range);
+  constexpr static auto __radix_count       = sizeof(image_type) * CHAR_BIT / __radix_size;
 };
 
 template <typename _Value, typename _Map>
@@ -112,8 +112,8 @@ struct __counting_sort_traits {
   static_assert(is_integral<image_type>::value, "");
   static_assert(is_unsigned<image_type>::value, "");
 
-  constexpr static const auto value_range = numeric_limits<image_type>::max() + 1;
-  constexpr static auto radix_size        = std::__intlog2<uint64_t>(value_range);
+  constexpr static const auto __value_range = numeric_limits<image_type>::max() + 1;
+  constexpr static auto __radix_size        = std::__intlog2<uint64_t>(__value_range);
 };
 
 template <typename _Radix>
@@ -124,7 +124,7 @@ _LIBCPP_HIDE_FROM_ABI auto __nth_radix(size_t __radix_number, _Radix __radix) {
     static_assert(is_unsigned<value_type>::value, "");
     using traits = __counting_sort_traits<value_type, _Radix>;
 
-    return __radix(static_cast<value_type>(__n >> traits::radix_size * __radix_number));
+    return __radix(static_cast<value_type>(__n >> traits::__radix_size * __radix_number));
   };
 }
 
@@ -142,7 +142,7 @@ __collect(_ForwardIterator __first, _ForwardIterator __last, _Map __map, _Random
 
   std::__count(__first, __last, __map, __counters);
 
-  const auto __counters_end = __counters + traits::value_range;
+  const auto __counters_end = __counters + traits::__value_range;
   std::partial_sum(__counters, __counters_end, __counters);
 }
 
@@ -192,7 +192,7 @@ _LIBCPP_HIDE_FROM_ABI bool __collect_impl(
     _RandomAccessIterator2 __maximums,
     index_sequence<_Radices...>) {
   using value_type                   = typename iterator_traits<_ForwardIterator>::value_type;
-  constexpr auto __radix_value_range = __radix_sort_traits<value_type, _Map, _Radix>::radix_value_range;
+  constexpr auto __radix_value_range = __radix_sort_traits<value_type, _Map, _Radix>::__radix_value_range;
 
   auto __previous  = numeric_limits<invoke_result_t<_Map, value_type> >::min();
   auto __is_sorted = true;
@@ -225,7 +225,7 @@ __collect(_ForwardIterator __first,
           _RandomAccessIterator1 __counters,
           _RandomAccessIterator2 __maximums) {
   using value_type             = typename iterator_traits<_ForwardIterator>::value_type;
-  constexpr auto __radix_count = __radix_sort_traits<value_type, _Map, _Radix>::radix_count;
+  constexpr auto __radix_count = __radix_sort_traits<value_type, _Map, _Radix>::__radix_count;
   return std::__collect_impl(
       __first, __last, __map, __radix, __counters, __maximums, make_index_sequence<__radix_count>());
 }
@@ -255,17 +255,17 @@ __counting_sort_impl(_ForwardIterator __first, _ForwardIterator __last, _RandomA
   using traits     = __counting_sort_traits<value_type, _Map>;
 
   using difference_type = typename iterator_traits<_RandomAccessIterator>::difference_type;
-  difference_type __counters[traits::value_range + 1] = {0};
+  difference_type __counters[traits::__value_range + 1] = {0};
 
   std::__collect(__first, __last, __map, std::next(std::begin(__counters)));
   std::__dispose(__first, __last, __result, __map, std::begin(__counters));
 
-  return __result + __counters[traits::value_range];
+  return __result + __counters[traits::__value_range];
 }
 
 template <typename _RandomAccessIterator1, typename _RandomAccessIterator2, typename _Map, typename _Radix>
 _LIBCPP_HIDE_FROM_ABI typename enable_if<
-    __radix_sort_traits<typename iterator_traits<_RandomAccessIterator1>::value_type, _Map, _Radix>::radix_count == 1,
+    __radix_sort_traits<typename iterator_traits<_RandomAccessIterator1>::value_type, _Map, _Radix>::__radix_count == 1,
     void>::type
 __radix_sort_impl(_RandomAccessIterator1 __first,
                   _RandomAccessIterator1 __last,
@@ -283,7 +283,8 @@ __radix_sort_impl(_RandomAccessIterator1 __first,
 
 template <typename _RandomAccessIterator1, typename _RandomAccessIterator2, typename _Map, typename _Radix>
 _LIBCPP_HIDE_FROM_ABI typename enable_if<
-    __radix_sort_traits<typename iterator_traits<_RandomAccessIterator1>::value_type, _Map, _Radix>::radix_count % 2 ==
+    __radix_sort_traits<typename iterator_traits<_RandomAccessIterator1>::value_type, _Map, _Radix>::__radix_count %
+            2 ==
         0,
     void>::type
 __radix_sort_impl(_RandomAccessIterator1 __first,
@@ -295,13 +296,13 @@ __radix_sort_impl(_RandomAccessIterator1 __first,
   using traits     = __radix_sort_traits<value_type, _Map, _Radix>;
 
   using difference_type = typename iterator_traits<_RandomAccessIterator1>::difference_type;
-  difference_type __counters[traits::radix_count][traits::radix_value_range] = {{0}};
-  difference_type __maximums[traits::radix_count]                            = {0};
+  difference_type __counters[traits::__radix_count][traits::__radix_value_range] = {{0}};
+  difference_type __maximums[traits::__radix_count]                              = {0};
   const auto __is_sorted = std::__collect(__first, __last, __map, __radix, __counters, __maximums);
   if (not __is_sorted) {
     const auto __range_size = std::distance(__first, __last);
     auto __buffer_end       = __buffer_begin + __range_size;
-    for (size_t __radix_number = 0; __radix_number < traits::radix_count; __radix_number += 2) {
+    for (size_t __radix_number = 0; __radix_number < traits::__radix_count; __radix_number += 2) {
       const auto __n0th_is_single = __maximums[__radix_number] == __range_size;
       const auto __n1th_is_single = __maximums[__radix_number + 1] == __range_size;
 

>From 7dfbf48251274100e6798a61350b7a3c564e4248 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=94=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9=20=D0=98=D0=B7?=
 =?UTF-8?q?=D0=B2=D0=BE=D0=BB=D0=BE=D0=B2?= <dmitriy at izvolov.ru>
Date: Wed, 21 Aug 2024 00:37:52 +0300
Subject: [PATCH 16/46] class-not-typename

---
 libcxx/include/__algorithm/radix_sort.h | 68 +++++++++++--------------
 1 file changed, 29 insertions(+), 39 deletions(-)

diff --git a/libcxx/include/__algorithm/radix_sort.h b/libcxx/include/__algorithm/radix_sort.h
index e3de71a417ceab..9827e1aa4a53b9 100644
--- a/libcxx/include/__algorithm/radix_sort.h
+++ b/libcxx/include/__algorithm/radix_sort.h
@@ -51,20 +51,20 @@ inline _LIBCPP_HIDE_FROM_ABI void __variadic_expansion_dummy(initializer_list<in
 
 #  define _EXPAND_VARIADIC(expression) std::__variadic_expansion_dummy({(expression, 0)...})
 
-template <typename _Iterator>
+template <class _Iterator>
 _LIBCPP_HIDE_FROM_ABI constexpr auto __move_assign_please(_Iterator __i)
     -> enable_if_t<is_move_assignable<typename iterator_traits<_Iterator>::value_type>::value,
                    move_iterator<_Iterator> > {
   return std::make_move_iterator(std::move(__i));
 }
 
-template <typename _Iterator>
+template <class _Iterator>
 _LIBCPP_HIDE_FROM_ABI constexpr auto __move_assign_please(_Iterator __i)
     -> enable_if_t<not is_move_assignable<typename iterator_traits<_Iterator>::value_type>::value, _Iterator> {
   return __i;
 }
 
-template <typename _UnsignedInteger>
+template <class _UnsignedInteger>
 _LIBCPP_HIDE_FROM_ABI constexpr _UnsignedInteger __intlog2(_UnsignedInteger __n) {
   static_assert(is_integral<_UnsignedInteger>::value, "Must be an integral type");
   static_assert(is_unsigned<_UnsignedInteger>::value, "Must be unsigned");
@@ -72,7 +72,7 @@ _LIBCPP_HIDE_FROM_ABI constexpr _UnsignedInteger __intlog2(_UnsignedInteger __n)
   return numeric_limits<_UnsignedInteger>::digits - 1 - std::__countl_zero(__n);
 }
 
-template <typename _InputIterator, typename _OutputIterator>
+template <class _InputIterator, class _OutputIterator>
 _LIBCPP_HIDE_FROM_ABI pair<_OutputIterator, typename iterator_traits<_InputIterator>::value_type>
 __partial_sum_max(_InputIterator __first, _InputIterator __last, _OutputIterator __result) {
   if (__first == __last)
@@ -92,7 +92,7 @@ __partial_sum_max(_InputIterator __first, _InputIterator __last, _OutputIterator
   return {++__result, __max};
 }
 
-template <typename _Value, typename _Map, typename _Radix>
+template <class _Value, class _Map, class _Radix>
 struct __radix_sort_traits {
   using image_type = decay_t<invoke_result_t<_Map, _Value> >;
   static_assert(is_integral<image_type>::value, "");
@@ -106,7 +106,7 @@ struct __radix_sort_traits {
   constexpr static auto __radix_count       = sizeof(image_type) * CHAR_BIT / __radix_size;
 };
 
-template <typename _Value, typename _Map>
+template <class _Value, class _Map>
 struct __counting_sort_traits {
   using image_type = decay_t<invoke_result_t<_Map, _Value> >;
   static_assert(is_integral<image_type>::value, "");
@@ -116,7 +116,7 @@ struct __counting_sort_traits {
   constexpr static auto __radix_size        = std::__intlog2<uint64_t>(__value_range);
 };
 
-template <typename _Radix>
+template <class _Radix>
 _LIBCPP_HIDE_FROM_ABI auto __nth_radix(size_t __radix_number, _Radix __radix) {
   return [__radix_number, __radix = std::move(__radix)](auto __n) {
     using value_type = decltype(__n);
@@ -128,13 +128,13 @@ _LIBCPP_HIDE_FROM_ABI auto __nth_radix(size_t __radix_number, _Radix __radix) {
   };
 }
 
-template <typename _ForwardIterator, typename _Map, typename _RandomAccessIterator>
+template <class _ForwardIterator, class _Map, class _RandomAccessIterator>
 _LIBCPP_HIDE_FROM_ABI void
 __count(_ForwardIterator __first, _ForwardIterator __last, _Map __map, _RandomAccessIterator __counters) {
   std::for_each(__first, __last, [&__counters, &__map](const auto& __preimage) { ++__counters[__map(__preimage)]; });
 }
 
-template <typename _ForwardIterator, typename _Map, typename _RandomAccessIterator>
+template <class _ForwardIterator, class _Map, class _RandomAccessIterator>
 _LIBCPP_HIDE_FROM_ABI void
 __collect(_ForwardIterator __first, _ForwardIterator __last, _Map __map, _RandomAccessIterator __counters) {
   using value_type = typename iterator_traits<_ForwardIterator>::value_type;
@@ -146,7 +146,7 @@ __collect(_ForwardIterator __first, _ForwardIterator __last, _Map __map, _Random
   std::partial_sum(__counters, __counters_end, __counters);
 }
 
-template <typename _ForwardIterator, typename _RandomAccessIterator1, typename _Map, typename _RandomAccessIterator2>
+template <class _ForwardIterator, class _RandomAccessIterator1, class _Map, class _RandomAccessIterator2>
 _LIBCPP_HIDE_FROM_ABI void
 __dispose(_ForwardIterator __first,
           _ForwardIterator __last,
@@ -159,10 +159,7 @@ __dispose(_ForwardIterator __first,
   });
 }
 
-template <typename _BidirectionalIterator,
-          typename _RandomAccessIterator1,
-          typename _Map,
-          typename _RandomAccessIterator2>
+template <class _BidirectionalIterator, class _RandomAccessIterator1, class _Map, class _RandomAccessIterator2>
 _LIBCPP_HIDE_FROM_ABI void dispose_backward(
     _BidirectionalIterator __first,
     _BidirectionalIterator __last,
@@ -177,11 +174,11 @@ _LIBCPP_HIDE_FROM_ABI void dispose_backward(
                 });
 }
 
-template <typename _ForwardIterator,
-          typename _Map,
-          typename _Radix,
-          typename _RandomAccessIterator1,
-          typename _RandomAccessIterator2,
+template <class _ForwardIterator,
+          class _Map,
+          class _Radix,
+          class _RandomAccessIterator1,
+          class _RandomAccessIterator2,
           size_t... _Radices>
 _LIBCPP_HIDE_FROM_ABI bool __collect_impl(
     _ForwardIterator __first,
@@ -212,11 +209,7 @@ _LIBCPP_HIDE_FROM_ABI bool __collect_impl(
   return __is_sorted;
 }
 
-template <typename _ForwardIterator,
-          typename _Map,
-          typename _Radix,
-          typename _RandomAccessIterator1,
-          typename _RandomAccessIterator2>
+template <class _ForwardIterator, class _Map, class _Radix, class _RandomAccessIterator1, class _RandomAccessIterator2>
 _LIBCPP_HIDE_FROM_ABI bool
 __collect(_ForwardIterator __first,
           _ForwardIterator __last,
@@ -230,10 +223,7 @@ __collect(_ForwardIterator __first,
       __first, __last, __map, __radix, __counters, __maximums, make_index_sequence<__radix_count>());
 }
 
-template <typename _BidirectionalIterator,
-          typename _RandomAccessIterator1,
-          typename _Map,
-          typename _RandomAccessIterator2>
+template <class _BidirectionalIterator, class _RandomAccessIterator1, class _Map, class _RandomAccessIterator2>
 _LIBCPP_HIDE_FROM_ABI void __dispose_backward(
     _BidirectionalIterator __first,
     _BidirectionalIterator __last,
@@ -248,7 +238,7 @@ _LIBCPP_HIDE_FROM_ABI void __dispose_backward(
                 });
 }
 
-template <typename _ForwardIterator, typename _RandomAccessIterator, typename _Map>
+template <class _ForwardIterator, class _RandomAccessIterator, class _Map>
 _LIBCPP_HIDE_FROM_ABI _RandomAccessIterator
 __counting_sort_impl(_ForwardIterator __first, _ForwardIterator __last, _RandomAccessIterator __result, _Map __map) {
   using value_type = typename iterator_traits<_ForwardIterator>::value_type;
@@ -263,7 +253,7 @@ __counting_sort_impl(_ForwardIterator __first, _ForwardIterator __last, _RandomA
   return __result + __counters[traits::__value_range];
 }
 
-template <typename _RandomAccessIterator1, typename _RandomAccessIterator2, typename _Map, typename _Radix>
+template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _Map, class _Radix>
 _LIBCPP_HIDE_FROM_ABI typename enable_if<
     __radix_sort_traits<typename iterator_traits<_RandomAccessIterator1>::value_type, _Map, _Radix>::__radix_count == 1,
     void>::type
@@ -281,7 +271,7 @@ __radix_sort_impl(_RandomAccessIterator1 __first,
   std::copy(std::__move_assign_please(buffer), std::__move_assign_please(__buffer_end), __first);
 }
 
-template <typename _RandomAccessIterator1, typename _RandomAccessIterator2, typename _Map, typename _Radix>
+template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _Map, class _Radix>
 _LIBCPP_HIDE_FROM_ABI typename enable_if<
     __radix_sort_traits<typename iterator_traits<_RandomAccessIterator1>::value_type, _Map, _Radix>::__radix_count %
             2 ==
@@ -343,21 +333,21 @@ __radix_sort_impl(_RandomAccessIterator1 __first,
 
 _LIBCPP_HIDE_FROM_ABI constexpr auto __to_unsigned(bool __b) { return __b; }
 
-template <typename _Ip>
+template <class _Ip>
 _LIBCPP_HIDE_FROM_ABI constexpr auto __to_unsigned(_Ip __n) {
   constexpr const auto __min_value = numeric_limits<_Ip>::min();
   return static_cast<make_unsigned_t<_Ip> >(__n ^ __min_value);
 }
 
 struct __identity_fn {
-  template <typename _Tp>
+  template <class _Tp>
   _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) operator()(_Tp&& __value) const {
     return std::forward<_Tp>(__value);
   }
 };
 
 struct __low_byte_fn {
-  template <typename _Ip>
+  template <class _Ip>
   _LIBCPP_HIDE_FROM_ABI constexpr uint8_t operator()(_Ip __integer) const {
     static_assert(is_integral<_Ip>::value, "");
     static_assert(is_unsigned<_Ip>::value, "");
@@ -366,7 +356,7 @@ struct __low_byte_fn {
   }
 };
 
-template <typename _RandomAccessIterator1, typename _RandomAccessIterator2, typename _Map, typename _Radix>
+template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _Map, class _Radix>
 _LIBCPP_HIDE_FROM_ABI void
 __radix_sort(_RandomAccessIterator1 __first,
              _RandomAccessIterator1 __last,
@@ -377,20 +367,20 @@ __radix_sort(_RandomAccessIterator1 __first,
   std::__radix_sort_impl(__first, __last, buffer, __map_to_unsigned, __radix);
 }
 
-template <typename _RandomAccessIterator1, typename _RandomAccessIterator2>
+template <class _RandomAccessIterator1, class _RandomAccessIterator2>
 _LIBCPP_HIDE_FROM_ABI void
 __radix_sort(_RandomAccessIterator1 __first, _RandomAccessIterator1 __last, _RandomAccessIterator2 buffer) {
   std::__radix_sort(__first, __last, buffer, __identity_fn{}, __low_byte_fn{});
 }
 
-template <typename _RandomAccessIterator1, typename _RandomAccessIterator2>
+template <class _RandomAccessIterator1, class _RandomAccessIterator2>
 _LIBCPP_HIDE_FROM_ABI bool __radix_sort(
     _RandomAccessIterator1 __first, _RandomAccessIterator1 __last, _RandomAccessIterator2 buffer, _BoolConstant<true>) {
   std::__radix_sort(__first, __last, buffer, __identity_fn{}, __low_byte_fn{});
   return true;
 }
 
-template <typename _RandomAccessIterator1, typename _RandomAccessIterator2>
+template <class _RandomAccessIterator1, class _RandomAccessIterator2>
 _LIBCPP_HIDE_FROM_ABI bool
 __radix_sort(_RandomAccessIterator1, _RandomAccessIterator1, _RandomAccessIterator2, _BoolConstant<false>) {
   return false;
@@ -400,7 +390,7 @@ __radix_sort(_RandomAccessIterator1, _RandomAccessIterator1, _RandomAccessIterat
 
 #else // _LIBCPP_STD_VER > 14
 
-template <typename _RandomAccessIterator1, typename _RandomAccessIterator2, bool _EnableRadixSort>
+template <class _RandomAccessIterator1, class _RandomAccessIterator2, bool _EnableRadixSort>
 _LIBCPP_HIDE_FROM_ABI bool
 __radix_sort(_RandomAccessIterator1, _RandomAccessIterator1, _RandomAccessIterator2, _BoolConstant<_EnableRadixSort>) {
   return false;

>From a67ba1042b58096bc070eef24f42455f31bdf41c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=94=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9=20=D0=98=D0=B7?=
 =?UTF-8?q?=D0=B2=D0=BE=D0=BB=D0=BE=D0=B2?= <dmitriy at izvolov.ru>
Date: Wed, 21 Aug 2024 00:43:15 +0300
Subject: [PATCH 17/46] no-trailing-return

---
 libcxx/include/__algorithm/radix_sort.h | 13 ++++++-------
 1 file changed, 6 insertions(+), 7 deletions(-)

diff --git a/libcxx/include/__algorithm/radix_sort.h b/libcxx/include/__algorithm/radix_sort.h
index 9827e1aa4a53b9..98ca9e7a5a6431 100644
--- a/libcxx/include/__algorithm/radix_sort.h
+++ b/libcxx/include/__algorithm/radix_sort.h
@@ -51,16 +51,15 @@ inline _LIBCPP_HIDE_FROM_ABI void __variadic_expansion_dummy(initializer_list<in
 
 #  define _EXPAND_VARIADIC(expression) std::__variadic_expansion_dummy({(expression, 0)...})
 
-template <class _Iterator>
-_LIBCPP_HIDE_FROM_ABI constexpr auto __move_assign_please(_Iterator __i)
-    -> enable_if_t<is_move_assignable<typename iterator_traits<_Iterator>::value_type>::value,
-                   move_iterator<_Iterator> > {
+template <class _Iterator,
+          enable_if_t<is_move_assignable<typename iterator_traits<_Iterator>::value_type>::value, int> = 0>
+_LIBCPP_HIDE_FROM_ABI constexpr move_iterator<_Iterator> __move_assign_please(_Iterator __i) {
   return std::make_move_iterator(std::move(__i));
 }
 
-template <class _Iterator>
-_LIBCPP_HIDE_FROM_ABI constexpr auto __move_assign_please(_Iterator __i)
-    -> enable_if_t<not is_move_assignable<typename iterator_traits<_Iterator>::value_type>::value, _Iterator> {
+template <class _Iterator,
+          enable_if_t<!is_move_assignable<typename iterator_traits<_Iterator>::value_type>::value, int> = 0>
+_LIBCPP_HIDE_FROM_ABI constexpr _Iterator __move_assign_please(_Iterator __i) {
   return __i;
 }
 

>From 0b49a86203e239b388ed4ffda2b201bc76787ce1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=94=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9=20=D0=98=D0=B7?=
 =?UTF-8?q?=D0=B2=D0=BE=D0=BB=D0=BE=D0=B2?= <dmitriy at izvolov.ru>
Date: Wed, 21 Aug 2024 01:18:46 +0300
Subject: [PATCH 18/46] redundancy

---
 libcxx/include/__algorithm/radix_sort.h | 7 +------
 1 file changed, 1 insertion(+), 6 deletions(-)

diff --git a/libcxx/include/__algorithm/radix_sort.h b/libcxx/include/__algorithm/radix_sort.h
index 98ca9e7a5a6431..2dfc61c811d1bd 100644
--- a/libcxx/include/__algorithm/radix_sort.h
+++ b/libcxx/include/__algorithm/radix_sort.h
@@ -65,8 +65,7 @@ _LIBCPP_HIDE_FROM_ABI constexpr _Iterator __move_assign_please(_Iterator __i) {
 
 template <class _UnsignedInteger>
 _LIBCPP_HIDE_FROM_ABI constexpr _UnsignedInteger __intlog2(_UnsignedInteger __n) {
-  static_assert(is_integral<_UnsignedInteger>::value, "Must be an integral type");
-  static_assert(is_unsigned<_UnsignedInteger>::value, "Must be unsigned");
+  static_assert(is_unsigned<_UnsignedInteger>::value, "Must be unsigned integral");
 
   return numeric_limits<_UnsignedInteger>::digits - 1 - std::__countl_zero(__n);
 }
@@ -94,7 +93,6 @@ __partial_sum_max(_InputIterator __first, _InputIterator __last, _OutputIterator
 template <class _Value, class _Map, class _Radix>
 struct __radix_sort_traits {
   using image_type = decay_t<invoke_result_t<_Map, _Value> >;
-  static_assert(is_integral<image_type>::value, "");
   static_assert(is_unsigned<image_type>::value, "");
 
   using radix_type = decay_t<invoke_result_t<_Radix, image_type> >;
@@ -108,7 +106,6 @@ struct __radix_sort_traits {
 template <class _Value, class _Map>
 struct __counting_sort_traits {
   using image_type = decay_t<invoke_result_t<_Map, _Value> >;
-  static_assert(is_integral<image_type>::value, "");
   static_assert(is_unsigned<image_type>::value, "");
 
   constexpr static const auto __value_range = numeric_limits<image_type>::max() + 1;
@@ -119,7 +116,6 @@ template <class _Radix>
 _LIBCPP_HIDE_FROM_ABI auto __nth_radix(size_t __radix_number, _Radix __radix) {
   return [__radix_number, __radix = std::move(__radix)](auto __n) {
     using value_type = decltype(__n);
-    static_assert(is_integral<value_type>::value, "");
     static_assert(is_unsigned<value_type>::value, "");
     using traits = __counting_sort_traits<value_type, _Radix>;
 
@@ -348,7 +344,6 @@ struct __identity_fn {
 struct __low_byte_fn {
   template <class _Ip>
   _LIBCPP_HIDE_FROM_ABI constexpr uint8_t operator()(_Ip __integer) const {
-    static_assert(is_integral<_Ip>::value, "");
     static_assert(is_unsigned<_Ip>::value, "");
 
     return static_cast<uint8_t>(__integer & 0xff);

>From 799a6d71da472b2fafca769a06cf0f8c71282784 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=94=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9=20=D0=98=D0=B7?=
 =?UTF-8?q?=D0=B2=D0=BE=D0=BB=D0=BE=D0=B2?= <dmitriy at izvolov.ru>
Date: Wed, 21 Aug 2024 01:30:11 +0300
Subject: [PATCH 19/46] rm-count

---
 libcxx/include/__algorithm/radix_sort.h | 8 +-------
 1 file changed, 1 insertion(+), 7 deletions(-)

diff --git a/libcxx/include/__algorithm/radix_sort.h b/libcxx/include/__algorithm/radix_sort.h
index 2dfc61c811d1bd..2ba2456c5a0489 100644
--- a/libcxx/include/__algorithm/radix_sort.h
+++ b/libcxx/include/__algorithm/radix_sort.h
@@ -123,19 +123,13 @@ _LIBCPP_HIDE_FROM_ABI auto __nth_radix(size_t __radix_number, _Radix __radix) {
   };
 }
 
-template <class _ForwardIterator, class _Map, class _RandomAccessIterator>
-_LIBCPP_HIDE_FROM_ABI void
-__count(_ForwardIterator __first, _ForwardIterator __last, _Map __map, _RandomAccessIterator __counters) {
-  std::for_each(__first, __last, [&__counters, &__map](const auto& __preimage) { ++__counters[__map(__preimage)]; });
-}
-
 template <class _ForwardIterator, class _Map, class _RandomAccessIterator>
 _LIBCPP_HIDE_FROM_ABI void
 __collect(_ForwardIterator __first, _ForwardIterator __last, _Map __map, _RandomAccessIterator __counters) {
   using value_type = typename iterator_traits<_ForwardIterator>::value_type;
   using traits     = __counting_sort_traits<value_type, _Map>;
 
-  std::__count(__first, __last, __map, __counters);
+  std::for_each(__first, __last, [&__counters, &__map](const auto& __preimage) { ++__counters[__map(__preimage)]; });
 
   const auto __counters_end = __counters + traits::__value_range;
   std::partial_sum(__counters, __counters_end, __counters);

>From 4e9054246981d82691f7b5a3a5c51c15d201f60f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=94=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9=20=D0=98=D0=B7?=
 =?UTF-8?q?=D0=B2=D0=BE=D0=BB=D0=BE=D0=B2?= <dmitriy at izvolov.ru>
Date: Wed, 21 Aug 2024 01:30:26 +0300
Subject: [PATCH 20/46] rm-duplicate

---
 libcxx/include/__algorithm/radix_sort.h | 21 +++------------------
 1 file changed, 3 insertions(+), 18 deletions(-)

diff --git a/libcxx/include/__algorithm/radix_sort.h b/libcxx/include/__algorithm/radix_sort.h
index 2ba2456c5a0489..6ac41d7d3f25ca 100644
--- a/libcxx/include/__algorithm/radix_sort.h
+++ b/libcxx/include/__algorithm/radix_sort.h
@@ -148,21 +148,6 @@ __dispose(_ForwardIterator __first,
   });
 }
 
-template <class _BidirectionalIterator, class _RandomAccessIterator1, class _Map, class _RandomAccessIterator2>
-_LIBCPP_HIDE_FROM_ABI void dispose_backward(
-    _BidirectionalIterator __first,
-    _BidirectionalIterator __last,
-    _RandomAccessIterator1 __result,
-    _Map __map,
-    _RandomAccessIterator2 __counters) {
-  std::for_each(std::make_reverse_iterator(__last),
-                std::make_reverse_iterator(__first),
-                [&__result, &__counters, &__map](auto&& __preimage) {
-                  auto __index      = --__counters[__map(__preimage)];
-                  __result[__index] = std::forward<decltype(__preimage)>(__preimage);
-                });
-}
-
 template <class _ForwardIterator,
           class _Map,
           class _Radix,
@@ -221,9 +206,9 @@ _LIBCPP_HIDE_FROM_ABI void __dispose_backward(
     _RandomAccessIterator2 __counters) {
   std::for_each(std::make_reverse_iterator(__last),
                 std::make_reverse_iterator(__first),
-                [&__result, &__counters, &__map](auto&& preimage) {
-                  auto __index      = --__counters[__map(preimage)];
-                  __result[__index] = std::forward<decltype(preimage)>(preimage);
+                [&__result, &__counters, &__map](auto&& __preimage) {
+                  auto __index      = --__counters[__map(__preimage)];
+                  __result[__index] = std::forward<decltype(__preimage)>(__preimage);
                 });
 }
 

>From 5871042b6c1a61809c32940f495fe218c12b19b6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=94=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9=20=D0=98=D0=B7?=
 =?UTF-8?q?=D0=B2=D0=BE=D0=BB=D0=BE=D0=B2?= <dmitriy at izvolov.ru>
Date: Wed, 21 Aug 2024 01:33:40 +0300
Subject: [PATCH 21/46] identity

---
 libcxx/include/__algorithm/radix_sort.h | 12 +++---------
 1 file changed, 3 insertions(+), 9 deletions(-)

diff --git a/libcxx/include/__algorithm/radix_sort.h b/libcxx/include/__algorithm/radix_sort.h
index 6ac41d7d3f25ca..43288bee69de5a 100644
--- a/libcxx/include/__algorithm/radix_sort.h
+++ b/libcxx/include/__algorithm/radix_sort.h
@@ -14,6 +14,7 @@
 #include <__algorithm/for_each.h>
 #include <__bit/countl.h>
 #include <__config>
+#include <__functional/identity.h>
 #include <__iterator/distance.h>
 #include <__iterator/iterator_traits.h>
 #include <__iterator/move_iterator.h>
@@ -313,13 +314,6 @@ _LIBCPP_HIDE_FROM_ABI constexpr auto __to_unsigned(_Ip __n) {
   return static_cast<make_unsigned_t<_Ip> >(__n ^ __min_value);
 }
 
-struct __identity_fn {
-  template <class _Tp>
-  _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) operator()(_Tp&& __value) const {
-    return std::forward<_Tp>(__value);
-  }
-};
-
 struct __low_byte_fn {
   template <class _Ip>
   _LIBCPP_HIDE_FROM_ABI constexpr uint8_t operator()(_Ip __integer) const {
@@ -343,13 +337,13 @@ __radix_sort(_RandomAccessIterator1 __first,
 template <class _RandomAccessIterator1, class _RandomAccessIterator2>
 _LIBCPP_HIDE_FROM_ABI void
 __radix_sort(_RandomAccessIterator1 __first, _RandomAccessIterator1 __last, _RandomAccessIterator2 buffer) {
-  std::__radix_sort(__first, __last, buffer, __identity_fn{}, __low_byte_fn{});
+  std::__radix_sort(__first, __last, buffer, __identity{}, __low_byte_fn{});
 }
 
 template <class _RandomAccessIterator1, class _RandomAccessIterator2>
 _LIBCPP_HIDE_FROM_ABI bool __radix_sort(
     _RandomAccessIterator1 __first, _RandomAccessIterator1 __last, _RandomAccessIterator2 buffer, _BoolConstant<true>) {
-  std::__radix_sort(__first, __last, buffer, __identity_fn{}, __low_byte_fn{});
+  std::__radix_sort(__first, __last, buffer, __identity{}, __low_byte_fn{});
   return true;
 }
 

>From 6958232376f3cb5626d45bfb6a40f3faf1b0622d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=94=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9=20=D0=98=D0=B7?=
 =?UTF-8?q?=D0=B2=D0=BE=D0=BB=D0=BE=D0=B2?= <dmitriy at izvolov.ru>
Date: Wed, 21 Aug 2024 09:12:30 +0300
Subject: [PATCH 22/46] rm-expand-variadic-macro

---
 libcxx/include/__algorithm/radix_sort.h | 16 +++++-----------
 1 file changed, 5 insertions(+), 11 deletions(-)

diff --git a/libcxx/include/__algorithm/radix_sort.h b/libcxx/include/__algorithm/radix_sort.h
index 43288bee69de5a..01b81fffbd4290 100644
--- a/libcxx/include/__algorithm/radix_sort.h
+++ b/libcxx/include/__algorithm/radix_sort.h
@@ -48,10 +48,6 @@ _LIBCPP_BEGIN_NAMESPACE_STD
 
 #if _LIBCPP_STD_VER >= 14
 
-inline _LIBCPP_HIDE_FROM_ABI void __variadic_expansion_dummy(initializer_list<int>) {}
-
-#  define _EXPAND_VARIADIC(expression) std::__variadic_expansion_dummy({(expression, 0)...})
-
 template <class _Iterator,
           enable_if_t<is_move_assignable<typename iterator_traits<_Iterator>::value_type>::value, int> = 0>
 _LIBCPP_HIDE_FROM_ABI constexpr move_iterator<_Iterator> __move_assign_please(_Iterator __i) {
@@ -173,13 +169,13 @@ _LIBCPP_HIDE_FROM_ABI bool __collect_impl(
     __is_sorted &= (__current >= __previous);
     __previous = __current;
 
-    _EXPAND_VARIADIC(++__counters[_Radices][std::__nth_radix(_Radices, __radix)(__current)]);
+    (++__counters[_Radices][std::__nth_radix(_Radices, __radix)(__current)], ...);
   });
 
-  _EXPAND_VARIADIC(
-      __maximums[_Radices] =
-          std::__partial_sum_max(__counters[_Radices], __counters[_Radices] + __radix_value_range, __counters[_Radices])
-              .second);
+  ((__maximums[_Radices] =
+        std::__partial_sum_max(__counters[_Radices], __counters[_Radices] + __radix_value_range, __counters[_Radices])
+            .second),
+   ...);
 
   return __is_sorted;
 }
@@ -353,8 +349,6 @@ __radix_sort(_RandomAccessIterator1, _RandomAccessIterator1, _RandomAccessIterat
   return false;
 }
 
-#  undef _EXPAND_VARIADIC
-
 #else // _LIBCPP_STD_VER > 14
 
 template <class _RandomAccessIterator1, class _RandomAccessIterator2, bool _EnableRadixSort>

>From 5665f753f342fb66e44aac210c6520b559e57eaf Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=94=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9=20=D0=98=D0=B7?=
 =?UTF-8?q?=D0=B2=D0=BE=D0=BB=D0=BE=D0=B2?= <dmitriy at izvolov.ru>
Date: Wed, 21 Aug 2024 12:12:29 +0300
Subject: [PATCH 23/46] iter-value

---
 libcxx/include/__algorithm/radix_sort.h | 34 +++++++++++--------------
 1 file changed, 15 insertions(+), 19 deletions(-)

diff --git a/libcxx/include/__algorithm/radix_sort.h b/libcxx/include/__algorithm/radix_sort.h
index 01b81fffbd4290..a68f023e29e036 100644
--- a/libcxx/include/__algorithm/radix_sort.h
+++ b/libcxx/include/__algorithm/radix_sort.h
@@ -48,14 +48,12 @@ _LIBCPP_BEGIN_NAMESPACE_STD
 
 #if _LIBCPP_STD_VER >= 14
 
-template <class _Iterator,
-          enable_if_t<is_move_assignable<typename iterator_traits<_Iterator>::value_type>::value, int> = 0>
+template <class _Iterator, enable_if_t<is_move_assignable<__iter_value_type<_Iterator>>::value, int> = 0>
 _LIBCPP_HIDE_FROM_ABI constexpr move_iterator<_Iterator> __move_assign_please(_Iterator __i) {
   return std::make_move_iterator(std::move(__i));
 }
 
-template <class _Iterator,
-          enable_if_t<!is_move_assignable<typename iterator_traits<_Iterator>::value_type>::value, int> = 0>
+template <class _Iterator, enable_if_t<!is_move_assignable<__iter_value_type<_Iterator>>::value, int> = 0>
 _LIBCPP_HIDE_FROM_ABI constexpr _Iterator __move_assign_please(_Iterator __i) {
   return __i;
 }
@@ -68,14 +66,14 @@ _LIBCPP_HIDE_FROM_ABI constexpr _UnsignedInteger __intlog2(_UnsignedInteger __n)
 }
 
 template <class _InputIterator, class _OutputIterator>
-_LIBCPP_HIDE_FROM_ABI pair<_OutputIterator, typename iterator_traits<_InputIterator>::value_type>
+_LIBCPP_HIDE_FROM_ABI pair<_OutputIterator, __iter_value_type<_InputIterator>>
 __partial_sum_max(_InputIterator __first, _InputIterator __last, _OutputIterator __result) {
   if (__first == __last)
     return {__result, 0};
 
-  auto __max                                                 = *__first;
-  typename iterator_traits<_InputIterator>::value_type __sum = *__first;
-  *__result                                                  = __sum;
+  auto __max                              = *__first;
+  __iter_value_type<_InputIterator> __sum = *__first;
+  *__result                               = __sum;
 
   while (++__first != __last) {
     if (__max < *__first) {
@@ -123,7 +121,7 @@ _LIBCPP_HIDE_FROM_ABI auto __nth_radix(size_t __radix_number, _Radix __radix) {
 template <class _ForwardIterator, class _Map, class _RandomAccessIterator>
 _LIBCPP_HIDE_FROM_ABI void
 __collect(_ForwardIterator __first, _ForwardIterator __last, _Map __map, _RandomAccessIterator __counters) {
-  using value_type = typename iterator_traits<_ForwardIterator>::value_type;
+  using value_type = __iter_value_type<_ForwardIterator>;
   using traits     = __counting_sort_traits<value_type, _Map>;
 
   std::for_each(__first, __last, [&__counters, &__map](const auto& __preimage) { ++__counters[__map(__preimage)]; });
@@ -159,7 +157,7 @@ _LIBCPP_HIDE_FROM_ABI bool __collect_impl(
     _RandomAccessIterator1 __counters,
     _RandomAccessIterator2 __maximums,
     index_sequence<_Radices...>) {
-  using value_type                   = typename iterator_traits<_ForwardIterator>::value_type;
+  using value_type                   = __iter_value_type<_ForwardIterator>;
   constexpr auto __radix_value_range = __radix_sort_traits<value_type, _Map, _Radix>::__radix_value_range;
 
   auto __previous  = numeric_limits<invoke_result_t<_Map, value_type> >::min();
@@ -188,7 +186,7 @@ __collect(_ForwardIterator __first,
           _Radix __radix,
           _RandomAccessIterator1 __counters,
           _RandomAccessIterator2 __maximums) {
-  using value_type             = typename iterator_traits<_ForwardIterator>::value_type;
+  using value_type             = __iter_value_type<_ForwardIterator>;
   constexpr auto __radix_count = __radix_sort_traits<value_type, _Map, _Radix>::__radix_count;
   return std::__collect_impl(
       __first, __last, __map, __radix, __counters, __maximums, make_index_sequence<__radix_count>());
@@ -212,7 +210,7 @@ _LIBCPP_HIDE_FROM_ABI void __dispose_backward(
 template <class _ForwardIterator, class _RandomAccessIterator, class _Map>
 _LIBCPP_HIDE_FROM_ABI _RandomAccessIterator
 __counting_sort_impl(_ForwardIterator __first, _ForwardIterator __last, _RandomAccessIterator __result, _Map __map) {
-  using value_type = typename iterator_traits<_ForwardIterator>::value_type;
+  using value_type = __iter_value_type<_ForwardIterator>;
   using traits     = __counting_sort_traits<value_type, _Map>;
 
   using difference_type = typename iterator_traits<_RandomAccessIterator>::difference_type;
@@ -225,9 +223,9 @@ __counting_sort_impl(_ForwardIterator __first, _ForwardIterator __last, _RandomA
 }
 
 template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _Map, class _Radix>
-_LIBCPP_HIDE_FROM_ABI typename enable_if<
-    __radix_sort_traits<typename iterator_traits<_RandomAccessIterator1>::value_type, _Map, _Radix>::__radix_count == 1,
-    void>::type
+_LIBCPP_HIDE_FROM_ABI
+typename enable_if< __radix_sort_traits<__iter_value_type<_RandomAccessIterator1>, _Map, _Radix>::__radix_count == 1,
+                    void>::type
 __radix_sort_impl(_RandomAccessIterator1 __first,
                   _RandomAccessIterator1 __last,
                   _RandomAccessIterator2 buffer,
@@ -244,16 +242,14 @@ __radix_sort_impl(_RandomAccessIterator1 __first,
 
 template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _Map, class _Radix>
 _LIBCPP_HIDE_FROM_ABI typename enable_if<
-    __radix_sort_traits<typename iterator_traits<_RandomAccessIterator1>::value_type, _Map, _Radix>::__radix_count %
-            2 ==
-        0,
+    __radix_sort_traits<__iter_value_type<_RandomAccessIterator1>, _Map, _Radix>::__radix_count % 2 == 0,
     void>::type
 __radix_sort_impl(_RandomAccessIterator1 __first,
                   _RandomAccessIterator1 __last,
                   _RandomAccessIterator2 __buffer_begin,
                   _Map __map,
                   _Radix __radix) {
-  using value_type = typename iterator_traits<_RandomAccessIterator1>::value_type;
+  using value_type = __iter_value_type<_RandomAccessIterator1>;
   using traits     = __radix_sort_traits<value_type, _Map, _Radix>;
 
   using difference_type = typename iterator_traits<_RandomAccessIterator1>::difference_type;

>From c1cb87b6066bcea54d6a89e67cf80cbd3a5d67b6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=94=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9=20=D0=98=D0=B7?=
 =?UTF-8?q?=D0=B2=D0=BE=D0=BB=D0=BE=D0=B2?= <dmitriy at izvolov.ru>
Date: Wed, 21 Aug 2024 12:17:31 +0300
Subject: [PATCH 24/46] iter-diff-t

---
 libcxx/include/__algorithm/radix_sort.h | 8 +++-----
 1 file changed, 3 insertions(+), 5 deletions(-)

diff --git a/libcxx/include/__algorithm/radix_sort.h b/libcxx/include/__algorithm/radix_sort.h
index a68f023e29e036..cba56e75814a78 100644
--- a/libcxx/include/__algorithm/radix_sort.h
+++ b/libcxx/include/__algorithm/radix_sort.h
@@ -213,8 +213,7 @@ __counting_sort_impl(_ForwardIterator __first, _ForwardIterator __last, _RandomA
   using value_type = __iter_value_type<_ForwardIterator>;
   using traits     = __counting_sort_traits<value_type, _Map>;
 
-  using difference_type = typename iterator_traits<_RandomAccessIterator>::difference_type;
-  difference_type __counters[traits::__value_range + 1] = {0};
+  __iter_diff_t<_RandomAccessIterator> __counters[traits::__value_range + 1] = {0};
 
   std::__collect(__first, __last, __map, std::next(std::begin(__counters)));
   std::__dispose(__first, __last, __result, __map, std::begin(__counters));
@@ -252,9 +251,8 @@ __radix_sort_impl(_RandomAccessIterator1 __first,
   using value_type = __iter_value_type<_RandomAccessIterator1>;
   using traits     = __radix_sort_traits<value_type, _Map, _Radix>;
 
-  using difference_type = typename iterator_traits<_RandomAccessIterator1>::difference_type;
-  difference_type __counters[traits::__radix_count][traits::__radix_value_range] = {{0}};
-  difference_type __maximums[traits::__radix_count]                              = {0};
+  __iter_diff_t<_RandomAccessIterator1> __counters[traits::__radix_count][traits::__radix_value_range] = {{0}};
+  __iter_diff_t<_RandomAccessIterator1> __maximums[traits::__radix_count]                              = {0};
   const auto __is_sorted = std::__collect(__first, __last, __map, __radix, __counters, __maximums);
   if (not __is_sorted) {
     const auto __range_size = std::distance(__first, __last);

>From e4fa01258c2fc48cc8b58963e7567fed14f02fac Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=94=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9=20=D0=98=D0=B7?=
 =?UTF-8?q?=D0=B2=D0=BE=D0=BB=D0=BE=D0=B2?= <dmitriy at izvolov.ru>
Date: Wed, 21 Aug 2024 12:22:43 +0300
Subject: [PATCH 25/46] uglify-more

---
 libcxx/include/__algorithm/radix_sort.h | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/libcxx/include/__algorithm/radix_sort.h b/libcxx/include/__algorithm/radix_sort.h
index cba56e75814a78..9626c00fd9a1c4 100644
--- a/libcxx/include/__algorithm/radix_sort.h
+++ b/libcxx/include/__algorithm/radix_sort.h
@@ -87,23 +87,23 @@ __partial_sum_max(_InputIterator __first, _InputIterator __last, _OutputIterator
 
 template <class _Value, class _Map, class _Radix>
 struct __radix_sort_traits {
-  using image_type = decay_t<invoke_result_t<_Map, _Value> >;
-  static_assert(is_unsigned<image_type>::value, "");
+  using __image_type = decay_t<invoke_result_t<_Map, _Value> >;
+  static_assert(is_unsigned<__image_type>::value, "");
 
-  using radix_type = decay_t<invoke_result_t<_Radix, image_type> >;
-  static_assert(is_integral<radix_type>::value, "");
+  using __radix_type = decay_t<invoke_result_t<_Radix, __image_type> >;
+  static_assert(is_integral<__radix_type>::value, "");
 
-  constexpr static auto __radix_value_range = numeric_limits<radix_type>::max() + 1;
+  constexpr static auto __radix_value_range = numeric_limits<__radix_type>::max() + 1;
   constexpr static auto __radix_size        = std::__intlog2<uint64_t>(__radix_value_range);
-  constexpr static auto __radix_count       = sizeof(image_type) * CHAR_BIT / __radix_size;
+  constexpr static auto __radix_count       = sizeof(__image_type) * CHAR_BIT / __radix_size;
 };
 
 template <class _Value, class _Map>
 struct __counting_sort_traits {
-  using image_type = decay_t<invoke_result_t<_Map, _Value> >;
-  static_assert(is_unsigned<image_type>::value, "");
+  using __image_type = decay_t<invoke_result_t<_Map, _Value> >;
+  static_assert(is_unsigned<__image_type>::value, "");
 
-  constexpr static const auto __value_range = numeric_limits<image_type>::max() + 1;
+  constexpr static const auto __value_range = numeric_limits<__image_type>::max() + 1;
   constexpr static auto __radix_size        = std::__intlog2<uint64_t>(__value_range);
 };
 

>From f2df8698a7de3f62867b7dba929577163d46e803 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=94=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9=20=D0=98=D0=B7?=
 =?UTF-8?q?=D0=B2=D0=BE=D0=BB=D0=BE=D0=B2?= <dmitriy at izvolov.ru>
Date: Wed, 21 Aug 2024 12:33:21 +0300
Subject: [PATCH 26/46] nth-radix

---
 libcxx/include/__algorithm/radix_sort.h | 21 +++++++++------------
 1 file changed, 9 insertions(+), 12 deletions(-)

diff --git a/libcxx/include/__algorithm/radix_sort.h b/libcxx/include/__algorithm/radix_sort.h
index 9626c00fd9a1c4..a5a1321a917666 100644
--- a/libcxx/include/__algorithm/radix_sort.h
+++ b/libcxx/include/__algorithm/radix_sort.h
@@ -107,15 +107,12 @@ struct __counting_sort_traits {
   constexpr static auto __radix_size        = std::__intlog2<uint64_t>(__value_range);
 };
 
-template <class _Radix>
-_LIBCPP_HIDE_FROM_ABI auto __nth_radix(size_t __radix_number, _Radix __radix) {
-  return [__radix_number, __radix = std::move(__radix)](auto __n) {
-    using value_type = decltype(__n);
-    static_assert(is_unsigned<value_type>::value, "");
-    using traits = __counting_sort_traits<value_type, _Radix>;
-
-    return __radix(static_cast<value_type>(__n >> traits::__radix_size * __radix_number));
-  };
+template <class _Radix, class _Integer>
+_LIBCPP_HIDE_FROM_ABI auto __nth_radix(size_t __radix_number, _Radix __radix, _Integer __n) {
+  static_assert(is_unsigned<_Integer>::value, "");
+  using traits = __counting_sort_traits<_Integer, _Radix>;
+
+  return __radix(static_cast<_Integer>(__n >> traits::__radix_size * __radix_number));
 }
 
 template <class _ForwardIterator, class _Map, class _RandomAccessIterator>
@@ -167,7 +164,7 @@ _LIBCPP_HIDE_FROM_ABI bool __collect_impl(
     __is_sorted &= (__current >= __previous);
     __previous = __current;
 
-    (++__counters[_Radices][std::__nth_radix(_Radices, __radix)(__current)], ...);
+    (++__counters[_Radices][std::__nth_radix(_Radices, __radix, __current)], ...);
   });
 
   ((__maximums[_Radices] =
@@ -269,7 +266,7 @@ __radix_sort_impl(_RandomAccessIterator1 __first,
         std::copy(std::__move_assign_please(__first), std::__move_assign_please(__last), __buffer_begin);
       } else {
         auto __n0th = [__radix_number, &__map, &__radix](const auto& __v) {
-          return std::__nth_radix(__radix_number, __radix)(__map(__v));
+          return std::__nth_radix(__radix_number, __radix, __map(__v));
         };
         std::__dispose_backward(
             std::__move_assign_please(__first),
@@ -283,7 +280,7 @@ __radix_sort_impl(_RandomAccessIterator1 __first,
         std::copy(std::__move_assign_please(__buffer_begin), std::__move_assign_please(__buffer_end), __first);
       } else {
         auto __n1th = [__radix_number, &__map, &__radix](const auto& __v) {
-          return std::__nth_radix(__radix_number + 1, __radix)(__map(__v));
+          return std::__nth_radix(__radix_number + 1, __radix, __map(__v));
         };
         std::__dispose_backward(
             std::__move_assign_please(__buffer_begin),

>From e6ba2d4f4aa1ad19fcf1d7992caebd13e083df12 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=94=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9=20=D0=98=D0=B7?=
 =?UTF-8?q?=D0=B2=D0=BE=D0=BB=D0=BE=D0=B2?= <dmitriy at izvolov.ru>
Date: Wed, 21 Aug 2024 12:43:52 +0300
Subject: [PATCH 27/46] is-identity

---
 libcxx/include/__algorithm/ranges_stable_sort.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libcxx/include/__algorithm/ranges_stable_sort.h b/libcxx/include/__algorithm/ranges_stable_sort.h
index 96d84b208687fc..029551fefa692c 100644
--- a/libcxx/include/__algorithm/ranges_stable_sort.h
+++ b/libcxx/include/__algorithm/ranges_stable_sort.h
@@ -48,7 +48,7 @@ struct __stable_sort {
 
     auto&& __projected_comp = std::__make_projected(__comp, __proj);
     constexpr auto __default_comp        = is_same_v<_Comp, ranges::less>;
-    constexpr auto __default_proj        = is_same_v<_Proj, identity>;
+    constexpr auto __default_proj        = __is_identity<_Proj>::value;
     constexpr auto __integral_value      = is_integral_v<iter_value_t<_Iter>>;
     constexpr auto __integral_projection = __default_proj && __integral_value;
     // constexpr auto __integral_projection = is_integral_v<remove_reference_t<invoke_result_t<_Proj&,

>From cb1d90e5fa84941a95dc383e87fcb4f07027c21f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=94=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9=20=D0=98=D0=B7?=
 =?UTF-8?q?=D0=B2=D0=BE=D0=BB=D0=BE=D0=B2?= <dmitriy at izvolov.ru>
Date: Wed, 21 Aug 2024 12:59:43 +0300
Subject: [PATCH 28/46] desugars

---
 libcxx/include/__algorithm/ranges_stable_sort.h | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/libcxx/include/__algorithm/ranges_stable_sort.h b/libcxx/include/__algorithm/ranges_stable_sort.h
index 029551fefa692c..329ff1b7ba8da3 100644
--- a/libcxx/include/__algorithm/ranges_stable_sort.h
+++ b/libcxx/include/__algorithm/ranges_stable_sort.h
@@ -24,8 +24,8 @@
 #include <__ranges/access.h>
 #include <__ranges/concepts.h>
 #include <__ranges/dangling.h>
+#include <__type_traits/desugars_to.h>
 #include <__type_traits/is_integral.h>
-#include <__type_traits/is_same.h>
 #include <__utility/forward.h>
 #include <__utility/move.h>
 
@@ -47,7 +47,8 @@ struct __stable_sort {
     auto __last_iter = ranges::next(__first, __last);
 
     auto&& __projected_comp = std::__make_projected(__comp, __proj);
-    constexpr auto __default_comp        = is_same_v<_Comp, ranges::less>;
+    constexpr auto __default_comp =
+        __desugars_to_v<__totally_ordered_less_tag, _Comp, iter_value_t<_Iter>, iter_value_t<_Iter> >;
     constexpr auto __default_proj        = __is_identity<_Proj>::value;
     constexpr auto __integral_value      = is_integral_v<iter_value_t<_Iter>>;
     constexpr auto __integral_projection = __default_proj && __integral_value;

>From 8e14bec951fb8682d811d2840a3591b7af25a1a3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=94=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9=20=D0=98=D0=B7?=
 =?UTF-8?q?=D0=B2=D0=BE=D0=BB=D0=BE=D0=B2?= <dmitriy at izvolov.ru>
Date: Wed, 21 Aug 2024 23:07:47 +0300
Subject: [PATCH 29/46] enable-if

---
 libcxx/include/__algorithm/radix_sort.h | 43 ++++++++++++++-----------
 1 file changed, 25 insertions(+), 18 deletions(-)

diff --git a/libcxx/include/__algorithm/radix_sort.h b/libcxx/include/__algorithm/radix_sort.h
index a5a1321a917666..874fc6584bee38 100644
--- a/libcxx/include/__algorithm/radix_sort.h
+++ b/libcxx/include/__algorithm/radix_sort.h
@@ -218,15 +218,18 @@ __counting_sort_impl(_ForwardIterator __first, _ForwardIterator __last, _RandomA
   return __result + __counters[traits::__value_range];
 }
 
-template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _Map, class _Radix>
-_LIBCPP_HIDE_FROM_ABI
-typename enable_if< __radix_sort_traits<__iter_value_type<_RandomAccessIterator1>, _Map, _Radix>::__radix_count == 1,
-                    void>::type
-__radix_sort_impl(_RandomAccessIterator1 __first,
-                  _RandomAccessIterator1 __last,
-                  _RandomAccessIterator2 buffer,
-                  _Map __map,
-                  _Radix __radix) {
+template <class _RandomAccessIterator1,
+          class _RandomAccessIterator2,
+          class _Map,
+          class _Radix,
+          enable_if_t< __radix_sort_traits<__iter_value_type<_RandomAccessIterator1>, _Map, _Radix>::__radix_count == 1,
+                       int> = 0>
+_LIBCPP_HIDE_FROM_ABI void __radix_sort_impl(
+    _RandomAccessIterator1 __first,
+    _RandomAccessIterator1 __last,
+    _RandomAccessIterator2 buffer,
+    _Map __map,
+    _Radix __radix) {
   auto __buffer_end = std::__counting_sort_impl(
       std::__move_assign_please(__first),
       std::__move_assign_please(__last),
@@ -236,15 +239,19 @@ __radix_sort_impl(_RandomAccessIterator1 __first,
   std::copy(std::__move_assign_please(buffer), std::__move_assign_please(__buffer_end), __first);
 }
 
-template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _Map, class _Radix>
-_LIBCPP_HIDE_FROM_ABI typename enable_if<
-    __radix_sort_traits<__iter_value_type<_RandomAccessIterator1>, _Map, _Radix>::__radix_count % 2 == 0,
-    void>::type
-__radix_sort_impl(_RandomAccessIterator1 __first,
-                  _RandomAccessIterator1 __last,
-                  _RandomAccessIterator2 __buffer_begin,
-                  _Map __map,
-                  _Radix __radix) {
+template <
+    class _RandomAccessIterator1,
+    class _RandomAccessIterator2,
+    class _Map,
+    class _Radix,
+    enable_if_t< __radix_sort_traits<__iter_value_type<_RandomAccessIterator1>, _Map, _Radix>::__radix_count % 2 == 0,
+                 int> = 0 >
+_LIBCPP_HIDE_FROM_ABI void __radix_sort_impl(
+    _RandomAccessIterator1 __first,
+    _RandomAccessIterator1 __last,
+    _RandomAccessIterator2 __buffer_begin,
+    _Map __map,
+    _Radix __radix) {
   using value_type = __iter_value_type<_RandomAccessIterator1>;
   using traits     = __radix_sort_traits<value_type, _Map, _Radix>;
 

>From 52b177bbcbddb54c3b48a5c5ffeed6ec96231228 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=94=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9=20=D0=98=D0=B7?=
 =?UTF-8?q?=D0=B2=D0=BE=D0=BB=D0=BE=D0=B2?= <dmitriy at izvolov.ru>
Date: Wed, 21 Aug 2024 23:32:41 +0300
Subject: [PATCH 30/46] naming

---
 libcxx/include/__algorithm/radix_sort.h | 23 +++++++++++++----------
 1 file changed, 13 insertions(+), 10 deletions(-)

diff --git a/libcxx/include/__algorithm/radix_sort.h b/libcxx/include/__algorithm/radix_sort.h
index 874fc6584bee38..d720a5f0e06aa9 100644
--- a/libcxx/include/__algorithm/radix_sort.h
+++ b/libcxx/include/__algorithm/radix_sort.h
@@ -227,16 +227,16 @@ template <class _RandomAccessIterator1,
 _LIBCPP_HIDE_FROM_ABI void __radix_sort_impl(
     _RandomAccessIterator1 __first,
     _RandomAccessIterator1 __last,
-    _RandomAccessIterator2 buffer,
+    _RandomAccessIterator2 __buffer,
     _Map __map,
     _Radix __radix) {
   auto __buffer_end = std::__counting_sort_impl(
       std::__move_assign_please(__first),
       std::__move_assign_please(__last),
-      buffer,
+      __buffer,
       [&__map, &__radix](const auto& value) { return __radix(__map(value)); });
 
-  std::copy(std::__move_assign_please(buffer), std::__move_assign_please(__buffer_end), __first);
+  std::copy(std::__move_assign_please(__buffer), std::__move_assign_please(__buffer_end), __first);
 }
 
 template <
@@ -321,23 +321,26 @@ template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _Map
 _LIBCPP_HIDE_FROM_ABI void
 __radix_sort(_RandomAccessIterator1 __first,
              _RandomAccessIterator1 __last,
-             _RandomAccessIterator2 buffer,
+             _RandomAccessIterator2 __buffer,
              _Map __map,
              _Radix __radix) {
   auto __map_to_unsigned = [__map = std::move(__map)](const auto& x) { return std::__to_unsigned(__map(x)); };
-  std::__radix_sort_impl(__first, __last, buffer, __map_to_unsigned, __radix);
+  std::__radix_sort_impl(__first, __last, __buffer, __map_to_unsigned, __radix);
 }
 
 template <class _RandomAccessIterator1, class _RandomAccessIterator2>
 _LIBCPP_HIDE_FROM_ABI void
-__radix_sort(_RandomAccessIterator1 __first, _RandomAccessIterator1 __last, _RandomAccessIterator2 buffer) {
-  std::__radix_sort(__first, __last, buffer, __identity{}, __low_byte_fn{});
+__radix_sort(_RandomAccessIterator1 __first, _RandomAccessIterator1 __last, _RandomAccessIterator2 __buffer) {
+  std::__radix_sort(__first, __last, __buffer, __identity{}, __low_byte_fn{});
 }
 
 template <class _RandomAccessIterator1, class _RandomAccessIterator2>
-_LIBCPP_HIDE_FROM_ABI bool __radix_sort(
-    _RandomAccessIterator1 __first, _RandomAccessIterator1 __last, _RandomAccessIterator2 buffer, _BoolConstant<true>) {
-  std::__radix_sort(__first, __last, buffer, __identity{}, __low_byte_fn{});
+_LIBCPP_HIDE_FROM_ABI bool
+__radix_sort(_RandomAccessIterator1 __first,
+             _RandomAccessIterator1 __last,
+             _RandomAccessIterator2 __buffer,
+             _BoolConstant<true>) {
+  std::__radix_sort(__first, __last, __buffer, __identity{}, __low_byte_fn{});
   return true;
 }
 

>From d42fb97e102da14deb38a9c862ff55e941fdc9d2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=94=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9=20=D0=98=D0=B7?=
 =?UTF-8?q?=D0=B2=D0=BE=D0=BB=D0=BE=D0=B2?= <dmitriy at izvolov.ru>
Date: Thu, 22 Aug 2024 16:45:50 +0300
Subject: [PATCH 31/46] description

---
 libcxx/include/__algorithm/radix_sort.h | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/libcxx/include/__algorithm/radix_sort.h b/libcxx/include/__algorithm/radix_sort.h
index d720a5f0e06aa9..e60092c0184303 100644
--- a/libcxx/include/__algorithm/radix_sort.h
+++ b/libcxx/include/__algorithm/radix_sort.h
@@ -10,6 +10,23 @@
 #ifndef _LIBCPP___ALGORITHM_RADIX_SORT_H
 #define _LIBCPP___ALGORITHM_RADIX_SORT_H
 
+// This is an implementation of classic LSD radix sort algorithm, running in linear time and using `O(max(N, M))`
+// additional memory, where `N` is size of an input range, `M` — maximum value of
+// a radix of the sorted integer type. Type of the radix and its maximum value are determined at compile time
+// based on type returned by function `__radix`. The default radix is uint8.
+
+// The algorithm is equivalent to several consecutive calls of counting sort for each
+// radix of the sorted numbers from low to high byte.
+// The algorithm uses a temporary buffer of size equal to size of the input range. Each `i`-th pass
+// of the algorithm sorts values by `i`-th radix and moves values to the temporary buffer (for each even `i`, counted
+// from zero), or moves them back to the initial range (for each odd `i`). It there is only one radix in sorted integers
+// (e.g. int8), than sorted values are placed to the buffer, and then moved back to the initial range.
+
+// The implementation also has several optimizations:
+// - the counters for the counting sort are calculated in one pass for all radices;
+// - if all values of a radix are the same, we do not sort that radix, and just move items to the buffer;
+// - if two consecutive radices satisfies condition above, we do nothing for these two radices.
+
 #include <__algorithm/copy.h>
 #include <__algorithm/for_each.h>
 #include <__bit/countl.h>

>From 1fe91e33b7fd46349cf5cdc59f1c9e3be1819033 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=94=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9=20=D0=98=D0=B7?=
 =?UTF-8?q?=D0=B2=D0=BE=D0=BB=D0=BE=D0=B2?= <dmitriy at izvolov.ru>
Date: Thu, 22 Aug 2024 18:28:09 +0300
Subject: [PATCH 32/46] move-explicitly

---
 libcxx/include/__algorithm/radix_sort.h | 44 +++++++------------------
 1 file changed, 11 insertions(+), 33 deletions(-)

diff --git a/libcxx/include/__algorithm/radix_sort.h b/libcxx/include/__algorithm/radix_sort.h
index e60092c0184303..4f0023f7dc3a55 100644
--- a/libcxx/include/__algorithm/radix_sort.h
+++ b/libcxx/include/__algorithm/radix_sort.h
@@ -27,8 +27,8 @@
 // - if all values of a radix are the same, we do not sort that radix, and just move items to the buffer;
 // - if two consecutive radices satisfies condition above, we do nothing for these two radices.
 
-#include <__algorithm/copy.h>
 #include <__algorithm/for_each.h>
+#include <__algorithm/move.h>
 #include <__bit/countl.h>
 #include <__config>
 #include <__functional/identity.h>
@@ -65,16 +65,6 @@ _LIBCPP_BEGIN_NAMESPACE_STD
 
 #if _LIBCPP_STD_VER >= 14
 
-template <class _Iterator, enable_if_t<is_move_assignable<__iter_value_type<_Iterator>>::value, int> = 0>
-_LIBCPP_HIDE_FROM_ABI constexpr move_iterator<_Iterator> __move_assign_please(_Iterator __i) {
-  return std::make_move_iterator(std::move(__i));
-}
-
-template <class _Iterator, enable_if_t<!is_move_assignable<__iter_value_type<_Iterator>>::value, int> = 0>
-_LIBCPP_HIDE_FROM_ABI constexpr _Iterator __move_assign_please(_Iterator __i) {
-  return __i;
-}
-
 template <class _UnsignedInteger>
 _LIBCPP_HIDE_FROM_ABI constexpr _UnsignedInteger __intlog2(_UnsignedInteger __n) {
   static_assert(is_unsigned<_UnsignedInteger>::value, "Must be unsigned integral");
@@ -153,7 +143,7 @@ __dispose(_ForwardIterator __first,
           _RandomAccessIterator2 __counters) {
   std::for_each(__first, __last, [&__result, &__counters, &__map](auto&& __preimage) {
     auto __index      = __counters[__map(__preimage)]++;
-    __result[__index] = std::forward<decltype(__preimage)>(__preimage);
+    __result[__index] = std::move(__preimage);
   });
 }
 
@@ -217,7 +207,7 @@ _LIBCPP_HIDE_FROM_ABI void __dispose_backward(
                 std::make_reverse_iterator(__first),
                 [&__result, &__counters, &__map](auto&& __preimage) {
                   auto __index      = --__counters[__map(__preimage)];
-                  __result[__index] = std::forward<decltype(__preimage)>(__preimage);
+                  __result[__index] = std::move(__preimage);
                 });
 }
 
@@ -247,13 +237,11 @@ _LIBCPP_HIDE_FROM_ABI void __radix_sort_impl(
     _RandomAccessIterator2 __buffer,
     _Map __map,
     _Radix __radix) {
-  auto __buffer_end = std::__counting_sort_impl(
-      std::__move_assign_please(__first),
-      std::__move_assign_please(__last),
-      __buffer,
-      [&__map, &__radix](const auto& value) { return __radix(__map(value)); });
+  auto __buffer_end = std::__counting_sort_impl(__first, __last, __buffer, [&__map, &__radix](const auto& value) {
+    return __radix(__map(value));
+  });
 
-  std::copy(std::__move_assign_please(__buffer), std::__move_assign_please(__buffer_end), __first);
+  std::move(__buffer, __buffer_end, __first);
 }
 
 template <
@@ -287,31 +275,21 @@ _LIBCPP_HIDE_FROM_ABI void __radix_sort_impl(
       }
 
       if (__n0th_is_single) {
-        std::copy(std::__move_assign_please(__first), std::__move_assign_please(__last), __buffer_begin);
+        std::move(__first, __last, __buffer_begin);
       } else {
         auto __n0th = [__radix_number, &__map, &__radix](const auto& __v) {
           return std::__nth_radix(__radix_number, __radix, __map(__v));
         };
-        std::__dispose_backward(
-            std::__move_assign_please(__first),
-            std::__move_assign_please(__last),
-            __buffer_begin,
-            __n0th,
-            __counters[__radix_number]);
+        std::__dispose_backward(__first, __last, __buffer_begin, __n0th, __counters[__radix_number]);
       }
 
       if (__n1th_is_single) {
-        std::copy(std::__move_assign_please(__buffer_begin), std::__move_assign_please(__buffer_end), __first);
+        std::move(__buffer_begin, __buffer_end, __first);
       } else {
         auto __n1th = [__radix_number, &__map, &__radix](const auto& __v) {
           return std::__nth_radix(__radix_number + 1, __radix, __map(__v));
         };
-        std::__dispose_backward(
-            std::__move_assign_please(__buffer_begin),
-            std::__move_assign_please(__buffer_end),
-            __first,
-            __n1th,
-            __counters[__radix_number + 1]);
+        std::__dispose_backward(__buffer_begin, __buffer_end, __first, __n1th, __counters[__radix_number + 1]);
       }
     }
   }

>From 5ca88f9e29bac113318aa87ea13c651db075103e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=94=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9=20=D0=98=D0=B7?=
 =?UTF-8?q?=D0=B2=D0=BE=D0=BB=D0=BE=D0=B2?= <dmitriy at izvolov.ru>
Date: Mon, 26 Aug 2024 08:04:37 +0300
Subject: [PATCH 33/46] shift-to-unsigned

---
 libcxx/include/__algorithm/radix_sort.h | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/libcxx/include/__algorithm/radix_sort.h b/libcxx/include/__algorithm/radix_sort.h
index 4f0023f7dc3a55..5b494e5c352d7f 100644
--- a/libcxx/include/__algorithm/radix_sort.h
+++ b/libcxx/include/__algorithm/radix_sort.h
@@ -295,10 +295,10 @@ _LIBCPP_HIDE_FROM_ABI void __radix_sort_impl(
   }
 }
 
-_LIBCPP_HIDE_FROM_ABI constexpr auto __to_unsigned(bool __b) { return __b; }
+_LIBCPP_HIDE_FROM_ABI constexpr auto __shift_to_unsigned(bool __b) { return __b; }
 
 template <class _Ip>
-_LIBCPP_HIDE_FROM_ABI constexpr auto __to_unsigned(_Ip __n) {
+_LIBCPP_HIDE_FROM_ABI constexpr auto __shift_to_unsigned(_Ip __n) {
   constexpr const auto __min_value = numeric_limits<_Ip>::min();
   return static_cast<make_unsigned_t<_Ip> >(__n ^ __min_value);
 }
@@ -319,7 +319,7 @@ __radix_sort(_RandomAccessIterator1 __first,
              _RandomAccessIterator2 __buffer,
              _Map __map,
              _Radix __radix) {
-  auto __map_to_unsigned = [__map = std::move(__map)](const auto& x) { return std::__to_unsigned(__map(x)); };
+  auto __map_to_unsigned = [__map = std::move(__map)](const auto& x) { return std::__shift_to_unsigned(__map(x)); };
   std::__radix_sort_impl(__first, __last, __buffer, __map_to_unsigned, __radix);
 }
 

>From 9915dbb1a53fca8b024f778c58054dd657a8153c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=94=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9=20=D0=98=D0=B7?=
 =?UTF-8?q?=D0=B2=D0=BE=D0=BB=D0=BE=D0=B2?= <dmitriy at izvolov.ru>
Date: Mon, 9 Sep 2024 22:50:02 +0300
Subject: [PATCH 34/46] comment

---
 libcxx/include/__algorithm/radix_sort.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/libcxx/include/__algorithm/radix_sort.h b/libcxx/include/__algorithm/radix_sort.h
index 5b494e5c352d7f..df8db85ac76eaa 100644
--- a/libcxx/include/__algorithm/radix_sort.h
+++ b/libcxx/include/__algorithm/radix_sort.h
@@ -19,8 +19,8 @@
 // radix of the sorted numbers from low to high byte.
 // The algorithm uses a temporary buffer of size equal to size of the input range. Each `i`-th pass
 // of the algorithm sorts values by `i`-th radix and moves values to the temporary buffer (for each even `i`, counted
-// from zero), or moves them back to the initial range (for each odd `i`). It there is only one radix in sorted integers
-// (e.g. int8), than sorted values are placed to the buffer, and then moved back to the initial range.
+// from zero), or moves them back to the initial range (for each odd `i`). If there is only one radix in sorted integers
+// (e.g. int8), the sorted values are placed to the buffer, and then moved back to the initial range.
 
 // The implementation also has several optimizations:
 // - the counters for the counting sort are calculated in one pass for all radices;

>From e5d138ec329f88de34eea08c52fc6f71bcdc00ab Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=94=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9=20=D0=98=D0=B7?=
 =?UTF-8?q?=D0=B2=D0=BE=D0=BB=D0=BE=D0=B2?= <dmitriy at izvolov.ru>
Date: Mon, 9 Sep 2024 22:50:22 +0300
Subject: [PATCH 35/46] backport-bit-log2

---
 libcxx/include/__algorithm/radix_sort.h | 12 +++---------
 libcxx/include/__bit/bit_log2.h         |  9 +++++----
 2 files changed, 8 insertions(+), 13 deletions(-)

diff --git a/libcxx/include/__algorithm/radix_sort.h b/libcxx/include/__algorithm/radix_sort.h
index df8db85ac76eaa..c46079b4d5d168 100644
--- a/libcxx/include/__algorithm/radix_sort.h
+++ b/libcxx/include/__algorithm/radix_sort.h
@@ -29,6 +29,7 @@
 
 #include <__algorithm/for_each.h>
 #include <__algorithm/move.h>
+#include <__bit/bit_log2.h>
 #include <__bit/countl.h>
 #include <__config>
 #include <__functional/identity.h>
@@ -65,13 +66,6 @@ _LIBCPP_BEGIN_NAMESPACE_STD
 
 #if _LIBCPP_STD_VER >= 14
 
-template <class _UnsignedInteger>
-_LIBCPP_HIDE_FROM_ABI constexpr _UnsignedInteger __intlog2(_UnsignedInteger __n) {
-  static_assert(is_unsigned<_UnsignedInteger>::value, "Must be unsigned integral");
-
-  return numeric_limits<_UnsignedInteger>::digits - 1 - std::__countl_zero(__n);
-}
-
 template <class _InputIterator, class _OutputIterator>
 _LIBCPP_HIDE_FROM_ABI pair<_OutputIterator, __iter_value_type<_InputIterator>>
 __partial_sum_max(_InputIterator __first, _InputIterator __last, _OutputIterator __result) {
@@ -101,7 +95,7 @@ struct __radix_sort_traits {
   static_assert(is_integral<__radix_type>::value, "");
 
   constexpr static auto __radix_value_range = numeric_limits<__radix_type>::max() + 1;
-  constexpr static auto __radix_size        = std::__intlog2<uint64_t>(__radix_value_range);
+  constexpr static auto __radix_size        = std::__bit_log2<uint64_t>(__radix_value_range);
   constexpr static auto __radix_count       = sizeof(__image_type) * CHAR_BIT / __radix_size;
 };
 
@@ -111,7 +105,7 @@ struct __counting_sort_traits {
   static_assert(is_unsigned<__image_type>::value, "");
 
   constexpr static const auto __value_range = numeric_limits<__image_type>::max() + 1;
-  constexpr static auto __radix_size        = std::__intlog2<uint64_t>(__value_range);
+  constexpr static auto __radix_size        = std::__bit_log2<uint64_t>(__value_range);
 };
 
 template <class _Radix, class _Integer>
diff --git a/libcxx/include/__bit/bit_log2.h b/libcxx/include/__bit/bit_log2.h
index 62936f67868600..bd1ee1a5b57e5a 100644
--- a/libcxx/include/__bit/bit_log2.h
+++ b/libcxx/include/__bit/bit_log2.h
@@ -10,8 +10,8 @@
 #define _LIBCPP___BIT_BIT_LOG2_H
 
 #include <__bit/countl.h>
-#include <__concepts/arithmetic.h>
 #include <__config>
+#include <__type_traits/is_unsigned.h>
 #include <limits>
 
 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
@@ -20,14 +20,15 @@
 
 _LIBCPP_BEGIN_NAMESPACE_STD
 
-#if _LIBCPP_STD_VER >= 20
+#if _LIBCPP_STD_VER >= 14
 
-template <__libcpp_unsigned_integer _Tp>
+template <class _Tp>
 _LIBCPP_HIDE_FROM_ABI constexpr _Tp __bit_log2(_Tp __t) noexcept {
+  static_assert(is_unsigned<_Tp>::value, "__bit_log2 requires an unsigned integer type");
   return numeric_limits<_Tp>::digits - 1 - std::countl_zero(__t);
 }
 
-#endif // _LIBCPP_STD_VER >= 20
+#endif // _LIBCPP_STD_VER >= 14
 
 _LIBCPP_END_NAMESPACE_STD
 

>From c707bc9ce66bf3b91fc2b933d92004e99c1a089c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=94=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9=20=D0=98=D0=B7?=
 =?UTF-8?q?=D0=B2=D0=BE=D0=BB=D0=BE=D0=B2?= <dmitriy at izvolov.ru>
Date: Mon, 16 Sep 2024 22:39:47 +0300
Subject: [PATCH 36/46] dispatch-locally

---
 libcxx/include/__algorithm/radix_sort.h       | 24 -----
 .../include/__algorithm/ranges_stable_sort.h  | 16 +---
 libcxx/include/__algorithm/stable_sort.h      | 96 ++++++++-----------
 3 files changed, 43 insertions(+), 93 deletions(-)

diff --git a/libcxx/include/__algorithm/radix_sort.h b/libcxx/include/__algorithm/radix_sort.h
index c46079b4d5d168..de664596eda525 100644
--- a/libcxx/include/__algorithm/radix_sort.h
+++ b/libcxx/include/__algorithm/radix_sort.h
@@ -323,30 +323,6 @@ __radix_sort(_RandomAccessIterator1 __first, _RandomAccessIterator1 __last, _Ran
   std::__radix_sort(__first, __last, __buffer, __identity{}, __low_byte_fn{});
 }
 
-template <class _RandomAccessIterator1, class _RandomAccessIterator2>
-_LIBCPP_HIDE_FROM_ABI bool
-__radix_sort(_RandomAccessIterator1 __first,
-             _RandomAccessIterator1 __last,
-             _RandomAccessIterator2 __buffer,
-             _BoolConstant<true>) {
-  std::__radix_sort(__first, __last, __buffer, __identity{}, __low_byte_fn{});
-  return true;
-}
-
-template <class _RandomAccessIterator1, class _RandomAccessIterator2>
-_LIBCPP_HIDE_FROM_ABI bool
-__radix_sort(_RandomAccessIterator1, _RandomAccessIterator1, _RandomAccessIterator2, _BoolConstant<false>) {
-  return false;
-}
-
-#else // _LIBCPP_STD_VER > 14
-
-template <class _RandomAccessIterator1, class _RandomAccessIterator2, bool _EnableRadixSort>
-_LIBCPP_HIDE_FROM_ABI bool
-__radix_sort(_RandomAccessIterator1, _RandomAccessIterator1, _RandomAccessIterator2, _BoolConstant<_EnableRadixSort>) {
-  return false;
-}
-
 #endif // _LIBCPP_STD_VER > 14
 
 _LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/__algorithm/ranges_stable_sort.h b/libcxx/include/__algorithm/ranges_stable_sort.h
index 329ff1b7ba8da3..9c7df80ae98722 100644
--- a/libcxx/include/__algorithm/ranges_stable_sort.h
+++ b/libcxx/include/__algorithm/ranges_stable_sort.h
@@ -24,8 +24,6 @@
 #include <__ranges/access.h>
 #include <__ranges/concepts.h>
 #include <__ranges/dangling.h>
-#include <__type_traits/desugars_to.h>
-#include <__type_traits/is_integral.h>
 #include <__utility/forward.h>
 #include <__utility/move.h>
 
@@ -47,19 +45,7 @@ struct __stable_sort {
     auto __last_iter = ranges::next(__first, __last);
 
     auto&& __projected_comp = std::__make_projected(__comp, __proj);
-    constexpr auto __default_comp =
-        __desugars_to_v<__totally_ordered_less_tag, _Comp, iter_value_t<_Iter>, iter_value_t<_Iter> >;
-    constexpr auto __default_proj        = __is_identity<_Proj>::value;
-    constexpr auto __integral_value      = is_integral_v<iter_value_t<_Iter>>;
-    constexpr auto __integral_projection = __default_proj && __integral_value;
-    // constexpr auto __integral_projection = is_integral_v<remove_reference_t<invoke_result_t<_Proj&,
-    // iter_value_t<_Iter>>>>;
-    // TODO: Support projection in stable_sort
-    std::__stable_sort_impl<_RangeAlgPolicy>(
-        std::move(__first),
-        __last_iter,
-        __projected_comp,
-        _BoolConstant < __default_comp && __integral_projection > {});
+    std::__stable_sort_impl<_RangeAlgPolicy>(std::move(__first), __last_iter, __projected_comp);
 
     return __last_iter;
   }
diff --git a/libcxx/include/__algorithm/stable_sort.h b/libcxx/include/__algorithm/stable_sort.h
index 2df7456c2733ff..eaeac067dd66b9 100644
--- a/libcxx/include/__algorithm/stable_sort.h
+++ b/libcxx/include/__algorithm/stable_sort.h
@@ -22,11 +22,11 @@
 #include <__memory/destruct_n.h>
 #include <__memory/unique_ptr.h>
 #include <__memory/unique_temporary_buffer.h>
+#include <__type_traits/desugars_to.h>
 #include <__type_traits/enable_if.h>
-#include <__type_traits/integral_constant.h>
 #include <__type_traits/is_integral.h>
-#include <__type_traits/is_same.h>
 #include <__type_traits/is_trivially_assignable.h>
+#include <__type_traits/remove_cvref.h>
 #include <__utility/move.h>
 #include <__utility/pair.h>
 #include <new>
@@ -139,24 +139,20 @@ _LIBCPP_HIDE_FROM_ABI void __merge_move_assign(
     *__result = _Ops::__iter_move(__first2);
 }
 
-template <class _AlgPolicy, class _Compare, class _RandomAccessIterator, bool _EnableRadixSort>
-void __stable_sort(
-    _RandomAccessIterator __first,
-    _RandomAccessIterator __last,
-    _Compare __comp,
-    typename iterator_traits<_RandomAccessIterator>::difference_type __len,
-    typename iterator_traits<_RandomAccessIterator>::value_type* __buff,
-    ptrdiff_t __buff_size,
-    _BoolConstant<_EnableRadixSort>);
+template <class _AlgPolicy, class _Compare, class _RandomAccessIterator>
+void __stable_sort(_RandomAccessIterator __first,
+                   _RandomAccessIterator __last,
+                   _Compare __comp,
+                   typename iterator_traits<_RandomAccessIterator>::difference_type __len,
+                   typename iterator_traits<_RandomAccessIterator>::value_type* __buff,
+                   ptrdiff_t __buff_size);
 
-template <class _AlgPolicy, class _Compare, class _RandomAccessIterator, bool _EnableRadixSort>
-void __stable_sort_move(
-    _RandomAccessIterator __first1,
-    _RandomAccessIterator __last1,
-    _Compare __comp,
-    typename iterator_traits<_RandomAccessIterator>::difference_type __len,
-    typename iterator_traits<_RandomAccessIterator>::value_type* __first2,
-    _BoolConstant<_EnableRadixSort> __rs) {
+template <class _AlgPolicy, class _Compare, class _RandomAccessIterator>
+void __stable_sort_move(_RandomAccessIterator __first1,
+                        _RandomAccessIterator __last1,
+                        _Compare __comp,
+                        typename iterator_traits<_RandomAccessIterator>::difference_type __len,
+                        typename iterator_traits<_RandomAccessIterator>::value_type* __first2) {
   using _Ops = _IterOps<_AlgPolicy>;
 
   typedef typename iterator_traits<_RandomAccessIterator>::value_type value_type;
@@ -189,8 +185,8 @@ void __stable_sort_move(
   }
   typename iterator_traits<_RandomAccessIterator>::difference_type __l2 = __len / 2;
   _RandomAccessIterator __m                                             = __first1 + __l2;
-  std::__stable_sort<_AlgPolicy, _Compare>(__first1, __m, __comp, __l2, __first2, __l2, __rs);
-  std::__stable_sort<_AlgPolicy, _Compare>(__m, __last1, __comp, __len - __l2, __first2 + __l2, __len - __l2, __rs);
+  std::__stable_sort<_AlgPolicy, _Compare>(__first1, __m, __comp, __l2, __first2, __l2);
+  std::__stable_sort<_AlgPolicy, _Compare>(__m, __last1, __comp, __len - __l2, __first2 + __l2, __len - __l2);
   std::__merge_move_construct<_AlgPolicy, _Compare>(__first1, __m, __m, __last1, __first2, __comp);
 }
 
@@ -219,15 +215,13 @@ struct __radix_sort_max_switch<_Int64, __enable_if_t<is_integral<_Int64>::value
   static const unsigned value = (1 << 15);
 };
 
-template <class _AlgPolicy, class _Compare, class _RandomAccessIterator, bool _EnableRadixSort>
-void __stable_sort(
-    _RandomAccessIterator __first,
-    _RandomAccessIterator __last,
-    _Compare __comp,
-    typename iterator_traits<_RandomAccessIterator>::difference_type __len,
-    typename iterator_traits<_RandomAccessIterator>::value_type* __buff,
-    ptrdiff_t __buff_size,
-    _BoolConstant<_EnableRadixSort> __rs) {
+template <class _AlgPolicy, class _Compare, class _RandomAccessIterator>
+void __stable_sort(_RandomAccessIterator __first,
+                   _RandomAccessIterator __last,
+                   _Compare __comp,
+                   typename iterator_traits<_RandomAccessIterator>::difference_type __len,
+                   typename iterator_traits<_RandomAccessIterator>::value_type* __buff,
+                   ptrdiff_t __buff_size) {
   typedef typename iterator_traits<_RandomAccessIterator>::value_type value_type;
   typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type;
   switch (__len) {
@@ -243,9 +237,14 @@ void __stable_sort(
     std::__insertion_sort<_AlgPolicy, _Compare>(__first, __last, __comp);
     return;
   }
-  if (__len <= __buff_size && __len >= static_cast<difference_type>(__radix_sort_min_switch<value_type>::value) &&
-      __len <= static_cast<difference_type>(__radix_sort_max_switch<value_type>::value)) {
-    if (std::__radix_sort(__first, __last, __buff, __rs)) {
+  constexpr auto __default_comp =
+      __desugars_to_v<__totally_ordered_less_tag, __remove_cvref_t<_Compare>, value_type, value_type >;
+  constexpr auto __integral_value     = is_integral_v<value_type >;
+  constexpr auto __allowed_radix_sort = __default_comp && __integral_value;
+  if constexpr (__allowed_radix_sort) {
+    if (__len <= __buff_size && __len >= static_cast<difference_type>(__radix_sort_min_switch<value_type>::value) &&
+        __len <= static_cast<difference_type>(__radix_sort_max_switch<value_type>::value)) {
+      std::__radix_sort(__first, __last, __buff);
       return;
     }
   }
@@ -254,9 +253,9 @@ void __stable_sort(
   if (__len <= __buff_size) {
     __destruct_n __d(0);
     unique_ptr<value_type, __destruct_n&> __h2(__buff, __d);
-    std::__stable_sort_move<_AlgPolicy, _Compare>(__first, __m, __comp, __l2, __buff, __rs);
+    std::__stable_sort_move<_AlgPolicy, _Compare>(__first, __m, __comp, __l2, __buff);
     __d.__set(__l2, (value_type*)nullptr);
-    std::__stable_sort_move<_AlgPolicy, _Compare>(__m, __last, __comp, __len - __l2, __buff + __l2, __rs);
+    std::__stable_sort_move<_AlgPolicy, _Compare>(__m, __last, __comp, __len - __l2, __buff + __l2);
     __d.__set(__len, (value_type*)nullptr);
     std::__merge_move_assign<_AlgPolicy, _Compare>(
         __buff, __buff + __l2, __buff + __l2, __buff + __len, __first, __comp);
@@ -267,17 +266,14 @@ void __stable_sort(
     //                                  __first, __comp);
     return;
   }
-  std::__stable_sort<_AlgPolicy, _Compare>(__first, __m, __comp, __l2, __buff, __buff_size, __rs);
-  std::__stable_sort<_AlgPolicy, _Compare>(__m, __last, __comp, __len - __l2, __buff, __buff_size, __rs);
+  std::__stable_sort<_AlgPolicy, _Compare>(__first, __m, __comp, __l2, __buff, __buff_size);
+  std::__stable_sort<_AlgPolicy, _Compare>(__m, __last, __comp, __len - __l2, __buff, __buff_size);
   std::__inplace_merge<_AlgPolicy>(__first, __m, __last, __comp, __l2, __len - __l2, __buff, __buff_size);
 }
 
-template <class _AlgPolicy, class _RandomAccessIterator, class _Compare, bool _EnableRadixSort = false>
-inline _LIBCPP_HIDE_FROM_ABI void __stable_sort_impl(
-    _RandomAccessIterator __first,
-    _RandomAccessIterator __last,
-    _Compare& __comp,
-    _BoolConstant<_EnableRadixSort> __rs = _BoolConstant<false>()) {
+template <class _AlgPolicy, class _RandomAccessIterator, class _Compare>
+inline _LIBCPP_HIDE_FROM_ABI void
+__stable_sort_impl(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare& __comp) {
   using value_type      = typename iterator_traits<_RandomAccessIterator>::value_type;
   using difference_type = typename iterator_traits<_RandomAccessIterator>::difference_type;
 
@@ -290,27 +286,19 @@ inline _LIBCPP_HIDE_FROM_ABI void __stable_sort_impl(
     __buf.second = __unique_buf.get_deleter().__count_;
   }
 
-  std::__stable_sort<_AlgPolicy, __comp_ref_type<_Compare> >(
-      __first, __last, __comp, __len, __buf.first, __buf.second, __rs);
+  std::__stable_sort<_AlgPolicy, __comp_ref_type<_Compare> >(__first, __last, __comp, __len, __buf.first, __buf.second);
   std::__check_strict_weak_ordering_sorted(__first, __last, __comp);
 }
 
 template <class _RandomAccessIterator, class _Compare>
 inline _LIBCPP_HIDE_FROM_ABI void
 stable_sort(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) {
-  std::__stable_sort_impl<_ClassicAlgPolicy>(std::move(__first), std::move(__last), __comp, _BoolConstant<false>());
+  std::__stable_sort_impl<_ClassicAlgPolicy>(std::move(__first), std::move(__last), __comp);
 }
 
 template <class _RandomAccessIterator>
 inline _LIBCPP_HIDE_FROM_ABI void stable_sort(_RandomAccessIterator __first, _RandomAccessIterator __last) {
-  using value_type     = typename iterator_traits<_RandomAccessIterator>::value_type;
-  using reference_type = typename iterator_traits<_RandomAccessIterator>::reference;
-  auto __comp          = __less<>();
-  std::__stable_sort_impl<_ClassicAlgPolicy>(
-      std::move(__first),
-      std::move(__last),
-      __comp,
-      _BoolConstant < is_integral<value_type>::value && is_same<value_type&, reference_type>::value > ());
+  std::stable_sort(__first, __last, __less<>());
 }
 
 _LIBCPP_END_NAMESPACE_STD

>From 0164222acefc62d2282c91c46205f9286db63be5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=94=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9=20=D0=98=D0=B7?=
 =?UTF-8?q?=D0=B2=D0=BE=D0=BB=D0=BE=D0=B2?= <dmitriy at izvolov.ru>
Date: Mon, 16 Sep 2024 22:43:55 +0300
Subject: [PATCH 37/46] constexpr-fn-switch

---
 libcxx/include/__algorithm/stable_sort.h | 36 ++++++++++++------------
 1 file changed, 18 insertions(+), 18 deletions(-)

diff --git a/libcxx/include/__algorithm/stable_sort.h b/libcxx/include/__algorithm/stable_sort.h
index eaeac067dd66b9..cc0c21073db1e0 100644
--- a/libcxx/include/__algorithm/stable_sort.h
+++ b/libcxx/include/__algorithm/stable_sort.h
@@ -195,25 +195,25 @@ struct __stable_sort_switch {
   static const unsigned value = 128 * is_trivially_copy_assignable<_Tp>::value;
 };
 
-template <class _Tp, class = void>
-struct __radix_sort_min_switch {
-  static const unsigned value = (1 << 10);
-};
+template <class _Tp>
+constexpr unsigned __radix_sort_min_bound() {
+  static_assert(is_integral<_Tp>::value);
+  if constexpr (sizeof(_Tp) == 1) {
+    return 1 << 8;
+  }
 
-template <class _Int8>
-struct __radix_sort_min_switch<_Int8, __enable_if_t<is_integral<_Int8>::value && sizeof(_Int8) == 1> > {
-  static const unsigned value = (1 << 8);
-};
+  return 1 << 10;
+}
 
-template <class _Tp, class = void>
-struct __radix_sort_max_switch {
-  static const unsigned value = (1 << 16);
-};
+template <class _Tp>
+constexpr unsigned __radix_sort_max_bound() {
+  static_assert(is_integral<_Tp>::value);
+  if constexpr (sizeof(_Tp) == 8) {
+    return 1 << 15;
+  }
 
-template <class _Int64>
-struct __radix_sort_max_switch<_Int64, __enable_if_t<is_integral<_Int64>::value && sizeof(_Int64) == 8> > {
-  static const unsigned value = (1 << 15);
-};
+  return 1 << 16;
+}
 
 template <class _AlgPolicy, class _Compare, class _RandomAccessIterator>
 void __stable_sort(_RandomAccessIterator __first,
@@ -242,8 +242,8 @@ void __stable_sort(_RandomAccessIterator __first,
   constexpr auto __integral_value     = is_integral_v<value_type >;
   constexpr auto __allowed_radix_sort = __default_comp && __integral_value;
   if constexpr (__allowed_radix_sort) {
-    if (__len <= __buff_size && __len >= static_cast<difference_type>(__radix_sort_min_switch<value_type>::value) &&
-        __len <= static_cast<difference_type>(__radix_sort_max_switch<value_type>::value)) {
+    if (__len <= __buff_size && __len >= static_cast<difference_type>(__radix_sort_min_bound<value_type>()) &&
+        __len <= static_cast<difference_type>(__radix_sort_max_bound<value_type>())) {
       std::__radix_sort(__first, __last, __buff);
       return;
     }

>From a0d2fc0a87b8858017912a0c2687c151e2869efc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=94=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9=20=D0=98=D0=B7?=
 =?UTF-8?q?=D0=B2=D0=BE=D0=BB=D0=BE=D0=B2?= <dmitriy at izvolov.ru>
Date: Mon, 16 Sep 2024 23:32:23 +0300
Subject: [PATCH 38/46] release-notes

---
 libcxx/docs/ReleaseNotes/19.rst | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/libcxx/docs/ReleaseNotes/19.rst b/libcxx/docs/ReleaseNotes/19.rst
index e8f76773c54373..aec7865d52fada 100644
--- a/libcxx/docs/ReleaseNotes/19.rst
+++ b/libcxx/docs/ReleaseNotes/19.rst
@@ -126,6 +126,8 @@ Improvements and New Features
 
 - In C++23 and C++26 the number of transitive includes in several headers has been reduced, improving the compilation speed.
 
+- ``std::stable_sort`` uses radix sort for integral types now, which can improve the performance up to 10 times, depending
+  on type of sorted elements and the initial state of the sorted array.
 
 Deprecations and Removals
 -------------------------

>From 840323bdafd58ec8d5027bf83e40eec3038c5d26 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=94=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9=20=D0=98=D0=B7?=
 =?UTF-8?q?=D0=B2=D0=BE=D0=BB=D0=BE=D0=B2?= <dmitriy at izvolov.ru>
Date: Wed, 18 Sep 2024 22:49:09 +0300
Subject: [PATCH 39/46] 17guard

---
 libcxx/include/__algorithm/stable_sort.h | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/libcxx/include/__algorithm/stable_sort.h b/libcxx/include/__algorithm/stable_sort.h
index cc0c21073db1e0..868e36bc12f0b3 100644
--- a/libcxx/include/__algorithm/stable_sort.h
+++ b/libcxx/include/__algorithm/stable_sort.h
@@ -195,6 +195,7 @@ struct __stable_sort_switch {
   static const unsigned value = 128 * is_trivially_copy_assignable<_Tp>::value;
 };
 
+#if _LIBCPP_STD_VER >= 17
 template <class _Tp>
 constexpr unsigned __radix_sort_min_bound() {
   static_assert(is_integral<_Tp>::value);
@@ -214,6 +215,7 @@ constexpr unsigned __radix_sort_max_bound() {
 
   return 1 << 16;
 }
+#endif // _LIBCPP_STD_VER > 17
 
 template <class _AlgPolicy, class _Compare, class _RandomAccessIterator>
 void __stable_sort(_RandomAccessIterator __first,
@@ -237,6 +239,8 @@ void __stable_sort(_RandomAccessIterator __first,
     std::__insertion_sort<_AlgPolicy, _Compare>(__first, __last, __comp);
     return;
   }
+
+#if _LIBCPP_STD_VER >= 17
   constexpr auto __default_comp =
       __desugars_to_v<__totally_ordered_less_tag, __remove_cvref_t<_Compare>, value_type, value_type >;
   constexpr auto __integral_value     = is_integral_v<value_type >;
@@ -248,6 +252,8 @@ void __stable_sort(_RandomAccessIterator __first,
       return;
     }
   }
+#endif // _LIBCPP_STD_VER > 17
+
   typename iterator_traits<_RandomAccessIterator>::difference_type __l2 = __len / 2;
   _RandomAccessIterator __m                                             = __first + __l2;
   if (__len <= __buff_size) {

>From edd6ccb2b3108e6fde7d7e7e7b6127c56ddb8156 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=94=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9=20=D0=98=D0=B7?=
 =?UTF-8?q?=D0=B2=D0=BE=D0=BB=D0=BE=D0=B2?= <dmitriy at izvolov.ru>
Date: Thu, 19 Sep 2024 23:13:47 +0300
Subject: [PATCH 40/46] fix-dispatch-locally

---
 libcxx/include/__algorithm/stable_sort.h | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/libcxx/include/__algorithm/stable_sort.h b/libcxx/include/__algorithm/stable_sort.h
index 868e36bc12f0b3..814dade5ea0b21 100644
--- a/libcxx/include/__algorithm/stable_sort.h
+++ b/libcxx/include/__algorithm/stable_sort.h
@@ -25,6 +25,7 @@
 #include <__type_traits/desugars_to.h>
 #include <__type_traits/enable_if.h>
 #include <__type_traits/is_integral.h>
+#include <__type_traits/is_same.h>
 #include <__type_traits/is_trivially_assignable.h>
 #include <__type_traits/remove_cvref.h>
 #include <__utility/move.h>
@@ -243,7 +244,8 @@ void __stable_sort(_RandomAccessIterator __first,
 #if _LIBCPP_STD_VER >= 17
   constexpr auto __default_comp =
       __desugars_to_v<__totally_ordered_less_tag, __remove_cvref_t<_Compare>, value_type, value_type >;
-  constexpr auto __integral_value     = is_integral_v<value_type >;
+  constexpr auto __integral_value =
+      is_integral_v<value_type > && is_same_v< value_type&, iter_reference_t<_RandomAccessIterator>>;
   constexpr auto __allowed_radix_sort = __default_comp && __integral_value;
   if constexpr (__allowed_radix_sort) {
     if (__len <= __buff_size && __len >= static_cast<difference_type>(__radix_sort_min_bound<value_type>()) &&

>From 56e8073518289e521866bf3e5ccdb1818c10dec4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=94=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9=20=D0=98=D0=B7?=
 =?UTF-8?q?=D0=B2=D0=BE=D0=BB=D0=BE=D0=B2?= <dmitriy at izvolov.ru>
Date: Sun, 20 Oct 2024 17:42:08 +0300
Subject: [PATCH 41/46] module-map

---
 libcxx/include/module.modulemap | 1 +
 1 file changed, 1 insertion(+)

diff --git a/libcxx/include/module.modulemap b/libcxx/include/module.modulemap
index 9027c28632dcda..6c636d3999deea 100644
--- a/libcxx/include/module.modulemap
+++ b/libcxx/include/module.modulemap
@@ -487,6 +487,7 @@ module std [system] {
     module prev_permutation                       { header "__algorithm/prev_permutation.h" }
     module pstl                                   { header "__algorithm/pstl.h" }
     module push_heap                              { header "__algorithm/push_heap.h" }
+    module radix_sort                             { header "__algorithm/radix_sort.h" }
     module ranges_adjacent_find                   { header "__algorithm/ranges_adjacent_find.h" }
     module ranges_all_of                          { header "__algorithm/ranges_all_of.h" }
     module ranges_any_of                          { header "__algorithm/ranges_any_of.h" }

>From e90516e3c9f7d922e7db011660d098701fbc0eb6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=94=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9=20=D0=98=D0=B7?=
 =?UTF-8?q?=D0=B2=D0=BE=D0=BB=D0=BE=D0=B2?= <dmitriy at izvolov.ru>
Date: Thu, 7 Nov 2024 22:24:18 +0300
Subject: [PATCH 42/46] dash

---
 libcxx/include/__algorithm/radix_sort.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libcxx/include/__algorithm/radix_sort.h b/libcxx/include/__algorithm/radix_sort.h
index de664596eda525..89f05b15cf1754 100644
--- a/libcxx/include/__algorithm/radix_sort.h
+++ b/libcxx/include/__algorithm/radix_sort.h
@@ -11,7 +11,7 @@
 #define _LIBCPP___ALGORITHM_RADIX_SORT_H
 
 // This is an implementation of classic LSD radix sort algorithm, running in linear time and using `O(max(N, M))`
-// additional memory, where `N` is size of an input range, `M` — maximum value of
+// additional memory, where `N` is size of an input range, `M` - maximum value of
 // a radix of the sorted integer type. Type of the radix and its maximum value are determined at compile time
 // based on type returned by function `__radix`. The default radix is uint8.
 

>From 7e952a24440082524f5f96414f3f6e1ddcbc136f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=94=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9=20=D0=98=D0=B7?=
 =?UTF-8?q?=D0=B2=D0=BE=D0=BB=D0=BE=D0=B2?= <dmitriy at izvolov.ru>
Date: Thu, 7 Nov 2024 22:25:47 +0300
Subject: [PATCH 43/46] greater-equal

---
 libcxx/include/__algorithm/radix_sort.h  | 2 +-
 libcxx/include/__algorithm/stable_sort.h | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/libcxx/include/__algorithm/radix_sort.h b/libcxx/include/__algorithm/radix_sort.h
index 89f05b15cf1754..029ff4012ac449 100644
--- a/libcxx/include/__algorithm/radix_sort.h
+++ b/libcxx/include/__algorithm/radix_sort.h
@@ -323,7 +323,7 @@ __radix_sort(_RandomAccessIterator1 __first, _RandomAccessIterator1 __last, _Ran
   std::__radix_sort(__first, __last, __buffer, __identity{}, __low_byte_fn{});
 }
 
-#endif // _LIBCPP_STD_VER > 14
+#endif // _LIBCPP_STD_VER >= 14
 
 _LIBCPP_END_NAMESPACE_STD
 
diff --git a/libcxx/include/__algorithm/stable_sort.h b/libcxx/include/__algorithm/stable_sort.h
index 814dade5ea0b21..27a9d8218e3ed6 100644
--- a/libcxx/include/__algorithm/stable_sort.h
+++ b/libcxx/include/__algorithm/stable_sort.h
@@ -216,7 +216,7 @@ constexpr unsigned __radix_sort_max_bound() {
 
   return 1 << 16;
 }
-#endif // _LIBCPP_STD_VER > 17
+#endif // _LIBCPP_STD_VER >= 17
 
 template <class _AlgPolicy, class _Compare, class _RandomAccessIterator>
 void __stable_sort(_RandomAccessIterator __first,
@@ -254,7 +254,7 @@ void __stable_sort(_RandomAccessIterator __first,
       return;
     }
   }
-#endif // _LIBCPP_STD_VER > 17
+#endif // _LIBCPP_STD_VER >= 17
 
   typename iterator_traits<_RandomAccessIterator>::difference_type __l2 = __len / 2;
   _RandomAccessIterator __m                                             = __first + __l2;

>From 4b54c1d19b95c43c3150122bb46bf05a751ec205 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=94=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9=20=D0=98=D0=B7?=
 =?UTF-8?q?=D0=B2=D0=BE=D0=BB=D0=BE=D0=B2?= <dmitriy at izvolov.ru>
Date: Fri, 8 Nov 2024 01:56:27 +0300
Subject: [PATCH 44/46] countl

---
 libcxx/include/__bit/bit_log2.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libcxx/include/__bit/bit_log2.h b/libcxx/include/__bit/bit_log2.h
index bd1ee1a5b57e5a..f4146f456e4cc0 100644
--- a/libcxx/include/__bit/bit_log2.h
+++ b/libcxx/include/__bit/bit_log2.h
@@ -25,7 +25,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
 template <class _Tp>
 _LIBCPP_HIDE_FROM_ABI constexpr _Tp __bit_log2(_Tp __t) noexcept {
   static_assert(is_unsigned<_Tp>::value, "__bit_log2 requires an unsigned integer type");
-  return numeric_limits<_Tp>::digits - 1 - std::countl_zero(__t);
+  return numeric_limits<_Tp>::digits - 1 - std::__countl_zero(__t);
 }
 
 #endif // _LIBCPP_STD_VER >= 14

>From beee4e6add1e14231446fa9ed50331fda35caa88 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=94=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9=20=D0=98=D0=B7?=
 =?UTF-8?q?=D0=B2=D0=BE=D0=BB=D0=BE=D0=B2?= <dmitriy at izvolov.ru>
Date: Fri, 8 Nov 2024 09:13:34 +0300
Subject: [PATCH 45/46] iter-reference

---
 libcxx/include/__algorithm/stable_sort.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libcxx/include/__algorithm/stable_sort.h b/libcxx/include/__algorithm/stable_sort.h
index 27a9d8218e3ed6..38b1a2965f6924 100644
--- a/libcxx/include/__algorithm/stable_sort.h
+++ b/libcxx/include/__algorithm/stable_sort.h
@@ -245,7 +245,7 @@ void __stable_sort(_RandomAccessIterator __first,
   constexpr auto __default_comp =
       __desugars_to_v<__totally_ordered_less_tag, __remove_cvref_t<_Compare>, value_type, value_type >;
   constexpr auto __integral_value =
-      is_integral_v<value_type > && is_same_v< value_type&, iter_reference_t<_RandomAccessIterator>>;
+      is_integral_v<value_type > && is_same_v< value_type&, __iter_reference<_RandomAccessIterator>>;
   constexpr auto __allowed_radix_sort = __default_comp && __integral_value;
   if constexpr (__allowed_radix_sort) {
     if (__len <= __buff_size && __len >= static_cast<difference_type>(__radix_sort_min_bound<value_type>()) &&

>From 5af8bc77ebb634bb16f8822828ccdca282f2cf6a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=94=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9=20=D0=98=D0=B7?=
 =?UTF-8?q?=D0=B2=D0=BE=D0=BB=D0=BE=D0=B2?= <dmitriy at izvolov.ru>
Date: Fri, 8 Nov 2024 22:27:17 +0300
Subject: [PATCH 46/46] invoke-of

---
 libcxx/include/__algorithm/radix_sort.h | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/libcxx/include/__algorithm/radix_sort.h b/libcxx/include/__algorithm/radix_sort.h
index 029ff4012ac449..f7f912f5a6b7d8 100644
--- a/libcxx/include/__algorithm/radix_sort.h
+++ b/libcxx/include/__algorithm/radix_sort.h
@@ -88,10 +88,10 @@ __partial_sum_max(_InputIterator __first, _InputIterator __last, _OutputIterator
 
 template <class _Value, class _Map, class _Radix>
 struct __radix_sort_traits {
-  using __image_type = decay_t<invoke_result_t<_Map, _Value> >;
+  using __image_type = decay_t<typename __invoke_of<_Map, _Value>::type>;
   static_assert(is_unsigned<__image_type>::value, "");
 
-  using __radix_type = decay_t<invoke_result_t<_Radix, __image_type> >;
+  using __radix_type = decay_t<typename __invoke_of<_Radix, __image_type>::type>;
   static_assert(is_integral<__radix_type>::value, "");
 
   constexpr static auto __radix_value_range = numeric_limits<__radix_type>::max() + 1;
@@ -101,7 +101,7 @@ struct __radix_sort_traits {
 
 template <class _Value, class _Map>
 struct __counting_sort_traits {
-  using __image_type = decay_t<invoke_result_t<_Map, _Value> >;
+  using __image_type = decay_t<typename __invoke_of<_Map, _Value>::type>;
   static_assert(is_unsigned<__image_type>::value, "");
 
   constexpr static const auto __value_range = numeric_limits<__image_type>::max() + 1;
@@ -158,7 +158,7 @@ _LIBCPP_HIDE_FROM_ABI bool __collect_impl(
   using value_type                   = __iter_value_type<_ForwardIterator>;
   constexpr auto __radix_value_range = __radix_sort_traits<value_type, _Map, _Radix>::__radix_value_range;
 
-  auto __previous  = numeric_limits<invoke_result_t<_Map, value_type> >::min();
+  auto __previous  = numeric_limits<typename __invoke_of<_Map, value_type>::type>::min();
   auto __is_sorted = true;
   std::for_each(__first, __last, [&__counters, &__map, &__radix, &__previous, &__is_sorted](const auto& value) {
     auto __current = __map(value);



More information about the libcxx-commits mailing list