80 using bits_t = std::make_unsigned_t<
81 std::remove_cvref_t<std::invoke_result_t<P, std::iter_value_t<R>>>>;
82 constexpr bits_t _BITS = BITS;
85 using T = std::iter_value_t<R>;
88 using I = std::remove_cvref_t<std::invoke_result_t<P, T>>;
89 using uI = std::make_unsigned_t<I>;
91 if constexpr (!std::is_same_v<uI, I>)
98 if (range.size() <= 1)
101 uI max_value = proj(*std::ranges::max_element(range, std::less{}, proj));
104 constexpr uI bucket_size = 1 << _BITS;
105 uI mask = (uI(1) << _BITS) - 1;
113 if (
bool all_first_bit = std::ranges::all_of(
114 range, [&proj](
const auto& e)
115 {
return proj(e) & (uI(1) << (
sizeof(uI) * 8 - 1)); });
118 max_value = max_value & ~(uI(1) << (
sizeof(uI) * 8 - 1));
128 std::array<I, bucket_size> counter;
129 std::array<I, bucket_size + 1> offset;
132 std::vector<T> buffer(range.size());
133 std::span<T> current_perm = range;
134 std::span<T> next_perm = buffer;
135 for (I i = 0; i < its; i++)
138 std::ranges::fill(counter, 0);
141 for (
auto c : current_perm)
142 counter[(proj(c) & mask) >> mask_offset]++;
146 std::partial_sum(counter.begin(), counter.end(), std::next(offset.begin()));
147 for (
auto c : current_perm)
149 uI bucket = (proj(c) & mask) >> mask_offset;
150 uI new_pos = offset[bucket + 1] - counter[bucket];
151 next_perm[new_pos] = c;
155 mask = mask << _BITS;
156 mask_offset += _BITS;
158 std::swap(current_perm, next_perm);
163 std::ranges::copy(buffer, range.begin());
177std::vector<std::int32_t>
sort_by_perm(std::span<const T> x, std::size_t shape1)
179 static_assert(std::is_integral_v<T>,
"Integral required.");
182 return std::vector<std::int32_t>{};
185 assert(x.size() % shape1 == 0);
186 const std::size_t shape0 = x.size() / shape1;
187 std::vector<std::int32_t> perm(shape0);
188 std::iota(perm.begin(), perm.end(), 0);
192 std::vector<T> column(shape0);
193 for (std::size_t i = 0; i < shape1; ++i)
195 std::size_t col = shape1 - 1 - i;
196 for (std::size_t j = 0; j < shape0; ++j)
197 column[j] = x[j * shape1 + col];
199 {
return column.get()[index]; });
constexpr void radix_sort(R &&range, P proj={})
Sort a range with radix sorting algorithm. The bucket size is determined by the number of bits to sor...
Definition sort.h:78
std::vector< std::int32_t > sort_by_perm(std::span< const T > x, std::size_t shape1)
Compute the permutation array that sorts a 2D array by row.
Definition sort.h:177