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