View difference between Paste ID: qDByQzjp and 0FaENjX0
SHOW: | | - or go back to the newest paste.
1
/* a - source array;
2
 * b - destination array;
3
 * c - user supplied storage for counting, if not NULL;
4
 * n - array size;
5
 * r - range of values key values;
6
 * k - key extractor.
7
 */
8
#define rsort_macro(a,b,c,n,r,k) {      \
9
    int _t[r],                          \
10
        *_c = (c) ? (c) : _t;           \
11
    memset(_c, 0, sizeof(_t));          \
12
                                        \
13
    for (int _i = 0; _i < (n); ++_i) {  \
14
        ++_c[k((a)[_i])];               \
15
    for (int _i = 1; _i < (r); ++_i) {  \
16
        _c[_i] += _c[_i-1];             \
17
    for (int _i = n-1; _i >= 0; --_i) { \
18
        (b)[--_c[k((a)[_i])]] = (a)[_i];\
19
}
20
#define bits(x,b_,_b) (*(unsigned long long *)&(x) >> (b_) & ((1 << (_b)) - 1))
21
#define swap(a,b) { typeof(a) _t = a; a = b; b = _t; }
22
23
/* count sort by least significant byte 0..7,
24
 * then by 8..15 and so on...
25
 */
26
void rsort_int(int *arr, int num)
27
{
28
    int *arr_ = malloc(num * sizeof(int));
29
30
    for (int shr = 0; shr < sizeof(int) * 8; shr += 8) {
31
        #define key(x) bits(x,shr,8)
32
        rsort_macro(arr, arr_, NULL, num, 0x100, key);
33
        #undef key
34
        swap(arr, arr_);
35
    }
36
37
    free(arr_);
38
}
39
40
/* radix sorting of double precision floating point numbers:
41
 * 1. by mantissa, just like integers;
42
 * 2. by exponent, just like integers;
43
 * (1.111... * 2^n < 1.000... * 2^(n+1))
44
 * 3. when sorted by absolute value, collect in reverse order,
45
 *    stack negative ones on the left side
46
 *    (descending by absolute value == ascending by signed value),
47
 *    and positive ones on the right side
48
 *    (descending-descending == ascending).
49
 */
50
void rsort_dbl(double *arr, int num)
51
{
52
    double *arr_ = malloc(num * sizeof(double));
53
54
    for (int shr = 0; shr < 52; shr += 13) {
55
        #define key(x) bits(x,shr,13)
56
        rsort_macro(arr, arr_, NULL, num, 0x2000, key);
57
        #undef key
58
        swap(arr, arr_);
59
    }
60
    #define key(x) bits(x,52,11)
61
    rsort_macro(arr, arr_, NULL, num, 0x800, key);
62
    #undef key
63
    swap(arr, arr_);
64
65
    for (int i = num-1, i_ = 0, _i = num-1; i >= 0; --i) {
66
        if (arr[i] < 0) arr_[i_++] = arr[i];
67
                   else arr_[_i--] = arr[i];
68
    }
69
    swap(arr, arr_);
70
  
71
    free(arr_);
72
}
73
74
/* sorting of strings:
75
 * 1. find maxlen
76
 * 2. sort by len
77
 * 3. sort trailing subarray of ones not shorter than maxlen
78
 *    by maxlen-1st letter
79
 * 4. sort trailing subarray of ones not shorter than maxlen-1
80
 *    by maxlen-2nd letter
81
 * 5. ...
82
 * 6. by 0th letter
83
 */
84
void rsort_str(unsigned char **arr, int num)
85
{
86
    // avoid computing same strlen twice
87
    struct str {
88
        unsigned char *ptr;
89
        size_t         len;
90
    } *arr_  = malloc(num * sizeof(struct str)),
91
      *arr__ = malloc(num * sizeof(struct str));
92
93
    int maxl = 0;
94
    for (int i = 0; i < num; ++i) {
95
        arr_[i].ptr = arr[i];
96
        arr_[i].len = strlen(arr[i]);
97
        if (maxl < arr_[i].len)
98
            maxl = arr_[i].len;
99
    }
100
101
    /* for l=0..maxl: lidx[l] will become the index of the first string not
102
     * shorter than l, when used for counting. Passing decremented pointer
103
     * would do the trick, if there was guarantee, that no zero-length strings
104
     * occur.
105
     */
106
    int lidx[maxl+1];
107
    #define key(x) ((x).len)
108
    rsort_macro(arr_, arr__, lidx, num, maxl+1, key);
109
    #undef key
110
    swap(arr_, arr__);
111
112
    for (int l = maxl, i = l-1; l > 0; --l, --i) {
113
        memcpy(arr__, arr_, lidx[l] * sizeof(struct str));
114
        #define key(x) ((x).ptr[i])
115
        rsort_macro(&arr_[lidx[l]], &arr__[lidx[l]], NULL,
116
                    num - lidx[l], 0x100, key);
117
        #undef key
118
        swap(arr_, arr__);
119
    }
120
121
    for (int i = 0; i < num; ++i) {
122
        arr[i] = arr_[i].ptr;
123
    }
124
    free(arr__);
125
    free(arr_);
126
}