rlm@1
|
1 /* BwtSort.c -- BWT block sorting
|
rlm@1
|
2 2008-08-17
|
rlm@1
|
3 Igor Pavlov
|
rlm@1
|
4 Public domain */
|
rlm@1
|
5
|
rlm@1
|
6 #include "BwtSort.h"
|
rlm@1
|
7 #include "Sort.h"
|
rlm@1
|
8
|
rlm@1
|
9 /* #define BLOCK_SORT_USE_HEAP_SORT */
|
rlm@1
|
10
|
rlm@1
|
11 #define NO_INLINE MY_FAST_CALL
|
rlm@1
|
12
|
rlm@1
|
13 /* Don't change it !!! */
|
rlm@1
|
14 #define kNumHashBytes 2
|
rlm@1
|
15 #define kNumHashValues (1 << (kNumHashBytes * 8))
|
rlm@1
|
16
|
rlm@1
|
17 /* kNumRefBitsMax must be < (kNumHashBytes * 8) = 16 */
|
rlm@1
|
18 #define kNumRefBitsMax 12
|
rlm@1
|
19
|
rlm@1
|
20 #define BS_TEMP_SIZE kNumHashValues
|
rlm@1
|
21
|
rlm@1
|
22 #ifdef BLOCK_SORT_EXTERNAL_FLAGS
|
rlm@1
|
23
|
rlm@1
|
24 /* 32 Flags in UInt32 word */
|
rlm@1
|
25 #define kNumFlagsBits 5
|
rlm@1
|
26 #define kNumFlagsInWord (1 << kNumFlagsBits)
|
rlm@1
|
27 #define kFlagsMask (kNumFlagsInWord - 1)
|
rlm@1
|
28 #define kAllFlags 0xFFFFFFFF
|
rlm@1
|
29
|
rlm@1
|
30 #else
|
rlm@1
|
31
|
rlm@1
|
32 #define kNumBitsMax 20
|
rlm@1
|
33 #define kIndexMask ((1 << kNumBitsMax) - 1)
|
rlm@1
|
34 #define kNumExtraBits (32 - kNumBitsMax)
|
rlm@1
|
35 #define kNumExtra0Bits (kNumExtraBits - 2)
|
rlm@1
|
36 #define kNumExtra0Mask ((1 << kNumExtra0Bits) - 1)
|
rlm@1
|
37
|
rlm@1
|
38 #define SetFinishedGroupSize(p, size) \
|
rlm@1
|
39 { *(p) |= ((((size) - 1) & kNumExtra0Mask) << kNumBitsMax); \
|
rlm@1
|
40 if ((size) > (1 << kNumExtra0Bits)) { \
|
rlm@1
|
41 *(p) |= 0x40000000; *((p) + 1) |= ((((size) - 1)>> kNumExtra0Bits) << kNumBitsMax); } } \
|
rlm@1
|
42
|
rlm@1
|
43 static void SetGroupSize(UInt32 *p, UInt32 size)
|
rlm@1
|
44 {
|
rlm@1
|
45 if (--size == 0)
|
rlm@1
|
46 return;
|
rlm@1
|
47 *p |= 0x80000000 | ((size & kNumExtra0Mask) << kNumBitsMax);
|
rlm@1
|
48 if (size >= (1 << kNumExtra0Bits))
|
rlm@1
|
49 {
|
rlm@1
|
50 *p |= 0x40000000;
|
rlm@1
|
51 p[1] |= ((size >> kNumExtra0Bits) << kNumBitsMax);
|
rlm@1
|
52 }
|
rlm@1
|
53 }
|
rlm@1
|
54
|
rlm@1
|
55 #endif
|
rlm@1
|
56
|
rlm@1
|
57 /*
|
rlm@1
|
58 SortGroup - is recursive Range-Sort function with HeapSort optimization for small blocks
|
rlm@1
|
59 "range" is not real range. It's only for optimization.
|
rlm@1
|
60 returns: 1 - if there are groups, 0 - no more groups
|
rlm@1
|
61 */
|
rlm@1
|
62
|
rlm@1
|
63 UInt32 NO_INLINE SortGroup(UInt32 BlockSize, UInt32 NumSortedBytes, UInt32 groupOffset, UInt32 groupSize, int NumRefBits, UInt32 *Indices
|
rlm@1
|
64 #ifndef BLOCK_SORT_USE_HEAP_SORT
|
rlm@1
|
65 , UInt32 left, UInt32 range
|
rlm@1
|
66 #endif
|
rlm@1
|
67 )
|
rlm@1
|
68 {
|
rlm@1
|
69 UInt32 *ind2 = Indices + groupOffset;
|
rlm@1
|
70 UInt32 *Groups;
|
rlm@1
|
71 if (groupSize <= 1)
|
rlm@1
|
72 {
|
rlm@1
|
73 /*
|
rlm@1
|
74 #ifndef BLOCK_SORT_EXTERNAL_FLAGS
|
rlm@1
|
75 SetFinishedGroupSize(ind2, 1);
|
rlm@1
|
76 #endif
|
rlm@1
|
77 */
|
rlm@1
|
78 return 0;
|
rlm@1
|
79 }
|
rlm@1
|
80 Groups = Indices + BlockSize + BS_TEMP_SIZE;
|
rlm@1
|
81 if (groupSize <= ((UInt32)1 << NumRefBits)
|
rlm@1
|
82 #ifndef BLOCK_SORT_USE_HEAP_SORT
|
rlm@1
|
83 && groupSize <= range
|
rlm@1
|
84 #endif
|
rlm@1
|
85 )
|
rlm@1
|
86 {
|
rlm@1
|
87 UInt32 *temp = Indices + BlockSize;
|
rlm@1
|
88 UInt32 j;
|
rlm@1
|
89 UInt32 mask, thereAreGroups, group, cg;
|
rlm@1
|
90 {
|
rlm@1
|
91 UInt32 gPrev;
|
rlm@1
|
92 UInt32 gRes = 0;
|
rlm@1
|
93 {
|
rlm@1
|
94 UInt32 sp = ind2[0] + NumSortedBytes;
|
rlm@1
|
95 if (sp >= BlockSize) sp -= BlockSize;
|
rlm@1
|
96 gPrev = Groups[sp];
|
rlm@1
|
97 temp[0] = (gPrev << NumRefBits);
|
rlm@1
|
98 }
|
rlm@1
|
99
|
rlm@1
|
100 for (j = 1; j < groupSize; j++)
|
rlm@1
|
101 {
|
rlm@1
|
102 UInt32 sp = ind2[j] + NumSortedBytes;
|
rlm@1
|
103 UInt32 g;
|
rlm@1
|
104 if (sp >= BlockSize) sp -= BlockSize;
|
rlm@1
|
105 g = Groups[sp];
|
rlm@1
|
106 temp[j] = (g << NumRefBits) | j;
|
rlm@1
|
107 gRes |= (gPrev ^ g);
|
rlm@1
|
108 }
|
rlm@1
|
109 if (gRes == 0)
|
rlm@1
|
110 {
|
rlm@1
|
111 #ifndef BLOCK_SORT_EXTERNAL_FLAGS
|
rlm@1
|
112 SetGroupSize(ind2, groupSize);
|
rlm@1
|
113 #endif
|
rlm@1
|
114 return 1;
|
rlm@1
|
115 }
|
rlm@1
|
116 }
|
rlm@1
|
117
|
rlm@1
|
118 HeapSort(temp, groupSize);
|
rlm@1
|
119 mask = ((1 << NumRefBits) - 1);
|
rlm@1
|
120 thereAreGroups = 0;
|
rlm@1
|
121
|
rlm@1
|
122 group = groupOffset;
|
rlm@1
|
123 cg = (temp[0] >> NumRefBits);
|
rlm@1
|
124 temp[0] = ind2[temp[0] & mask];
|
rlm@1
|
125
|
rlm@1
|
126 {
|
rlm@1
|
127 #ifdef BLOCK_SORT_EXTERNAL_FLAGS
|
rlm@1
|
128 UInt32 *Flags = Groups + BlockSize;
|
rlm@1
|
129 #else
|
rlm@1
|
130 UInt32 prevGroupStart = 0;
|
rlm@1
|
131 #endif
|
rlm@1
|
132
|
rlm@1
|
133 for (j = 1; j < groupSize; j++)
|
rlm@1
|
134 {
|
rlm@1
|
135 UInt32 val = temp[j];
|
rlm@1
|
136 UInt32 cgCur = (val >> NumRefBits);
|
rlm@1
|
137
|
rlm@1
|
138 if (cgCur != cg)
|
rlm@1
|
139 {
|
rlm@1
|
140 cg = cgCur;
|
rlm@1
|
141 group = groupOffset + j;
|
rlm@1
|
142
|
rlm@1
|
143 #ifdef BLOCK_SORT_EXTERNAL_FLAGS
|
rlm@1
|
144 {
|
rlm@1
|
145 UInt32 t = group - 1;
|
rlm@1
|
146 Flags[t >> kNumFlagsBits] &= ~(1 << (t & kFlagsMask));
|
rlm@1
|
147 }
|
rlm@1
|
148 #else
|
rlm@1
|
149 SetGroupSize(temp + prevGroupStart, j - prevGroupStart);
|
rlm@1
|
150 prevGroupStart = j;
|
rlm@1
|
151 #endif
|
rlm@1
|
152 }
|
rlm@1
|
153 else
|
rlm@1
|
154 thereAreGroups = 1;
|
rlm@1
|
155 {
|
rlm@1
|
156 UInt32 ind = ind2[val & mask];
|
rlm@1
|
157 temp[j] = ind;
|
rlm@1
|
158 Groups[ind] = group;
|
rlm@1
|
159 }
|
rlm@1
|
160 }
|
rlm@1
|
161
|
rlm@1
|
162 #ifndef BLOCK_SORT_EXTERNAL_FLAGS
|
rlm@1
|
163 SetGroupSize(temp + prevGroupStart, j - prevGroupStart);
|
rlm@1
|
164 #endif
|
rlm@1
|
165 }
|
rlm@1
|
166
|
rlm@1
|
167 for (j = 0; j < groupSize; j++)
|
rlm@1
|
168 ind2[j] = temp[j];
|
rlm@1
|
169 return thereAreGroups;
|
rlm@1
|
170 }
|
rlm@1
|
171
|
rlm@1
|
172 /* Check that all strings are in one group (cannot sort) */
|
rlm@1
|
173 {
|
rlm@1
|
174 UInt32 group, j;
|
rlm@1
|
175 UInt32 sp = ind2[0] + NumSortedBytes; if (sp >= BlockSize) sp -= BlockSize;
|
rlm@1
|
176 group = Groups[sp];
|
rlm@1
|
177 for (j = 1; j < groupSize; j++)
|
rlm@1
|
178 {
|
rlm@1
|
179 sp = ind2[j] + NumSortedBytes; if (sp >= BlockSize) sp -= BlockSize;
|
rlm@1
|
180 if (Groups[sp] != group)
|
rlm@1
|
181 break;
|
rlm@1
|
182 }
|
rlm@1
|
183 if (j == groupSize)
|
rlm@1
|
184 {
|
rlm@1
|
185 #ifndef BLOCK_SORT_EXTERNAL_FLAGS
|
rlm@1
|
186 SetGroupSize(ind2, groupSize);
|
rlm@1
|
187 #endif
|
rlm@1
|
188 return 1;
|
rlm@1
|
189 }
|
rlm@1
|
190 }
|
rlm@1
|
191
|
rlm@1
|
192 #ifndef BLOCK_SORT_USE_HEAP_SORT
|
rlm@1
|
193 {
|
rlm@1
|
194 /* ---------- Range Sort ---------- */
|
rlm@1
|
195 UInt32 i;
|
rlm@1
|
196 UInt32 mid;
|
rlm@1
|
197 for (;;)
|
rlm@1
|
198 {
|
rlm@1
|
199 UInt32 j;
|
rlm@1
|
200 if (range <= 1)
|
rlm@1
|
201 {
|
rlm@1
|
202 #ifndef BLOCK_SORT_EXTERNAL_FLAGS
|
rlm@1
|
203 SetGroupSize(ind2, groupSize);
|
rlm@1
|
204 #endif
|
rlm@1
|
205 return 1;
|
rlm@1
|
206 }
|
rlm@1
|
207 mid = left + ((range + 1) >> 1);
|
rlm@1
|
208 j = groupSize;
|
rlm@1
|
209 i = 0;
|
rlm@1
|
210 do
|
rlm@1
|
211 {
|
rlm@1
|
212 UInt32 sp = ind2[i] + NumSortedBytes; if (sp >= BlockSize) sp -= BlockSize;
|
rlm@1
|
213 if (Groups[sp] >= mid)
|
rlm@1
|
214 {
|
rlm@1
|
215 for (j--; j > i; j--)
|
rlm@1
|
216 {
|
rlm@1
|
217 sp = ind2[j] + NumSortedBytes; if (sp >= BlockSize) sp -= BlockSize;
|
rlm@1
|
218 if (Groups[sp] < mid)
|
rlm@1
|
219 {
|
rlm@1
|
220 UInt32 temp = ind2[i]; ind2[i] = ind2[j]; ind2[j] = temp;
|
rlm@1
|
221 break;
|
rlm@1
|
222 }
|
rlm@1
|
223 }
|
rlm@1
|
224 if (i >= j)
|
rlm@1
|
225 break;
|
rlm@1
|
226 }
|
rlm@1
|
227 }
|
rlm@1
|
228 while (++i < j);
|
rlm@1
|
229 if (i == 0)
|
rlm@1
|
230 {
|
rlm@1
|
231 range = range - (mid - left);
|
rlm@1
|
232 left = mid;
|
rlm@1
|
233 }
|
rlm@1
|
234 else if (i == groupSize)
|
rlm@1
|
235 range = (mid - left);
|
rlm@1
|
236 else
|
rlm@1
|
237 break;
|
rlm@1
|
238 }
|
rlm@1
|
239
|
rlm@1
|
240 #ifdef BLOCK_SORT_EXTERNAL_FLAGS
|
rlm@1
|
241 {
|
rlm@1
|
242 UInt32 t = (groupOffset + i - 1);
|
rlm@1
|
243 UInt32 *Flags = Groups + BlockSize;
|
rlm@1
|
244 Flags[t >> kNumFlagsBits] &= ~(1 << (t & kFlagsMask));
|
rlm@1
|
245 }
|
rlm@1
|
246 #endif
|
rlm@1
|
247
|
rlm@1
|
248 {
|
rlm@1
|
249 UInt32 j;
|
rlm@1
|
250 for (j = i; j < groupSize; j++)
|
rlm@1
|
251 Groups[ind2[j]] = groupOffset + i;
|
rlm@1
|
252 }
|
rlm@1
|
253
|
rlm@1
|
254 {
|
rlm@1
|
255 UInt32 res = SortGroup(BlockSize, NumSortedBytes, groupOffset, i, NumRefBits, Indices, left, mid - left);
|
rlm@1
|
256 return res | SortGroup(BlockSize, NumSortedBytes, groupOffset + i, groupSize - i, NumRefBits, Indices, mid, range - (mid - left));
|
rlm@1
|
257 }
|
rlm@1
|
258
|
rlm@1
|
259 }
|
rlm@1
|
260
|
rlm@1
|
261 #else
|
rlm@1
|
262
|
rlm@1
|
263 /* ---------- Heap Sort ---------- */
|
rlm@1
|
264
|
rlm@1
|
265 {
|
rlm@1
|
266 UInt32 j;
|
rlm@1
|
267 for (j = 0; j < groupSize; j++)
|
rlm@1
|
268 {
|
rlm@1
|
269 UInt32 sp = ind2[j] + NumSortedBytes; if (sp >= BlockSize) sp -= BlockSize;
|
rlm@1
|
270 ind2[j] = sp;
|
rlm@1
|
271 }
|
rlm@1
|
272
|
rlm@1
|
273 HeapSortRef(ind2, Groups, groupSize);
|
rlm@1
|
274
|
rlm@1
|
275 /* Write Flags */
|
rlm@1
|
276 {
|
rlm@1
|
277 UInt32 sp = ind2[0];
|
rlm@1
|
278 UInt32 group = Groups[sp];
|
rlm@1
|
279
|
rlm@1
|
280 #ifdef BLOCK_SORT_EXTERNAL_FLAGS
|
rlm@1
|
281 UInt32 *Flags = Groups + BlockSize;
|
rlm@1
|
282 #else
|
rlm@1
|
283 UInt32 prevGroupStart = 0;
|
rlm@1
|
284 #endif
|
rlm@1
|
285
|
rlm@1
|
286 for (j = 1; j < groupSize; j++)
|
rlm@1
|
287 {
|
rlm@1
|
288 sp = ind2[j];
|
rlm@1
|
289 if (Groups[sp] != group)
|
rlm@1
|
290 {
|
rlm@1
|
291 group = Groups[sp];
|
rlm@1
|
292 #ifdef BLOCK_SORT_EXTERNAL_FLAGS
|
rlm@1
|
293 {
|
rlm@1
|
294 UInt32 t = groupOffset + j - 1;
|
rlm@1
|
295 Flags[t >> kNumFlagsBits] &= ~(1 << (t & kFlagsMask));
|
rlm@1
|
296 }
|
rlm@1
|
297 #else
|
rlm@1
|
298 SetGroupSize(ind2 + prevGroupStart, j - prevGroupStart);
|
rlm@1
|
299 prevGroupStart = j;
|
rlm@1
|
300 #endif
|
rlm@1
|
301 }
|
rlm@1
|
302 }
|
rlm@1
|
303
|
rlm@1
|
304 #ifndef BLOCK_SORT_EXTERNAL_FLAGS
|
rlm@1
|
305 SetGroupSize(ind2 + prevGroupStart, j - prevGroupStart);
|
rlm@1
|
306 #endif
|
rlm@1
|
307 }
|
rlm@1
|
308 {
|
rlm@1
|
309 /* Write new Groups values and Check that there are groups */
|
rlm@1
|
310 UInt32 thereAreGroups = 0;
|
rlm@1
|
311 for (j = 0; j < groupSize; j++)
|
rlm@1
|
312 {
|
rlm@1
|
313 UInt32 group = groupOffset + j;
|
rlm@1
|
314 #ifndef BLOCK_SORT_EXTERNAL_FLAGS
|
rlm@1
|
315 UInt32 subGroupSize = ((ind2[j] & ~0xC0000000) >> kNumBitsMax);
|
rlm@1
|
316 if ((ind2[j] & 0x40000000) != 0)
|
rlm@1
|
317 subGroupSize += ((ind2[j + 1] >> kNumBitsMax) << kNumExtra0Bits);
|
rlm@1
|
318 subGroupSize++;
|
rlm@1
|
319 for (;;)
|
rlm@1
|
320 {
|
rlm@1
|
321 UInt32 original = ind2[j];
|
rlm@1
|
322 UInt32 sp = original & kIndexMask;
|
rlm@1
|
323 if (sp < NumSortedBytes) sp += BlockSize; sp -= NumSortedBytes;
|
rlm@1
|
324 ind2[j] = sp | (original & ~kIndexMask);
|
rlm@1
|
325 Groups[sp] = group;
|
rlm@1
|
326 if (--subGroupSize == 0)
|
rlm@1
|
327 break;
|
rlm@1
|
328 j++;
|
rlm@1
|
329 thereAreGroups = 1;
|
rlm@1
|
330 }
|
rlm@1
|
331 #else
|
rlm@1
|
332 UInt32 *Flags = Groups + BlockSize;
|
rlm@1
|
333 for (;;)
|
rlm@1
|
334 {
|
rlm@1
|
335 UInt32 sp = ind2[j]; if (sp < NumSortedBytes) sp += BlockSize; sp -= NumSortedBytes;
|
rlm@1
|
336 ind2[j] = sp;
|
rlm@1
|
337 Groups[sp] = group;
|
rlm@1
|
338 if ((Flags[(groupOffset + j) >> kNumFlagsBits] & (1 << ((groupOffset + j) & kFlagsMask))) == 0)
|
rlm@1
|
339 break;
|
rlm@1
|
340 j++;
|
rlm@1
|
341 thereAreGroups = 1;
|
rlm@1
|
342 }
|
rlm@1
|
343 #endif
|
rlm@1
|
344 }
|
rlm@1
|
345 return thereAreGroups;
|
rlm@1
|
346 }
|
rlm@1
|
347 }
|
rlm@1
|
348 #endif
|
rlm@1
|
349 }
|
rlm@1
|
350
|
rlm@1
|
351 /* conditions: blockSize > 0 */
|
rlm@1
|
352 UInt32 BlockSort(UInt32 *Indices, const Byte *data, UInt32 blockSize)
|
rlm@1
|
353 {
|
rlm@1
|
354 UInt32 *counters = Indices + blockSize;
|
rlm@1
|
355 UInt32 i;
|
rlm@1
|
356 UInt32 *Groups;
|
rlm@1
|
357 #ifdef BLOCK_SORT_EXTERNAL_FLAGS
|
rlm@1
|
358 UInt32 *Flags;
|
rlm@1
|
359 #endif
|
rlm@1
|
360
|
rlm@1
|
361 /* Radix-Sort for 2 bytes */
|
rlm@1
|
362 for (i = 0; i < kNumHashValues; i++)
|
rlm@1
|
363 counters[i] = 0;
|
rlm@1
|
364 for (i = 0; i < blockSize - 1; i++)
|
rlm@1
|
365 counters[((UInt32)data[i] << 8) | data[i + 1]]++;
|
rlm@1
|
366 counters[((UInt32)data[i] << 8) | data[0]]++;
|
rlm@1
|
367
|
rlm@1
|
368 Groups = counters + BS_TEMP_SIZE;
|
rlm@1
|
369 #ifdef BLOCK_SORT_EXTERNAL_FLAGS
|
rlm@1
|
370 Flags = Groups + blockSize;
|
rlm@1
|
371 {
|
rlm@1
|
372 UInt32 numWords = (blockSize + kFlagsMask) >> kNumFlagsBits;
|
rlm@1
|
373 for (i = 0; i < numWords; i++)
|
rlm@1
|
374 Flags[i] = kAllFlags;
|
rlm@1
|
375 }
|
rlm@1
|
376 #endif
|
rlm@1
|
377
|
rlm@1
|
378 {
|
rlm@1
|
379 UInt32 sum = 0;
|
rlm@1
|
380 for (i = 0; i < kNumHashValues; i++)
|
rlm@1
|
381 {
|
rlm@1
|
382 UInt32 groupSize = counters[i];
|
rlm@1
|
383 if (groupSize > 0)
|
rlm@1
|
384 {
|
rlm@1
|
385 #ifdef BLOCK_SORT_EXTERNAL_FLAGS
|
rlm@1
|
386 UInt32 t = sum + groupSize - 1;
|
rlm@1
|
387 Flags[t >> kNumFlagsBits] &= ~(1 << (t & kFlagsMask));
|
rlm@1
|
388 #endif
|
rlm@1
|
389 sum += groupSize;
|
rlm@1
|
390 }
|
rlm@1
|
391 counters[i] = sum - groupSize;
|
rlm@1
|
392 }
|
rlm@1
|
393
|
rlm@1
|
394 for (i = 0; i < blockSize - 1; i++)
|
rlm@1
|
395 Groups[i] = counters[((UInt32)data[i] << 8) | data[i + 1]];
|
rlm@1
|
396 Groups[i] = counters[((UInt32)data[i] << 8) | data[0]];
|
rlm@1
|
397
|
rlm@1
|
398 for (i = 0; i < blockSize - 1; i++)
|
rlm@1
|
399 Indices[counters[((UInt32)data[i] << 8) | data[i + 1]]++] = i;
|
rlm@1
|
400 Indices[counters[((UInt32)data[i] << 8) | data[0]]++] = i;
|
rlm@1
|
401
|
rlm@1
|
402 #ifndef BLOCK_SORT_EXTERNAL_FLAGS
|
rlm@1
|
403 {
|
rlm@1
|
404 UInt32 prev = 0;
|
rlm@1
|
405 for (i = 0; i < kNumHashValues; i++)
|
rlm@1
|
406 {
|
rlm@1
|
407 UInt32 prevGroupSize = counters[i] - prev;
|
rlm@1
|
408 if (prevGroupSize == 0)
|
rlm@1
|
409 continue;
|
rlm@1
|
410 SetGroupSize(Indices + prev, prevGroupSize);
|
rlm@1
|
411 prev = counters[i];
|
rlm@1
|
412 }
|
rlm@1
|
413 }
|
rlm@1
|
414 #endif
|
rlm@1
|
415 }
|
rlm@1
|
416
|
rlm@1
|
417 {
|
rlm@1
|
418 int NumRefBits;
|
rlm@1
|
419 UInt32 NumSortedBytes;
|
rlm@1
|
420 for (NumRefBits = 0; ((blockSize - 1) >> NumRefBits) != 0; NumRefBits++);
|
rlm@1
|
421 NumRefBits = 32 - NumRefBits;
|
rlm@1
|
422 if (NumRefBits > kNumRefBitsMax)
|
rlm@1
|
423 NumRefBits = kNumRefBitsMax;
|
rlm@1
|
424
|
rlm@1
|
425 for (NumSortedBytes = kNumHashBytes; ; NumSortedBytes <<= 1)
|
rlm@1
|
426 {
|
rlm@1
|
427 #ifndef BLOCK_SORT_EXTERNAL_FLAGS
|
rlm@1
|
428 UInt32 finishedGroupSize = 0;
|
rlm@1
|
429 #endif
|
rlm@1
|
430 UInt32 newLimit = 0;
|
rlm@1
|
431 for (i = 0; i < blockSize;)
|
rlm@1
|
432 {
|
rlm@1
|
433 UInt32 groupSize;
|
rlm@1
|
434 #ifdef BLOCK_SORT_EXTERNAL_FLAGS
|
rlm@1
|
435
|
rlm@1
|
436 if ((Flags[i >> kNumFlagsBits] & (1 << (i & kFlagsMask))) == 0)
|
rlm@1
|
437 {
|
rlm@1
|
438 i++;
|
rlm@1
|
439 continue;
|
rlm@1
|
440 }
|
rlm@1
|
441 for (groupSize = 1;
|
rlm@1
|
442 (Flags[(i + groupSize) >> kNumFlagsBits] & (1 << ((i + groupSize) & kFlagsMask))) != 0;
|
rlm@1
|
443 groupSize++);
|
rlm@1
|
444
|
rlm@1
|
445 groupSize++;
|
rlm@1
|
446
|
rlm@1
|
447 #else
|
rlm@1
|
448
|
rlm@1
|
449 groupSize = ((Indices[i] & ~0xC0000000) >> kNumBitsMax);
|
rlm@1
|
450 {
|
rlm@1
|
451 Bool finishedGroup = ((Indices[i] & 0x80000000) == 0);
|
rlm@1
|
452 if ((Indices[i] & 0x40000000) != 0)
|
rlm@1
|
453 {
|
rlm@1
|
454 groupSize += ((Indices[i + 1] >> kNumBitsMax) << kNumExtra0Bits);
|
rlm@1
|
455 Indices[i + 1] &= kIndexMask;
|
rlm@1
|
456 }
|
rlm@1
|
457 Indices[i] &= kIndexMask;
|
rlm@1
|
458 groupSize++;
|
rlm@1
|
459 if (finishedGroup || groupSize == 1)
|
rlm@1
|
460 {
|
rlm@1
|
461 Indices[i - finishedGroupSize] &= kIndexMask;
|
rlm@1
|
462 if (finishedGroupSize > 1)
|
rlm@1
|
463 Indices[i - finishedGroupSize + 1] &= kIndexMask;
|
rlm@1
|
464 {
|
rlm@1
|
465 UInt32 newGroupSize = groupSize + finishedGroupSize;
|
rlm@1
|
466 SetFinishedGroupSize(Indices + i - finishedGroupSize, newGroupSize);
|
rlm@1
|
467 finishedGroupSize = newGroupSize;
|
rlm@1
|
468 }
|
rlm@1
|
469 i += groupSize;
|
rlm@1
|
470 continue;
|
rlm@1
|
471 }
|
rlm@1
|
472 finishedGroupSize = 0;
|
rlm@1
|
473 }
|
rlm@1
|
474
|
rlm@1
|
475 #endif
|
rlm@1
|
476
|
rlm@1
|
477 if (NumSortedBytes >= blockSize)
|
rlm@1
|
478 {
|
rlm@1
|
479 UInt32 j;
|
rlm@1
|
480 for (j = 0; j < groupSize; j++)
|
rlm@1
|
481 {
|
rlm@1
|
482 UInt32 t = (i + j);
|
rlm@1
|
483 /* Flags[t >> kNumFlagsBits] &= ~(1 << (t & kFlagsMask)); */
|
rlm@1
|
484 Groups[Indices[t]] = t;
|
rlm@1
|
485 }
|
rlm@1
|
486 }
|
rlm@1
|
487 else
|
rlm@1
|
488 if (SortGroup(blockSize, NumSortedBytes, i, groupSize, NumRefBits, Indices
|
rlm@1
|
489 #ifndef BLOCK_SORT_USE_HEAP_SORT
|
rlm@1
|
490 , 0, blockSize
|
rlm@1
|
491 #endif
|
rlm@1
|
492 ) != 0)
|
rlm@1
|
493 newLimit = i + groupSize;
|
rlm@1
|
494 i += groupSize;
|
rlm@1
|
495 }
|
rlm@1
|
496 if (newLimit == 0)
|
rlm@1
|
497 break;
|
rlm@1
|
498 }
|
rlm@1
|
499 }
|
rlm@1
|
500 #ifndef BLOCK_SORT_EXTERNAL_FLAGS
|
rlm@1
|
501 for (i = 0; i < blockSize;)
|
rlm@1
|
502 {
|
rlm@1
|
503 UInt32 groupSize = ((Indices[i] & ~0xC0000000) >> kNumBitsMax);
|
rlm@1
|
504 if ((Indices[i] & 0x40000000) != 0)
|
rlm@1
|
505 {
|
rlm@1
|
506 groupSize += ((Indices[i + 1] >> kNumBitsMax) << kNumExtra0Bits);
|
rlm@1
|
507 Indices[i + 1] &= kIndexMask;
|
rlm@1
|
508 }
|
rlm@1
|
509 Indices[i] &= kIndexMask;
|
rlm@1
|
510 groupSize++;
|
rlm@1
|
511 i += groupSize;
|
rlm@1
|
512 }
|
rlm@1
|
513 #endif
|
rlm@1
|
514 return Groups[0];
|
rlm@1
|
515 }
|
rlm@1
|
516
|