83 using bits_t = std::make_unsigned_t<
84 std::remove_cvref_t<std::invoke_result_t<P, std::iter_value_t<R>>>>;
85 constexpr bits_t _BITS = BITS;
88 using T = std::iter_value_t<R>;
91 using I = std::remove_cvref_t<std::invoke_result_t<P, T>>;
92 using uI = std::make_unsigned_t<I>;
94 if constexpr (!std::is_same_v<uI, I>)
101 if (range.size() <= 1)
105 constexpr uI bucket_size = 1 << _BITS;
106 uI mask = (uI(1) << _BITS) - 1;
107 constexpr uI top_bit = uI(1) << (
sizeof(uI) * 8 - 1);
114 std::array<I, bucket_size> counter{};
115 std::array<I, bucket_size> offset;
122 bool all_first_bit =
true;
123 for (
const auto& e : range)
126 max_value = std::max(max_value, v);
127 all_first_bit = all_first_bit && (v & top_bit);
132 max_value = max_value & ~top_bit;
144 std::vector<T> buffer(range.size());
145 std::span<T> current_perm = range;
146 std::span<T> next_perm = buffer;
147 for (I i = 0; i < its; i++)
152 std::ranges::fill(counter, 0);
155 for (
auto c : current_perm)
156 counter[(proj(c) & mask) >> mask_offset]++;
161 std::exclusive_scan(counter.begin(), counter.end(), offset.begin(), I(0));
162 for (
auto c : current_perm)
164 uI bucket = (proj(c) & mask) >> mask_offset;
165 next_perm[offset[bucket]++] = c;
168 mask = mask << _BITS;
169 mask_offset += _BITS;
171 std::swap(current_perm, next_perm);
176 std::ranges::copy(buffer, range.begin());
200std::vector<std::int32_t>
sort_by_perm(std::span<const T> x, std::size_t shape1,
201 std::optional<std::size_t> ncols
204 static_assert(std::is_integral_v<T>,
"Integral required.");
207 return std::vector<std::int32_t>{};
210 assert(x.size() % shape1 == 0);
211 std::size_t n = ncols.value_or(shape1);
213 const std::size_t shape0 = x.size() / shape1;
214 std::vector<std::int32_t> perm(shape0);
215 std::iota(perm.begin(), perm.end(), 0);
220 std::vector<T> column(shape0);
221 for (std::size_t i = 0; i < n; ++i)
223 std::size_t col = n - 1 - i;
224 for (std::size_t j = 0; j < shape0; ++j)
225 column[j] = x[j * shape1 + col];
227 {
return column.get()[index]; });
252 static_assert(std::is_integral_v<T>,
"Integral required.");
256 std::size_t shape1 = x.size();
257 std::size_t shape0 = x.front().size();
259 std::vector<std::int32_t> perm(shape0);
260 std::iota(perm.begin(), perm.end(), 0);
264 for (std::size_t i = 0; i < shape1; ++i)
266 std::size_t col = shape1 - 1 - i;
267 assert(x[col].size() == shape0);
268 std::span<const T> column = x[col];
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:81
std::vector< std::int32_t > sort_by_perm(std::span< const T > x, std::size_t shape1, std::optional< std::size_t > ncols=std::nullopt)
Compute the permutation array that sorts a 2D array by row.
Definition sort.h:200