104 DCHECK_LE(values.size(),
105 static_cast<size_t>(std::numeric_limits<uint32_t>::max()));
106 const uint32_t
size = values.size();
115 std::vector<uint32_t> count(num_passes << radix_width, 0);
116 uint32_t*
const count_ptr = count.data();
120 constexpr uint32_t kRadixMask = (1 << radix_width) - 1;
121 for (
const T
value : values) {
122 for (
int p = 0; p < num_passes; ++p) {
123 ++count_ptr[(p << radix_width) +
124 ((absl::bit_cast<U>(
value) >> (radix_width * p)) &
130 uint32_t sum[num_passes] = {};
131 for (
int i = 0; i < (1 << radix_width); ++i) {
133 for (
int p = 0; p < num_passes; ++p) {
134 const uint32_t old_sum = sum[p];
135 sum[p] += count_ptr[(p << radix_width) + i];
136 count_ptr[(p << radix_width) + i] = old_sum;
152 constexpr int kNumBitsInTopRadix =
153 std::numeric_limits<U>::digits - (num_passes - 1) * radix_width;
155 if constexpr (std::is_integral_v<T> && std::is_signed_v<T> &&
156 kNumBitsInTopRadix > 0 && kNumBitsInTopRadix <= radix_width) {
157 uint32_t*
const last_pass_count =
158 count_ptr + ((num_passes - 1) << radix_width);
159 const uint32_t num_nonnegative_values =
160 last_pass_count[1 << (kNumBitsInTopRadix - 1)];
161 if (num_nonnegative_values !=
size) {
167 const uint32_t num_negative_values =
size - num_nonnegative_values;
168 for (
int i = 0; i < (1 << (kNumBitsInTopRadix - 1)); ++i) {
170 last_pass_count[i] += num_negative_values;
172 last_pass_count[i + (1 << (kNumBitsInTopRadix - 1))] -=
173 num_nonnegative_values;
179 std::vector<T> tmp(
size);
180 T* from = values.data();
183 for (
int pass = 0; pass < num_passes; ++pass, radix += radix_width) {
184 uint32_t*
const cur_count_ptr = count_ptr + (pass << radix_width);
185 const T*
const from_end = from +
size;
186 for (T* ptr = from; ptr < from_end; ++ptr) {
187 to[cur_count_ptr[(absl::bit_cast<U>(*ptr) >> radix) & kRadixMask]++] =
195 if constexpr (!std::is_integral_v<T> && std::is_signed_v<T> &&
196 kNumBitsInTopRadix > 0 && kNumBitsInTopRadix <= radix_width) {
197 uint32_t*
const last_pass_count =
198 count_ptr + ((num_passes - 1) << radix_width);
199 const uint32_t num_nonnegative_values =
200 last_pass_count[(1 << (kNumBitsInTopRadix - 1)) - 1];
201 if (num_nonnegative_values !=
size) {
205 const uint32_t num_negative_values =
size - num_nonnegative_values;
206 if constexpr (num_passes % 2) {
209 std::memcpy(values.data() + num_negative_values, tmp.data(),
210 num_nonnegative_values *
sizeof(T));
212 DCHECK_EQ(from, tmp.data());
213 for (uint32_t i = 0; i < num_negative_values; ++i) {
214 values[i] = from[
size - 1 - i];
219 std::memcpy(tmp.data(), values.data() + num_nonnegative_values,
220 num_negative_values *
sizeof(T));
224 std::memmove(values.data() + num_negative_values, values.data(),
225 num_nonnegative_values *
sizeof(T));
226 DCHECK_EQ(
to, tmp.data());
227 for (uint32_t i = 0; i < num_negative_values; ++i) {
228 values[i] =
to[num_negative_values - 1 - i];
238 if constexpr (num_passes % 2) {
239 std::memcpy(values.data(), from,
size *
sizeof(T));