|
1 | 1 | #include <algorithm>
|
2 | 2 | #include <functional>
|
3 |
| -#include <random> |
| 3 | +#include <cmath> |
4 | 4 |
|
5 | 5 | #include <parlay/parallel.h>
|
6 | 6 | #include <parlay/primitives.h>
|
7 |
| -#include <parlay/random.h> |
8 | 7 | #include <parlay/slice.h>
|
9 |
| -#include <parlay/utilities.h> |
10 | 8 |
|
11 |
| -#include "helper/heap_tree.h" |
12 | 9 | #include "counting_sort.h"
|
13 | 10 |
|
14 | 11 | // **************************************************************
|
|
19 | 16 | // buckets based on the high bits and then recurses on each bucket.
|
20 | 17 | // The bottom up is a standard radix sort starting on low-order bits
|
21 | 18 | // and taking advantage of the stability of each counting sort.
|
| 19 | +// Uses counting_sort for each block of the radix. |
22 | 20 | //
|
23 | 21 | // Flips back and forth between in and out, with "inplace" keeping track
|
24 | 22 | // of whether the result should be in in (or if false, in out).
|
@@ -51,36 +49,35 @@ void radix_sort(Range in, Range out, long bits, bool inplace) {
|
51 | 49 | if (n < cutoff)
|
52 | 50 | bottom_up_radix_sort(in, out, bits, 0, inplace);
|
53 | 51 | else {
|
54 |
| - // number of bits in bucket count (e.g. 8 would mean 256 buckets) |
55 |
| - long radix_bits = std::min<long>(bits, std::ceil(std::log2(2*n/cutoff))); |
| 52 | + // number of bits in radix |
| 53 | + long radix_bits = std::min<long>(bits, std::min<long>(10l, std::ceil(std::log2(2*n/cutoff)))); |
56 | 54 | long num_buckets = 1l << radix_bits;
|
57 | 55 |
|
58 | 56 | // extract the needed bits for the keys
|
59 | 57 | auto keys = parlay::delayed::tabulate(n, [&] (long i) {
|
60 | 58 | return (in[i] >> bits - radix_bits) & (num_buckets-1);});
|
61 | 59 |
|
62 |
| - // sort into the buckets |
| 60 | + // sort in into the out based on keys |
63 | 61 | auto offsets = counting_sort(in.begin(), in.end(), out.begin(), keys.begin(),
|
64 | 62 | num_buckets);
|
65 | 63 |
|
66 | 64 | // now recursively sort each bucket
|
67 | 65 | parlay::parallel_for(0, num_buckets, [&] (long i) {
|
68 |
| - long first = offsets[i]; // start of region |
69 |
| - long last = offsets[i+1]; // end of region |
| 66 | + long first = offsets[i]; // start of bucket |
| 67 | + long last = offsets[i+1]; // end of bucket |
70 | 68 | // note that order of in and out is flipped (as is inplace)
|
71 | 69 | radix_sort(out.cut(first,last), in.cut(first,last),
|
72 | 70 | bits - radix_bits, !inplace);
|
73 | 71 | }, 1);
|
74 | 72 | }
|
75 | 73 | }
|
76 | 74 |
|
77 |
| -// A wraper that calls integer_sort_ |
| 75 | +// An inplace (i.e., result is in the same place as the input) integer_sort |
| 76 | +// Requires O(n) temp space |
78 | 77 | template <typename Range>
|
79 |
| -parlay::sequence<typename Range::value_type> |
80 |
| -integer_sort(Range& in, long bits) { |
81 |
| - auto out = parlay::sequence<typename Range::value_type>::uninitialized(in.size()); |
| 78 | +void integer_sort(Range& in, long bits) { |
| 79 | + auto tmp = parlay::sequence<typename Range::value_type>::uninitialized(in.size()); |
82 | 80 | auto in_slice = parlay::make_slice(in);
|
83 |
| - auto out_slice = parlay::make_slice(out); |
84 |
| - radix_sort(in_slice, out_slice, bits, false); |
85 |
| - return out; |
| 81 | + auto tmp_slice = parlay::make_slice(tmp); |
| 82 | + radix_sort(in_slice, tmp_slice, bits, true); |
86 | 83 | }
|
0 commit comments