29  static_assert(std::is_integral<T>(), 
"This function only sorts integers.");
 
   31  if (array.size() <= 1)
 
   34  T max_value = *std::max_element(array.begin(), array.end());
 
   37  constexpr int bucket_size = 1 << BITS;
 
   38  T mask = (T(1) << BITS) - 1;
 
   50  std::array<std::int32_t, bucket_size> counter;
 
   51  std::array<std::int32_t, bucket_size + 1> offset;
 
   53  std::int32_t mask_offset = 0;
 
   54  std::vector<T> buffer(array.size());
 
   55  std::span<T> current_perm = array;
 
   56  std::span<T> next_perm = buffer;
 
   57  for (
int i = 0; i < its; i++)
 
   60    std::fill(counter.begin(), counter.end(), 0);
 
   63    for (T c : current_perm)
 
   64      counter[(c & mask) >> mask_offset]++;
 
   68    std::partial_sum(counter.begin(), counter.end(), std::next(offset.begin()));
 
   69    for (T c : current_perm)
 
   71      std::int32_t bucket = (c & mask) >> mask_offset;
 
   72      std::int32_t new_pos = offset[bucket + 1] - counter[bucket];
 
   73      next_perm[new_pos] = c;
 
   80    std::swap(current_perm, next_perm);
 
   85    std::copy(buffer.begin(), buffer.end(), array.begin());
 
 
   97void argsort_radix(std::span<const T> array, std::span<std::int32_t> perm)
 
   99  static_assert(std::is_integral_v<T>, 
"Integral required.");
 
  101  if (array.size() <= 1)
 
  104  const auto [min, max] = std::minmax_element(array.begin(), array.end());
 
  105  T range = *max - *min + 1;
 
  108  constexpr int bucket_size = 1 << BITS;
 
  109  T mask = (T(1) << BITS) - 1;
 
  110  std::int32_t mask_offset = 0;
 
  122  std::array<std::int32_t, bucket_size> counter;
 
  123  std::array<std::int32_t, bucket_size + 1> offset;
 
  125  std::vector<std::int32_t> perm2(perm.size());
 
  126  std::span<std::int32_t> current_perm = perm;
 
  127  std::span<std::int32_t> next_perm = perm2;
 
  128  for (
int i = 0; i < its; i++)
 
  131    std::fill(counter.begin(), counter.end(), 0);
 
  134    for (
auto cp : current_perm)
 
  136      T value = array[cp] - *min;
 
  137      std::int32_t bucket = (value & mask) >> mask_offset;
 
  143    std::partial_sum(counter.begin(), counter.end(), std::next(offset.begin()));
 
  146    for (
auto cp : current_perm)
 
  148      T value = array[cp] - *min;
 
  149      std::int32_t bucket = (value & mask) >> mask_offset;
 
  150      std::int32_t pos = offset[bucket + 1] - counter[bucket];
 
  155    std::swap(current_perm, next_perm);
 
  162    std::copy(perm2.begin(), perm2.end(), perm.begin());
 
 
  175std::vector<std::int32_t> 
sort_by_perm(std::span<const T> x, std::size_t shape1)
 
  177  static_assert(std::is_integral_v<T>, 
"Integral required.");
 
  179  assert(x.size() % shape1 == 0);
 
  180  const std::size_t shape0 = x.size() / shape1;
 
  181  std::vector<std::int32_t> perm(shape0);
 
  182  std::iota(perm.begin(), perm.end(), 0);
 
  186  std::vector<T> column(shape0);
 
  187  for (std::size_t i = 0; i < shape1; ++i)
 
  189    int col = shape1 - 1 - i;
 
  190    for (std::size_t j = 0; j < shape0; ++j)
 
  191      column[j] = x[j * shape1 + col];
 
  192    argsort_radix<T, BITS>(column, perm);
 
 
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:175