<tb@panthema.net>
<http://www.gnu.org/licenses/>
template <typename Iterator>
static inline void radixsort(Iterator begin, Iterator end, size_t depth = 0)
{
if (end - begin < 128) {
std::sort(begin, end);
return;
}
const size_t K = begin->radixsort_limit();
size_t bucketsize[K];
memset(bucketsize, 0, sizeof(bucketsize));
for (Iterator i = begin; i != end; ++i) {
++bucketsize[ i->radixsort_index(depth) ];
}
ssize_t bucketindex[K];
bucketindex[0] = bucketsize[0];
size_t last_bucket_size = bucketsize[0];
for (size_t i = 1; i < K; ++i) {
bucketindex[i] = bucketindex[i-1] + bucketsize[i];
if (bucketsize[i]) last_bucket_size = bucketsize[i];
}
for (Iterator i = begin, j; i < end - last_bucket_size; )
{
while ( (j = begin + --bucketindex[ i->radixsort_index(depth) ]) > i )
{
std::swap(*i, *j);
}
i += bucketsize[ i->radixsort_index(depth) ];
}
Iterator i = begin + bucketsize[0];
for (size_t j = 1; j < K; i += bucketsize[j++]) {
if (bucketsize[j] <= 1) continue;
radixsort(i, i + bucketsize[j], depth+1);
}
}
template <typename Iterator>
static inline void radixsort_oracle(Iterator begin, Iterator end, size_t depth = 0)
{
if (end - begin < 128) {
std::sort(begin, end);
return;
}
const size_t K = begin->radixsort_limit();
size_t bucketsize[K];
memset(bucketsize, 0, sizeof(bucketsize));
typedef typename Iterator::value_type::radixsort_oracle_type oracle_type;
oracle_type* oracle = (oracle_type*)malloc((end - begin) * sizeof(oracle_type));
size_t ic = 0, jc;
for (Iterator i = begin; i != end; ++i, ++ic) {
++bucketsize[ oracle[ic] = i->radixsort_index(depth) ];
}
ssize_t bucketindex[K];
bucketindex[0] = bucketsize[0];
size_t last_bucket_size = bucketsize[0];
for (size_t i = 1; i < K; ++i) {
bucketindex[i] = bucketindex[i-1] + bucketsize[i];
if (bucketsize[i]) last_bucket_size = bucketsize[i];
}
ic = 0;
for (Iterator i = begin, j; i < end - last_bucket_size; )
{
while ( (jc = --bucketindex[ oracle[ic] ]) > ic )
{
j = begin + jc;
assert( j > i );
std::swap(*i, *j);
std::swap(oracle[ic], oracle[jc]);
}
i += bucketsize[ oracle[ic] ];
ic += bucketsize[ oracle[ic] ];
}
free(oracle);
Iterator i = begin + bucketsize[0];
for (size_t j = 1; j < K; i += bucketsize[j++]) {
if (bucketsize[j] <= 1) continue;
radixsort_oracle(i, i + bucketsize[j], depth+1);
}
}
template <typename Transform, typename Iterator>
static inline void radixsort_transform(Iterator begin, Iterator end, size_t depth = 0)
{
if (end - begin < 128 || depth >= Transform::maxdepth) {
std::sort(begin, end);
return;
}
const size_t K = Transform::limit(depth);
std::vector<size_t> bucketsize (K, 0);
for (Iterator i = begin; i != end; ++i) {
++bucketsize[ Transform::index(*i, depth) ];
}
size_t* bucketindex = new size_t[K];
bucketindex[0] = bucketsize[0];
size_t last_bucket_size = bucketsize[0];
for (size_t i = 1; i < K; ++i) {
bucketindex[i] = bucketindex[i-1] + bucketsize[i];
if (bucketsize[i]) last_bucket_size = bucketsize[i];
}
for (Iterator i = begin, j; i < end - last_bucket_size; )
{
while ( (j = begin + --bucketindex[ Transform::index(*i, depth) ]) > i )
{
std::swap(*i, *j);
}
i += bucketsize[ Transform::index(*i, depth) ];
}
delete [] bucketindex;
if (bucketsize[0] > 1)
Transform::subsort(begin, begin + bucketsize[0]);
Iterator i = begin + bucketsize[0];
for (size_t j = 1; j < K; i += bucketsize[j++]) {
if (bucketsize[j] <= 1) continue;
radixsort_transform<Transform,Iterator>(i, i + bucketsize[j], depth+1);
}
}
template <typename Transform, typename Iterator>
size_t radixsort_transform_maxmemory(size_t n)
{
const size_t K = Transform::limit(0);
typedef typename Transform::oracle_type oracle_type;
return (Transform::maxdepth+1) * K * sizeof(size_t)
+ n * sizeof(oracle_type);
}
template <typename Transform, typename Iterator>
static inline void radixsort_transform_oracle(Iterator begin, Iterator end, Transform transform, size_t depth = 0)
{
if (end - begin < 32 || depth >= Transform::maxdepth) {
std::sort(begin, end, transform);
return;
}
const size_t K = Transform::limit(depth);
std::vector<size_t> bucketsize (K, 0);
typedef typename Transform::oracle_type oracle_type;
oracle_type* oracle = (oracle_type*)malloc((end - begin) * sizeof(oracle_type));
size_t ic = 0, jc;
for (Iterator i = begin; i != end; ++i, ++ic) {
++bucketsize[ oracle[ic] = transform.index(*i,depth) ];
}
size_t* bucketindex = (size_t*)malloc(K * sizeof(size_t));
bucketindex[0] = bucketsize[0];
size_t last_bucket_size = bucketsize[0];
for (size_t i = 1; i < K; ++i) {
bucketindex[i] = bucketindex[i-1] + bucketsize[i];
if (bucketsize[i]) last_bucket_size = bucketsize[i];
}
ic = 0;
for (Iterator i = begin, j; i < end - last_bucket_size; )
{
while ( (jc = --bucketindex[ oracle[ic] ]) > ic )
{
j = begin + jc;
assert( j > i );
std::swap(*i, *j);
std::swap(oracle[ic], oracle[jc]);
}
i += bucketsize[ oracle[ic] ];
ic += bucketsize[ oracle[ic] ];
}
free(bucketindex);
free(oracle);
if (bucketsize[0] > 1)
transform.subsort(begin, begin + bucketsize[0]);
Iterator i = begin + bucketsize[0];
for (size_t j = 1; j < K; i += bucketsize[j++]) {
if (bucketsize[j] <= 1) continue;
radixsort_transform_oracle<Transform,Iterator>(i, i + bucketsize[j], transform, depth+1);
}
}