-
Notifications
You must be signed in to change notification settings - Fork 7
/
fuse-ts-smoothsort.c
192 lines (163 loc) · 5.11 KB
/
fuse-ts-smoothsort.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
#include "fuse-ts.h"
#include "fuse-ts-filelist.h"
// by keeping these constants, we can avoid the tiresome business
// of keeping track of Dijkstra's b and c. Instead of keeping
// b and c, I will keep an index into this array.
static const int LP[] = { 1, 1, 3, 5, 9, 15, 25, 41, 67, 109,
177, 287, 465, 753, 1219, 1973, 3193, 5167, 8361, 13529, 21891,
35421, 57313, 92735, 150049, 242785, 392835, 635621, 1028457,
1664079, 2692537, 4356617, 7049155, 11405773, 18454929, 29860703,
48315633, 78176337, 126491971, 204668309, 331160281, 535828591,
866988873 // the next number is > 31 bits.
};
int numberOfTrailingZeros(int a) {
if (a == 0) {
return 32;
}
int i = 0;
for (; i < 31; i++) {
if ((a & 1) == 1) {
return i;
}
a = a >> 1;
}
return 32;
}
void sift(sourcefile_t ** m, int pshift, int head) {
// we do not use Floyd's improvements to the heapsort sift, because we
// are not doing what heapsort does - always moving nodes from near
// the bottom of the tree to the root.
sourcefile_t* val = m[head];
while (pshift > 1) {
int rt = head - 1;
int lf = head - 1 - LP[pshift - 2];
if (strcmp(val->filename, (m[lf])->filename) >= 0
&& strcmp(val->filename, (m[rt])->filename) >= 0) {
break;
}
if (strcmp((m[lf])->filename,(m[rt])->filename) >= 0) {
m[head] = m[lf];
head = lf;
pshift -= 1;
} else {
m[head] = m[rt];
head = rt;
pshift -= 2;
}
}
m[head] = val;
}
void trinkle(sourcefile_t ** m, unsigned int p, int pshift, int head, int isTrusty) {
sourcefile_t* val = m[head];
while (p != 1) {
int stepson = head - LP[pshift];
if (strcmp((m[stepson])->filename, val->filename) <= 0)
break; // current node is greater than head. Sift.
// no need to check this if we know the current node is trusty,
// because we just checked the head (which is val, in the first
// iteration)
if (!isTrusty && pshift > 1) {
int rt = head - 1;
int lf = head - 1 - LP[pshift - 2];
if (strcmp((m[rt])->filename, (m[stepson])->filename) >= 0
|| strcmp((m[lf])->filename, (m[stepson])->filename) >= 0)
break;
}
m[head] = m[stepson];
head = stepson;
int trail = numberOfTrailingZeros(p & ~1);
p >>= trail;
pshift += trail;
isTrusty = 0 /* false */;
}
if (!isTrusty) {
m[head] = val;
sift(m, pshift, head);
}
}
void smoothsort(sourcefile_t ** m, int lo, int hi) {
int head = lo; // the offset of the first element of the prefix into m
// These variables need a little explaining. If our string of heaps
// is of length 38, then the heaps will be of size 25+9+3+1, which are
// Leonardo numbers 6, 4, 2, 1.
// Turning this into a binary number, we get b01010110 = 0x56. We represent
// this number as a pair of numbers by right-shifting all the zeros and
// storing the mantissa and exponent as "p" and "pshift".
// This is handy, because the exponent is the index into L[] giving the
// size of the rightmost heap, and because we can instantly find out if
// the rightmost two heaps are consecutive Leonardo numbers by checking
// (p&3)==3
unsigned int p = 1; // the bitmap of the current standard concatenation >> pshift
int pshift = 1;
while (head < hi) {
if ((p & 3) == 3) {
// Add 1 by merging the first two blocks into a larger one.
// The next Leonardo number is one bigger.
sift(m, pshift, head);
p >>= 2;
pshift += 2;
} else {
// adding a new block of length 1
if (LP[pshift - 1] >= hi - head) {
// this block is its final size.
trinkle(m, p, pshift, head, 0 /* false*/ );
} else {
// this block will get merged. Just make it trusty.
sift(m, pshift, head);
}
if (pshift == 1) {
// LP[1] is being used, so we add use LP[0]
p <<= 1;
pshift--;
} else {
// shift out to position 1, add LP[1]
p <<= (pshift - 1);
pshift = 1;
}
}
p |= 1;
head++;
}
trinkle(m, p, pshift, head, 0 /* false */);
while (pshift != 1 || p != 1) {
if (pshift <= 1) {
// block of length 1. No fiddling needed
int trail = numberOfTrailingZeros(p & ~1);
p >>= trail;
pshift += trail;
} else {
p <<= 2;
p ^= 7;
pshift -= 2;
// This block gets broken into three bits. The rightmost
// bit is a block of length 1. The left hand part is split into
// two, a block of length LP[pshift+1] and one of LP[pshift].
// Both these two are appropriately heapified, but the root
// nodes are not necessarily in order. We therefore semitrinkle
// both of them
trinkle(m, p >> 1, pshift + 1, head - LP[pshift] - 1, 1 /* true */);
trinkle(m, p, pshift, head - 1, 1 /* true */);
}
head--;
}
}
sourcefile_t * smoothsort_list (sourcefile_t * files) {
int num = 0;
sourcefile_t **t = list_to_array (files, &num);
if (num <= 0) {
return files;
}
smoothsort(t, 0, num - 1);
// liste neu verketten
(t[0])->prev = NULL;
(t[num - 1])->next = NULL;
int c = 0;
for (; c < num - 1; c++) {
(t[c])->next = t[c + 1];
(t[c + 1])->prev = t[c];
}
(t[0])->tailhelper = t[num - 1];
files = t[0];
free (t);
return files;
}