Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/contrib/zstd/lib/dictBuilder/divsufsort.c
48375 views
1
/*
2
* divsufsort.c for libdivsufsort-lite
3
* Copyright (c) 2003-2008 Yuta Mori All Rights Reserved.
4
*
5
* Permission is hereby granted, free of charge, to any person
6
* obtaining a copy of this software and associated documentation
7
* files (the "Software"), to deal in the Software without
8
* restriction, including without limitation the rights to use,
9
* copy, modify, merge, publish, distribute, sublicense, and/or sell
10
* copies of the Software, and to permit persons to whom the
11
* Software is furnished to do so, subject to the following
12
* conditions:
13
*
14
* The above copyright notice and this permission notice shall be
15
* included in all copies or substantial portions of the Software.
16
*
17
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
19
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
21
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24
* OTHER DEALINGS IN THE SOFTWARE.
25
*/
26
27
/*- Compiler specifics -*/
28
#ifdef __clang__
29
#pragma clang diagnostic ignored "-Wshorten-64-to-32"
30
#endif
31
32
#if defined(_MSC_VER)
33
# pragma warning(disable : 4244)
34
# pragma warning(disable : 4127) /* C4127 : Condition expression is constant */
35
#endif
36
37
38
/*- Dependencies -*/
39
#include <assert.h>
40
#include <stdio.h>
41
#include <stdlib.h>
42
43
#include "divsufsort.h"
44
45
/*- Constants -*/
46
#if defined(INLINE)
47
# undef INLINE
48
#endif
49
#if !defined(INLINE)
50
# define INLINE __inline
51
#endif
52
#if defined(ALPHABET_SIZE) && (ALPHABET_SIZE < 1)
53
# undef ALPHABET_SIZE
54
#endif
55
#if !defined(ALPHABET_SIZE)
56
# define ALPHABET_SIZE (256)
57
#endif
58
#define BUCKET_A_SIZE (ALPHABET_SIZE)
59
#define BUCKET_B_SIZE (ALPHABET_SIZE * ALPHABET_SIZE)
60
#if defined(SS_INSERTIONSORT_THRESHOLD)
61
# if SS_INSERTIONSORT_THRESHOLD < 1
62
# undef SS_INSERTIONSORT_THRESHOLD
63
# define SS_INSERTIONSORT_THRESHOLD (1)
64
# endif
65
#else
66
# define SS_INSERTIONSORT_THRESHOLD (8)
67
#endif
68
#if defined(SS_BLOCKSIZE)
69
# if SS_BLOCKSIZE < 0
70
# undef SS_BLOCKSIZE
71
# define SS_BLOCKSIZE (0)
72
# elif 32768 <= SS_BLOCKSIZE
73
# undef SS_BLOCKSIZE
74
# define SS_BLOCKSIZE (32767)
75
# endif
76
#else
77
# define SS_BLOCKSIZE (1024)
78
#endif
79
/* minstacksize = log(SS_BLOCKSIZE) / log(3) * 2 */
80
#if SS_BLOCKSIZE == 0
81
# define SS_MISORT_STACKSIZE (96)
82
#elif SS_BLOCKSIZE <= 4096
83
# define SS_MISORT_STACKSIZE (16)
84
#else
85
# define SS_MISORT_STACKSIZE (24)
86
#endif
87
#define SS_SMERGE_STACKSIZE (32)
88
#define TR_INSERTIONSORT_THRESHOLD (8)
89
#define TR_STACKSIZE (64)
90
91
92
/*- Macros -*/
93
#ifndef SWAP
94
# define SWAP(_a, _b) do { t = (_a); (_a) = (_b); (_b) = t; } while(0)
95
#endif /* SWAP */
96
#ifndef MIN
97
# define MIN(_a, _b) (((_a) < (_b)) ? (_a) : (_b))
98
#endif /* MIN */
99
#ifndef MAX
100
# define MAX(_a, _b) (((_a) > (_b)) ? (_a) : (_b))
101
#endif /* MAX */
102
#define STACK_PUSH(_a, _b, _c, _d)\
103
do {\
104
assert(ssize < STACK_SIZE);\
105
stack[ssize].a = (_a), stack[ssize].b = (_b),\
106
stack[ssize].c = (_c), stack[ssize++].d = (_d);\
107
} while(0)
108
#define STACK_PUSH5(_a, _b, _c, _d, _e)\
109
do {\
110
assert(ssize < STACK_SIZE);\
111
stack[ssize].a = (_a), stack[ssize].b = (_b),\
112
stack[ssize].c = (_c), stack[ssize].d = (_d), stack[ssize++].e = (_e);\
113
} while(0)
114
#define STACK_POP(_a, _b, _c, _d)\
115
do {\
116
assert(0 <= ssize);\
117
if(ssize == 0) { return; }\
118
(_a) = stack[--ssize].a, (_b) = stack[ssize].b,\
119
(_c) = stack[ssize].c, (_d) = stack[ssize].d;\
120
} while(0)
121
#define STACK_POP5(_a, _b, _c, _d, _e)\
122
do {\
123
assert(0 <= ssize);\
124
if(ssize == 0) { return; }\
125
(_a) = stack[--ssize].a, (_b) = stack[ssize].b,\
126
(_c) = stack[ssize].c, (_d) = stack[ssize].d, (_e) = stack[ssize].e;\
127
} while(0)
128
#define BUCKET_A(_c0) bucket_A[(_c0)]
129
#if ALPHABET_SIZE == 256
130
#define BUCKET_B(_c0, _c1) (bucket_B[((_c1) << 8) | (_c0)])
131
#define BUCKET_BSTAR(_c0, _c1) (bucket_B[((_c0) << 8) | (_c1)])
132
#else
133
#define BUCKET_B(_c0, _c1) (bucket_B[(_c1) * ALPHABET_SIZE + (_c0)])
134
#define BUCKET_BSTAR(_c0, _c1) (bucket_B[(_c0) * ALPHABET_SIZE + (_c1)])
135
#endif
136
137
138
/*- Private Functions -*/
139
140
static const int lg_table[256]= {
141
-1,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
142
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
143
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
144
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
145
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
146
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
147
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
148
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
149
};
150
151
#if (SS_BLOCKSIZE == 0) || (SS_INSERTIONSORT_THRESHOLD < SS_BLOCKSIZE)
152
153
static INLINE
154
int
155
ss_ilg(int n) {
156
#if SS_BLOCKSIZE == 0
157
return (n & 0xffff0000) ?
158
((n & 0xff000000) ?
159
24 + lg_table[(n >> 24) & 0xff] :
160
16 + lg_table[(n >> 16) & 0xff]) :
161
((n & 0x0000ff00) ?
162
8 + lg_table[(n >> 8) & 0xff] :
163
0 + lg_table[(n >> 0) & 0xff]);
164
#elif SS_BLOCKSIZE < 256
165
return lg_table[n];
166
#else
167
return (n & 0xff00) ?
168
8 + lg_table[(n >> 8) & 0xff] :
169
0 + lg_table[(n >> 0) & 0xff];
170
#endif
171
}
172
173
#endif /* (SS_BLOCKSIZE == 0) || (SS_INSERTIONSORT_THRESHOLD < SS_BLOCKSIZE) */
174
175
#if SS_BLOCKSIZE != 0
176
177
static const int sqq_table[256] = {
178
0, 16, 22, 27, 32, 35, 39, 42, 45, 48, 50, 53, 55, 57, 59, 61,
179
64, 65, 67, 69, 71, 73, 75, 76, 78, 80, 81, 83, 84, 86, 87, 89,
180
90, 91, 93, 94, 96, 97, 98, 99, 101, 102, 103, 104, 106, 107, 108, 109,
181
110, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126,
182
128, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142,
183
143, 144, 144, 145, 146, 147, 148, 149, 150, 150, 151, 152, 153, 154, 155, 155,
184
156, 157, 158, 159, 160, 160, 161, 162, 163, 163, 164, 165, 166, 167, 167, 168,
185
169, 170, 170, 171, 172, 173, 173, 174, 175, 176, 176, 177, 178, 178, 179, 180,
186
181, 181, 182, 183, 183, 184, 185, 185, 186, 187, 187, 188, 189, 189, 190, 191,
187
192, 192, 193, 193, 194, 195, 195, 196, 197, 197, 198, 199, 199, 200, 201, 201,
188
202, 203, 203, 204, 204, 205, 206, 206, 207, 208, 208, 209, 209, 210, 211, 211,
189
212, 212, 213, 214, 214, 215, 215, 216, 217, 217, 218, 218, 219, 219, 220, 221,
190
221, 222, 222, 223, 224, 224, 225, 225, 226, 226, 227, 227, 228, 229, 229, 230,
191
230, 231, 231, 232, 232, 233, 234, 234, 235, 235, 236, 236, 237, 237, 238, 238,
192
239, 240, 240, 241, 241, 242, 242, 243, 243, 244, 244, 245, 245, 246, 246, 247,
193
247, 248, 248, 249, 249, 250, 250, 251, 251, 252, 252, 253, 253, 254, 254, 255
194
};
195
196
static INLINE
197
int
198
ss_isqrt(int x) {
199
int y, e;
200
201
if(x >= (SS_BLOCKSIZE * SS_BLOCKSIZE)) { return SS_BLOCKSIZE; }
202
e = (x & 0xffff0000) ?
203
((x & 0xff000000) ?
204
24 + lg_table[(x >> 24) & 0xff] :
205
16 + lg_table[(x >> 16) & 0xff]) :
206
((x & 0x0000ff00) ?
207
8 + lg_table[(x >> 8) & 0xff] :
208
0 + lg_table[(x >> 0) & 0xff]);
209
210
if(e >= 16) {
211
y = sqq_table[x >> ((e - 6) - (e & 1))] << ((e >> 1) - 7);
212
if(e >= 24) { y = (y + 1 + x / y) >> 1; }
213
y = (y + 1 + x / y) >> 1;
214
} else if(e >= 8) {
215
y = (sqq_table[x >> ((e - 6) - (e & 1))] >> (7 - (e >> 1))) + 1;
216
} else {
217
return sqq_table[x] >> 4;
218
}
219
220
return (x < (y * y)) ? y - 1 : y;
221
}
222
223
#endif /* SS_BLOCKSIZE != 0 */
224
225
226
/*---------------------------------------------------------------------------*/
227
228
/* Compares two suffixes. */
229
static INLINE
230
int
231
ss_compare(const unsigned char *T,
232
const int *p1, const int *p2,
233
int depth) {
234
const unsigned char *U1, *U2, *U1n, *U2n;
235
236
for(U1 = T + depth + *p1,
237
U2 = T + depth + *p2,
238
U1n = T + *(p1 + 1) + 2,
239
U2n = T + *(p2 + 1) + 2;
240
(U1 < U1n) && (U2 < U2n) && (*U1 == *U2);
241
++U1, ++U2) {
242
}
243
244
return U1 < U1n ?
245
(U2 < U2n ? *U1 - *U2 : 1) :
246
(U2 < U2n ? -1 : 0);
247
}
248
249
250
/*---------------------------------------------------------------------------*/
251
252
#if (SS_BLOCKSIZE != 1) && (SS_INSERTIONSORT_THRESHOLD != 1)
253
254
/* Insertionsort for small size groups */
255
static
256
void
257
ss_insertionsort(const unsigned char *T, const int *PA,
258
int *first, int *last, int depth) {
259
int *i, *j;
260
int t;
261
int r;
262
263
for(i = last - 2; first <= i; --i) {
264
for(t = *i, j = i + 1; 0 < (r = ss_compare(T, PA + t, PA + *j, depth));) {
265
do { *(j - 1) = *j; } while((++j < last) && (*j < 0));
266
if(last <= j) { break; }
267
}
268
if(r == 0) { *j = ~*j; }
269
*(j - 1) = t;
270
}
271
}
272
273
#endif /* (SS_BLOCKSIZE != 1) && (SS_INSERTIONSORT_THRESHOLD != 1) */
274
275
276
/*---------------------------------------------------------------------------*/
277
278
#if (SS_BLOCKSIZE == 0) || (SS_INSERTIONSORT_THRESHOLD < SS_BLOCKSIZE)
279
280
static INLINE
281
void
282
ss_fixdown(const unsigned char *Td, const int *PA,
283
int *SA, int i, int size) {
284
int j, k;
285
int v;
286
int c, d, e;
287
288
for(v = SA[i], c = Td[PA[v]]; (j = 2 * i + 1) < size; SA[i] = SA[k], i = k) {
289
d = Td[PA[SA[k = j++]]];
290
if(d < (e = Td[PA[SA[j]]])) { k = j; d = e; }
291
if(d <= c) { break; }
292
}
293
SA[i] = v;
294
}
295
296
/* Simple top-down heapsort. */
297
static
298
void
299
ss_heapsort(const unsigned char *Td, const int *PA, int *SA, int size) {
300
int i, m;
301
int t;
302
303
m = size;
304
if((size % 2) == 0) {
305
m--;
306
if(Td[PA[SA[m / 2]]] < Td[PA[SA[m]]]) { SWAP(SA[m], SA[m / 2]); }
307
}
308
309
for(i = m / 2 - 1; 0 <= i; --i) { ss_fixdown(Td, PA, SA, i, m); }
310
if((size % 2) == 0) { SWAP(SA[0], SA[m]); ss_fixdown(Td, PA, SA, 0, m); }
311
for(i = m - 1; 0 < i; --i) {
312
t = SA[0], SA[0] = SA[i];
313
ss_fixdown(Td, PA, SA, 0, i);
314
SA[i] = t;
315
}
316
}
317
318
319
/*---------------------------------------------------------------------------*/
320
321
/* Returns the median of three elements. */
322
static INLINE
323
int *
324
ss_median3(const unsigned char *Td, const int *PA,
325
int *v1, int *v2, int *v3) {
326
int *t;
327
if(Td[PA[*v1]] > Td[PA[*v2]]) { SWAP(v1, v2); }
328
if(Td[PA[*v2]] > Td[PA[*v3]]) {
329
if(Td[PA[*v1]] > Td[PA[*v3]]) { return v1; }
330
else { return v3; }
331
}
332
return v2;
333
}
334
335
/* Returns the median of five elements. */
336
static INLINE
337
int *
338
ss_median5(const unsigned char *Td, const int *PA,
339
int *v1, int *v2, int *v3, int *v4, int *v5) {
340
int *t;
341
if(Td[PA[*v2]] > Td[PA[*v3]]) { SWAP(v2, v3); }
342
if(Td[PA[*v4]] > Td[PA[*v5]]) { SWAP(v4, v5); }
343
if(Td[PA[*v2]] > Td[PA[*v4]]) { SWAP(v2, v4); SWAP(v3, v5); }
344
if(Td[PA[*v1]] > Td[PA[*v3]]) { SWAP(v1, v3); }
345
if(Td[PA[*v1]] > Td[PA[*v4]]) { SWAP(v1, v4); SWAP(v3, v5); }
346
if(Td[PA[*v3]] > Td[PA[*v4]]) { return v4; }
347
return v3;
348
}
349
350
/* Returns the pivot element. */
351
static INLINE
352
int *
353
ss_pivot(const unsigned char *Td, const int *PA, int *first, int *last) {
354
int *middle;
355
int t;
356
357
t = last - first;
358
middle = first + t / 2;
359
360
if(t <= 512) {
361
if(t <= 32) {
362
return ss_median3(Td, PA, first, middle, last - 1);
363
} else {
364
t >>= 2;
365
return ss_median5(Td, PA, first, first + t, middle, last - 1 - t, last - 1);
366
}
367
}
368
t >>= 3;
369
first = ss_median3(Td, PA, first, first + t, first + (t << 1));
370
middle = ss_median3(Td, PA, middle - t, middle, middle + t);
371
last = ss_median3(Td, PA, last - 1 - (t << 1), last - 1 - t, last - 1);
372
return ss_median3(Td, PA, first, middle, last);
373
}
374
375
376
/*---------------------------------------------------------------------------*/
377
378
/* Binary partition for substrings. */
379
static INLINE
380
int *
381
ss_partition(const int *PA,
382
int *first, int *last, int depth) {
383
int *a, *b;
384
int t;
385
for(a = first - 1, b = last;;) {
386
for(; (++a < b) && ((PA[*a] + depth) >= (PA[*a + 1] + 1));) { *a = ~*a; }
387
for(; (a < --b) && ((PA[*b] + depth) < (PA[*b + 1] + 1));) { }
388
if(b <= a) { break; }
389
t = ~*b;
390
*b = *a;
391
*a = t;
392
}
393
if(first < a) { *first = ~*first; }
394
return a;
395
}
396
397
/* Multikey introsort for medium size groups. */
398
static
399
void
400
ss_mintrosort(const unsigned char *T, const int *PA,
401
int *first, int *last,
402
int depth) {
403
#define STACK_SIZE SS_MISORT_STACKSIZE
404
struct { int *a, *b, c; int d; } stack[STACK_SIZE];
405
const unsigned char *Td;
406
int *a, *b, *c, *d, *e, *f;
407
int s, t;
408
int ssize;
409
int limit;
410
int v, x = 0;
411
412
for(ssize = 0, limit = ss_ilg(last - first);;) {
413
414
if((last - first) <= SS_INSERTIONSORT_THRESHOLD) {
415
#if 1 < SS_INSERTIONSORT_THRESHOLD
416
if(1 < (last - first)) { ss_insertionsort(T, PA, first, last, depth); }
417
#endif
418
STACK_POP(first, last, depth, limit);
419
continue;
420
}
421
422
Td = T + depth;
423
if(limit-- == 0) { ss_heapsort(Td, PA, first, last - first); }
424
if(limit < 0) {
425
for(a = first + 1, v = Td[PA[*first]]; a < last; ++a) {
426
if((x = Td[PA[*a]]) != v) {
427
if(1 < (a - first)) { break; }
428
v = x;
429
first = a;
430
}
431
}
432
if(Td[PA[*first] - 1] < v) {
433
first = ss_partition(PA, first, a, depth);
434
}
435
if((a - first) <= (last - a)) {
436
if(1 < (a - first)) {
437
STACK_PUSH(a, last, depth, -1);
438
last = a, depth += 1, limit = ss_ilg(a - first);
439
} else {
440
first = a, limit = -1;
441
}
442
} else {
443
if(1 < (last - a)) {
444
STACK_PUSH(first, a, depth + 1, ss_ilg(a - first));
445
first = a, limit = -1;
446
} else {
447
last = a, depth += 1, limit = ss_ilg(a - first);
448
}
449
}
450
continue;
451
}
452
453
/* choose pivot */
454
a = ss_pivot(Td, PA, first, last);
455
v = Td[PA[*a]];
456
SWAP(*first, *a);
457
458
/* partition */
459
for(b = first; (++b < last) && ((x = Td[PA[*b]]) == v);) { }
460
if(((a = b) < last) && (x < v)) {
461
for(; (++b < last) && ((x = Td[PA[*b]]) <= v);) {
462
if(x == v) { SWAP(*b, *a); ++a; }
463
}
464
}
465
for(c = last; (b < --c) && ((x = Td[PA[*c]]) == v);) { }
466
if((b < (d = c)) && (x > v)) {
467
for(; (b < --c) && ((x = Td[PA[*c]]) >= v);) {
468
if(x == v) { SWAP(*c, *d); --d; }
469
}
470
}
471
for(; b < c;) {
472
SWAP(*b, *c);
473
for(; (++b < c) && ((x = Td[PA[*b]]) <= v);) {
474
if(x == v) { SWAP(*b, *a); ++a; }
475
}
476
for(; (b < --c) && ((x = Td[PA[*c]]) >= v);) {
477
if(x == v) { SWAP(*c, *d); --d; }
478
}
479
}
480
481
if(a <= d) {
482
c = b - 1;
483
484
if((s = a - first) > (t = b - a)) { s = t; }
485
for(e = first, f = b - s; 0 < s; --s, ++e, ++f) { SWAP(*e, *f); }
486
if((s = d - c) > (t = last - d - 1)) { s = t; }
487
for(e = b, f = last - s; 0 < s; --s, ++e, ++f) { SWAP(*e, *f); }
488
489
a = first + (b - a), c = last - (d - c);
490
b = (v <= Td[PA[*a] - 1]) ? a : ss_partition(PA, a, c, depth);
491
492
if((a - first) <= (last - c)) {
493
if((last - c) <= (c - b)) {
494
STACK_PUSH(b, c, depth + 1, ss_ilg(c - b));
495
STACK_PUSH(c, last, depth, limit);
496
last = a;
497
} else if((a - first) <= (c - b)) {
498
STACK_PUSH(c, last, depth, limit);
499
STACK_PUSH(b, c, depth + 1, ss_ilg(c - b));
500
last = a;
501
} else {
502
STACK_PUSH(c, last, depth, limit);
503
STACK_PUSH(first, a, depth, limit);
504
first = b, last = c, depth += 1, limit = ss_ilg(c - b);
505
}
506
} else {
507
if((a - first) <= (c - b)) {
508
STACK_PUSH(b, c, depth + 1, ss_ilg(c - b));
509
STACK_PUSH(first, a, depth, limit);
510
first = c;
511
} else if((last - c) <= (c - b)) {
512
STACK_PUSH(first, a, depth, limit);
513
STACK_PUSH(b, c, depth + 1, ss_ilg(c - b));
514
first = c;
515
} else {
516
STACK_PUSH(first, a, depth, limit);
517
STACK_PUSH(c, last, depth, limit);
518
first = b, last = c, depth += 1, limit = ss_ilg(c - b);
519
}
520
}
521
} else {
522
limit += 1;
523
if(Td[PA[*first] - 1] < v) {
524
first = ss_partition(PA, first, last, depth);
525
limit = ss_ilg(last - first);
526
}
527
depth += 1;
528
}
529
}
530
#undef STACK_SIZE
531
}
532
533
#endif /* (SS_BLOCKSIZE == 0) || (SS_INSERTIONSORT_THRESHOLD < SS_BLOCKSIZE) */
534
535
536
/*---------------------------------------------------------------------------*/
537
538
#if SS_BLOCKSIZE != 0
539
540
static INLINE
541
void
542
ss_blockswap(int *a, int *b, int n) {
543
int t;
544
for(; 0 < n; --n, ++a, ++b) {
545
t = *a, *a = *b, *b = t;
546
}
547
}
548
549
static INLINE
550
void
551
ss_rotate(int *first, int *middle, int *last) {
552
int *a, *b, t;
553
int l, r;
554
l = middle - first, r = last - middle;
555
for(; (0 < l) && (0 < r);) {
556
if(l == r) { ss_blockswap(first, middle, l); break; }
557
if(l < r) {
558
a = last - 1, b = middle - 1;
559
t = *a;
560
do {
561
*a-- = *b, *b-- = *a;
562
if(b < first) {
563
*a = t;
564
last = a;
565
if((r -= l + 1) <= l) { break; }
566
a -= 1, b = middle - 1;
567
t = *a;
568
}
569
} while(1);
570
} else {
571
a = first, b = middle;
572
t = *a;
573
do {
574
*a++ = *b, *b++ = *a;
575
if(last <= b) {
576
*a = t;
577
first = a + 1;
578
if((l -= r + 1) <= r) { break; }
579
a += 1, b = middle;
580
t = *a;
581
}
582
} while(1);
583
}
584
}
585
}
586
587
588
/*---------------------------------------------------------------------------*/
589
590
static
591
void
592
ss_inplacemerge(const unsigned char *T, const int *PA,
593
int *first, int *middle, int *last,
594
int depth) {
595
const int *p;
596
int *a, *b;
597
int len, half;
598
int q, r;
599
int x;
600
601
for(;;) {
602
if(*(last - 1) < 0) { x = 1; p = PA + ~*(last - 1); }
603
else { x = 0; p = PA + *(last - 1); }
604
for(a = first, len = middle - first, half = len >> 1, r = -1;
605
0 < len;
606
len = half, half >>= 1) {
607
b = a + half;
608
q = ss_compare(T, PA + ((0 <= *b) ? *b : ~*b), p, depth);
609
if(q < 0) {
610
a = b + 1;
611
half -= (len & 1) ^ 1;
612
} else {
613
r = q;
614
}
615
}
616
if(a < middle) {
617
if(r == 0) { *a = ~*a; }
618
ss_rotate(a, middle, last);
619
last -= middle - a;
620
middle = a;
621
if(first == middle) { break; }
622
}
623
--last;
624
if(x != 0) { while(*--last < 0) { } }
625
if(middle == last) { break; }
626
}
627
}
628
629
630
/*---------------------------------------------------------------------------*/
631
632
/* Merge-forward with internal buffer. */
633
static
634
void
635
ss_mergeforward(const unsigned char *T, const int *PA,
636
int *first, int *middle, int *last,
637
int *buf, int depth) {
638
int *a, *b, *c, *bufend;
639
int t;
640
int r;
641
642
bufend = buf + (middle - first) - 1;
643
ss_blockswap(buf, first, middle - first);
644
645
for(t = *(a = first), b = buf, c = middle;;) {
646
r = ss_compare(T, PA + *b, PA + *c, depth);
647
if(r < 0) {
648
do {
649
*a++ = *b;
650
if(bufend <= b) { *bufend = t; return; }
651
*b++ = *a;
652
} while(*b < 0);
653
} else if(r > 0) {
654
do {
655
*a++ = *c, *c++ = *a;
656
if(last <= c) {
657
while(b < bufend) { *a++ = *b, *b++ = *a; }
658
*a = *b, *b = t;
659
return;
660
}
661
} while(*c < 0);
662
} else {
663
*c = ~*c;
664
do {
665
*a++ = *b;
666
if(bufend <= b) { *bufend = t; return; }
667
*b++ = *a;
668
} while(*b < 0);
669
670
do {
671
*a++ = *c, *c++ = *a;
672
if(last <= c) {
673
while(b < bufend) { *a++ = *b, *b++ = *a; }
674
*a = *b, *b = t;
675
return;
676
}
677
} while(*c < 0);
678
}
679
}
680
}
681
682
/* Merge-backward with internal buffer. */
683
static
684
void
685
ss_mergebackward(const unsigned char *T, const int *PA,
686
int *first, int *middle, int *last,
687
int *buf, int depth) {
688
const int *p1, *p2;
689
int *a, *b, *c, *bufend;
690
int t;
691
int r;
692
int x;
693
694
bufend = buf + (last - middle) - 1;
695
ss_blockswap(buf, middle, last - middle);
696
697
x = 0;
698
if(*bufend < 0) { p1 = PA + ~*bufend; x |= 1; }
699
else { p1 = PA + *bufend; }
700
if(*(middle - 1) < 0) { p2 = PA + ~*(middle - 1); x |= 2; }
701
else { p2 = PA + *(middle - 1); }
702
for(t = *(a = last - 1), b = bufend, c = middle - 1;;) {
703
r = ss_compare(T, p1, p2, depth);
704
if(0 < r) {
705
if(x & 1) { do { *a-- = *b, *b-- = *a; } while(*b < 0); x ^= 1; }
706
*a-- = *b;
707
if(b <= buf) { *buf = t; break; }
708
*b-- = *a;
709
if(*b < 0) { p1 = PA + ~*b; x |= 1; }
710
else { p1 = PA + *b; }
711
} else if(r < 0) {
712
if(x & 2) { do { *a-- = *c, *c-- = *a; } while(*c < 0); x ^= 2; }
713
*a-- = *c, *c-- = *a;
714
if(c < first) {
715
while(buf < b) { *a-- = *b, *b-- = *a; }
716
*a = *b, *b = t;
717
break;
718
}
719
if(*c < 0) { p2 = PA + ~*c; x |= 2; }
720
else { p2 = PA + *c; }
721
} else {
722
if(x & 1) { do { *a-- = *b, *b-- = *a; } while(*b < 0); x ^= 1; }
723
*a-- = ~*b;
724
if(b <= buf) { *buf = t; break; }
725
*b-- = *a;
726
if(x & 2) { do { *a-- = *c, *c-- = *a; } while(*c < 0); x ^= 2; }
727
*a-- = *c, *c-- = *a;
728
if(c < first) {
729
while(buf < b) { *a-- = *b, *b-- = *a; }
730
*a = *b, *b = t;
731
break;
732
}
733
if(*b < 0) { p1 = PA + ~*b; x |= 1; }
734
else { p1 = PA + *b; }
735
if(*c < 0) { p2 = PA + ~*c; x |= 2; }
736
else { p2 = PA + *c; }
737
}
738
}
739
}
740
741
/* D&C based merge. */
742
static
743
void
744
ss_swapmerge(const unsigned char *T, const int *PA,
745
int *first, int *middle, int *last,
746
int *buf, int bufsize, int depth) {
747
#define STACK_SIZE SS_SMERGE_STACKSIZE
748
#define GETIDX(a) ((0 <= (a)) ? (a) : (~(a)))
749
#define MERGE_CHECK(a, b, c)\
750
do {\
751
if(((c) & 1) ||\
752
(((c) & 2) && (ss_compare(T, PA + GETIDX(*((a) - 1)), PA + *(a), depth) == 0))) {\
753
*(a) = ~*(a);\
754
}\
755
if(((c) & 4) && ((ss_compare(T, PA + GETIDX(*((b) - 1)), PA + *(b), depth) == 0))) {\
756
*(b) = ~*(b);\
757
}\
758
} while(0)
759
struct { int *a, *b, *c; int d; } stack[STACK_SIZE];
760
int *l, *r, *lm, *rm;
761
int m, len, half;
762
int ssize;
763
int check, next;
764
765
for(check = 0, ssize = 0;;) {
766
if((last - middle) <= bufsize) {
767
if((first < middle) && (middle < last)) {
768
ss_mergebackward(T, PA, first, middle, last, buf, depth);
769
}
770
MERGE_CHECK(first, last, check);
771
STACK_POP(first, middle, last, check);
772
continue;
773
}
774
775
if((middle - first) <= bufsize) {
776
if(first < middle) {
777
ss_mergeforward(T, PA, first, middle, last, buf, depth);
778
}
779
MERGE_CHECK(first, last, check);
780
STACK_POP(first, middle, last, check);
781
continue;
782
}
783
784
for(m = 0, len = MIN(middle - first, last - middle), half = len >> 1;
785
0 < len;
786
len = half, half >>= 1) {
787
if(ss_compare(T, PA + GETIDX(*(middle + m + half)),
788
PA + GETIDX(*(middle - m - half - 1)), depth) < 0) {
789
m += half + 1;
790
half -= (len & 1) ^ 1;
791
}
792
}
793
794
if(0 < m) {
795
lm = middle - m, rm = middle + m;
796
ss_blockswap(lm, middle, m);
797
l = r = middle, next = 0;
798
if(rm < last) {
799
if(*rm < 0) {
800
*rm = ~*rm;
801
if(first < lm) { for(; *--l < 0;) { } next |= 4; }
802
next |= 1;
803
} else if(first < lm) {
804
for(; *r < 0; ++r) { }
805
next |= 2;
806
}
807
}
808
809
if((l - first) <= (last - r)) {
810
STACK_PUSH(r, rm, last, (next & 3) | (check & 4));
811
middle = lm, last = l, check = (check & 3) | (next & 4);
812
} else {
813
if((next & 2) && (r == middle)) { next ^= 6; }
814
STACK_PUSH(first, lm, l, (check & 3) | (next & 4));
815
first = r, middle = rm, check = (next & 3) | (check & 4);
816
}
817
} else {
818
if(ss_compare(T, PA + GETIDX(*(middle - 1)), PA + *middle, depth) == 0) {
819
*middle = ~*middle;
820
}
821
MERGE_CHECK(first, last, check);
822
STACK_POP(first, middle, last, check);
823
}
824
}
825
#undef STACK_SIZE
826
}
827
828
#endif /* SS_BLOCKSIZE != 0 */
829
830
831
/*---------------------------------------------------------------------------*/
832
833
/* Substring sort */
834
static
835
void
836
sssort(const unsigned char *T, const int *PA,
837
int *first, int *last,
838
int *buf, int bufsize,
839
int depth, int n, int lastsuffix) {
840
int *a;
841
#if SS_BLOCKSIZE != 0
842
int *b, *middle, *curbuf;
843
int j, k, curbufsize, limit;
844
#endif
845
int i;
846
847
if(lastsuffix != 0) { ++first; }
848
849
#if SS_BLOCKSIZE == 0
850
ss_mintrosort(T, PA, first, last, depth);
851
#else
852
if((bufsize < SS_BLOCKSIZE) &&
853
(bufsize < (last - first)) &&
854
(bufsize < (limit = ss_isqrt(last - first)))) {
855
if(SS_BLOCKSIZE < limit) { limit = SS_BLOCKSIZE; }
856
buf = middle = last - limit, bufsize = limit;
857
} else {
858
middle = last, limit = 0;
859
}
860
for(a = first, i = 0; SS_BLOCKSIZE < (middle - a); a += SS_BLOCKSIZE, ++i) {
861
#if SS_INSERTIONSORT_THRESHOLD < SS_BLOCKSIZE
862
ss_mintrosort(T, PA, a, a + SS_BLOCKSIZE, depth);
863
#elif 1 < SS_BLOCKSIZE
864
ss_insertionsort(T, PA, a, a + SS_BLOCKSIZE, depth);
865
#endif
866
curbufsize = last - (a + SS_BLOCKSIZE);
867
curbuf = a + SS_BLOCKSIZE;
868
if(curbufsize <= bufsize) { curbufsize = bufsize, curbuf = buf; }
869
for(b = a, k = SS_BLOCKSIZE, j = i; j & 1; b -= k, k <<= 1, j >>= 1) {
870
ss_swapmerge(T, PA, b - k, b, b + k, curbuf, curbufsize, depth);
871
}
872
}
873
#if SS_INSERTIONSORT_THRESHOLD < SS_BLOCKSIZE
874
ss_mintrosort(T, PA, a, middle, depth);
875
#elif 1 < SS_BLOCKSIZE
876
ss_insertionsort(T, PA, a, middle, depth);
877
#endif
878
for(k = SS_BLOCKSIZE; i != 0; k <<= 1, i >>= 1) {
879
if(i & 1) {
880
ss_swapmerge(T, PA, a - k, a, middle, buf, bufsize, depth);
881
a -= k;
882
}
883
}
884
if(limit != 0) {
885
#if SS_INSERTIONSORT_THRESHOLD < SS_BLOCKSIZE
886
ss_mintrosort(T, PA, middle, last, depth);
887
#elif 1 < SS_BLOCKSIZE
888
ss_insertionsort(T, PA, middle, last, depth);
889
#endif
890
ss_inplacemerge(T, PA, first, middle, last, depth);
891
}
892
#endif
893
894
if(lastsuffix != 0) {
895
/* Insert last type B* suffix. */
896
int PAi[2]; PAi[0] = PA[*(first - 1)], PAi[1] = n - 2;
897
for(a = first, i = *(first - 1);
898
(a < last) && ((*a < 0) || (0 < ss_compare(T, &(PAi[0]), PA + *a, depth)));
899
++a) {
900
*(a - 1) = *a;
901
}
902
*(a - 1) = i;
903
}
904
}
905
906
907
/*---------------------------------------------------------------------------*/
908
909
static INLINE
910
int
911
tr_ilg(int n) {
912
return (n & 0xffff0000) ?
913
((n & 0xff000000) ?
914
24 + lg_table[(n >> 24) & 0xff] :
915
16 + lg_table[(n >> 16) & 0xff]) :
916
((n & 0x0000ff00) ?
917
8 + lg_table[(n >> 8) & 0xff] :
918
0 + lg_table[(n >> 0) & 0xff]);
919
}
920
921
922
/*---------------------------------------------------------------------------*/
923
924
/* Simple insertionsort for small size groups. */
925
static
926
void
927
tr_insertionsort(const int *ISAd, int *first, int *last) {
928
int *a, *b;
929
int t, r;
930
931
for(a = first + 1; a < last; ++a) {
932
for(t = *a, b = a - 1; 0 > (r = ISAd[t] - ISAd[*b]);) {
933
do { *(b + 1) = *b; } while((first <= --b) && (*b < 0));
934
if(b < first) { break; }
935
}
936
if(r == 0) { *b = ~*b; }
937
*(b + 1) = t;
938
}
939
}
940
941
942
/*---------------------------------------------------------------------------*/
943
944
static INLINE
945
void
946
tr_fixdown(const int *ISAd, int *SA, int i, int size) {
947
int j, k;
948
int v;
949
int c, d, e;
950
951
for(v = SA[i], c = ISAd[v]; (j = 2 * i + 1) < size; SA[i] = SA[k], i = k) {
952
d = ISAd[SA[k = j++]];
953
if(d < (e = ISAd[SA[j]])) { k = j; d = e; }
954
if(d <= c) { break; }
955
}
956
SA[i] = v;
957
}
958
959
/* Simple top-down heapsort. */
960
static
961
void
962
tr_heapsort(const int *ISAd, int *SA, int size) {
963
int i, m;
964
int t;
965
966
m = size;
967
if((size % 2) == 0) {
968
m--;
969
if(ISAd[SA[m / 2]] < ISAd[SA[m]]) { SWAP(SA[m], SA[m / 2]); }
970
}
971
972
for(i = m / 2 - 1; 0 <= i; --i) { tr_fixdown(ISAd, SA, i, m); }
973
if((size % 2) == 0) { SWAP(SA[0], SA[m]); tr_fixdown(ISAd, SA, 0, m); }
974
for(i = m - 1; 0 < i; --i) {
975
t = SA[0], SA[0] = SA[i];
976
tr_fixdown(ISAd, SA, 0, i);
977
SA[i] = t;
978
}
979
}
980
981
982
/*---------------------------------------------------------------------------*/
983
984
/* Returns the median of three elements. */
985
static INLINE
986
int *
987
tr_median3(const int *ISAd, int *v1, int *v2, int *v3) {
988
int *t;
989
if(ISAd[*v1] > ISAd[*v2]) { SWAP(v1, v2); }
990
if(ISAd[*v2] > ISAd[*v3]) {
991
if(ISAd[*v1] > ISAd[*v3]) { return v1; }
992
else { return v3; }
993
}
994
return v2;
995
}
996
997
/* Returns the median of five elements. */
998
static INLINE
999
int *
1000
tr_median5(const int *ISAd,
1001
int *v1, int *v2, int *v3, int *v4, int *v5) {
1002
int *t;
1003
if(ISAd[*v2] > ISAd[*v3]) { SWAP(v2, v3); }
1004
if(ISAd[*v4] > ISAd[*v5]) { SWAP(v4, v5); }
1005
if(ISAd[*v2] > ISAd[*v4]) { SWAP(v2, v4); SWAP(v3, v5); }
1006
if(ISAd[*v1] > ISAd[*v3]) { SWAP(v1, v3); }
1007
if(ISAd[*v1] > ISAd[*v4]) { SWAP(v1, v4); SWAP(v3, v5); }
1008
if(ISAd[*v3] > ISAd[*v4]) { return v4; }
1009
return v3;
1010
}
1011
1012
/* Returns the pivot element. */
1013
static INLINE
1014
int *
1015
tr_pivot(const int *ISAd, int *first, int *last) {
1016
int *middle;
1017
int t;
1018
1019
t = last - first;
1020
middle = first + t / 2;
1021
1022
if(t <= 512) {
1023
if(t <= 32) {
1024
return tr_median3(ISAd, first, middle, last - 1);
1025
} else {
1026
t >>= 2;
1027
return tr_median5(ISAd, first, first + t, middle, last - 1 - t, last - 1);
1028
}
1029
}
1030
t >>= 3;
1031
first = tr_median3(ISAd, first, first + t, first + (t << 1));
1032
middle = tr_median3(ISAd, middle - t, middle, middle + t);
1033
last = tr_median3(ISAd, last - 1 - (t << 1), last - 1 - t, last - 1);
1034
return tr_median3(ISAd, first, middle, last);
1035
}
1036
1037
1038
/*---------------------------------------------------------------------------*/
1039
1040
typedef struct _trbudget_t trbudget_t;
1041
struct _trbudget_t {
1042
int chance;
1043
int remain;
1044
int incval;
1045
int count;
1046
};
1047
1048
static INLINE
1049
void
1050
trbudget_init(trbudget_t *budget, int chance, int incval) {
1051
budget->chance = chance;
1052
budget->remain = budget->incval = incval;
1053
}
1054
1055
static INLINE
1056
int
1057
trbudget_check(trbudget_t *budget, int size) {
1058
if(size <= budget->remain) { budget->remain -= size; return 1; }
1059
if(budget->chance == 0) { budget->count += size; return 0; }
1060
budget->remain += budget->incval - size;
1061
budget->chance -= 1;
1062
return 1;
1063
}
1064
1065
1066
/*---------------------------------------------------------------------------*/
1067
1068
static INLINE
1069
void
1070
tr_partition(const int *ISAd,
1071
int *first, int *middle, int *last,
1072
int **pa, int **pb, int v) {
1073
int *a, *b, *c, *d, *e, *f;
1074
int t, s;
1075
int x = 0;
1076
1077
for(b = middle - 1; (++b < last) && ((x = ISAd[*b]) == v);) { }
1078
if(((a = b) < last) && (x < v)) {
1079
for(; (++b < last) && ((x = ISAd[*b]) <= v);) {
1080
if(x == v) { SWAP(*b, *a); ++a; }
1081
}
1082
}
1083
for(c = last; (b < --c) && ((x = ISAd[*c]) == v);) { }
1084
if((b < (d = c)) && (x > v)) {
1085
for(; (b < --c) && ((x = ISAd[*c]) >= v);) {
1086
if(x == v) { SWAP(*c, *d); --d; }
1087
}
1088
}
1089
for(; b < c;) {
1090
SWAP(*b, *c);
1091
for(; (++b < c) && ((x = ISAd[*b]) <= v);) {
1092
if(x == v) { SWAP(*b, *a); ++a; }
1093
}
1094
for(; (b < --c) && ((x = ISAd[*c]) >= v);) {
1095
if(x == v) { SWAP(*c, *d); --d; }
1096
}
1097
}
1098
1099
if(a <= d) {
1100
c = b - 1;
1101
if((s = a - first) > (t = b - a)) { s = t; }
1102
for(e = first, f = b - s; 0 < s; --s, ++e, ++f) { SWAP(*e, *f); }
1103
if((s = d - c) > (t = last - d - 1)) { s = t; }
1104
for(e = b, f = last - s; 0 < s; --s, ++e, ++f) { SWAP(*e, *f); }
1105
first += (b - a), last -= (d - c);
1106
}
1107
*pa = first, *pb = last;
1108
}
1109
1110
static
1111
void
1112
tr_copy(int *ISA, const int *SA,
1113
int *first, int *a, int *b, int *last,
1114
int depth) {
1115
/* sort suffixes of middle partition
1116
by using sorted order of suffixes of left and right partition. */
1117
int *c, *d, *e;
1118
int s, v;
1119
1120
v = b - SA - 1;
1121
for(c = first, d = a - 1; c <= d; ++c) {
1122
if((0 <= (s = *c - depth)) && (ISA[s] == v)) {
1123
*++d = s;
1124
ISA[s] = d - SA;
1125
}
1126
}
1127
for(c = last - 1, e = d + 1, d = b; e < d; --c) {
1128
if((0 <= (s = *c - depth)) && (ISA[s] == v)) {
1129
*--d = s;
1130
ISA[s] = d - SA;
1131
}
1132
}
1133
}
1134
1135
static
1136
void
1137
tr_partialcopy(int *ISA, const int *SA,
1138
int *first, int *a, int *b, int *last,
1139
int depth) {
1140
int *c, *d, *e;
1141
int s, v;
1142
int rank, lastrank, newrank = -1;
1143
1144
v = b - SA - 1;
1145
lastrank = -1;
1146
for(c = first, d = a - 1; c <= d; ++c) {
1147
if((0 <= (s = *c - depth)) && (ISA[s] == v)) {
1148
*++d = s;
1149
rank = ISA[s + depth];
1150
if(lastrank != rank) { lastrank = rank; newrank = d - SA; }
1151
ISA[s] = newrank;
1152
}
1153
}
1154
1155
lastrank = -1;
1156
for(e = d; first <= e; --e) {
1157
rank = ISA[*e];
1158
if(lastrank != rank) { lastrank = rank; newrank = e - SA; }
1159
if(newrank != rank) { ISA[*e] = newrank; }
1160
}
1161
1162
lastrank = -1;
1163
for(c = last - 1, e = d + 1, d = b; e < d; --c) {
1164
if((0 <= (s = *c - depth)) && (ISA[s] == v)) {
1165
*--d = s;
1166
rank = ISA[s + depth];
1167
if(lastrank != rank) { lastrank = rank; newrank = d - SA; }
1168
ISA[s] = newrank;
1169
}
1170
}
1171
}
1172
1173
static
1174
void
1175
tr_introsort(int *ISA, const int *ISAd,
1176
int *SA, int *first, int *last,
1177
trbudget_t *budget) {
1178
#define STACK_SIZE TR_STACKSIZE
1179
struct { const int *a; int *b, *c; int d, e; }stack[STACK_SIZE];
1180
int *a, *b, *c;
1181
int t;
1182
int v, x = 0;
1183
int incr = ISAd - ISA;
1184
int limit, next;
1185
int ssize, trlink = -1;
1186
1187
for(ssize = 0, limit = tr_ilg(last - first);;) {
1188
1189
if(limit < 0) {
1190
if(limit == -1) {
1191
/* tandem repeat partition */
1192
tr_partition(ISAd - incr, first, first, last, &a, &b, last - SA - 1);
1193
1194
/* update ranks */
1195
if(a < last) {
1196
for(c = first, v = a - SA - 1; c < a; ++c) { ISA[*c] = v; }
1197
}
1198
if(b < last) {
1199
for(c = a, v = b - SA - 1; c < b; ++c) { ISA[*c] = v; }
1200
}
1201
1202
/* push */
1203
if(1 < (b - a)) {
1204
STACK_PUSH5(NULL, a, b, 0, 0);
1205
STACK_PUSH5(ISAd - incr, first, last, -2, trlink);
1206
trlink = ssize - 2;
1207
}
1208
if((a - first) <= (last - b)) {
1209
if(1 < (a - first)) {
1210
STACK_PUSH5(ISAd, b, last, tr_ilg(last - b), trlink);
1211
last = a, limit = tr_ilg(a - first);
1212
} else if(1 < (last - b)) {
1213
first = b, limit = tr_ilg(last - b);
1214
} else {
1215
STACK_POP5(ISAd, first, last, limit, trlink);
1216
}
1217
} else {
1218
if(1 < (last - b)) {
1219
STACK_PUSH5(ISAd, first, a, tr_ilg(a - first), trlink);
1220
first = b, limit = tr_ilg(last - b);
1221
} else if(1 < (a - first)) {
1222
last = a, limit = tr_ilg(a - first);
1223
} else {
1224
STACK_POP5(ISAd, first, last, limit, trlink);
1225
}
1226
}
1227
} else if(limit == -2) {
1228
/* tandem repeat copy */
1229
a = stack[--ssize].b, b = stack[ssize].c;
1230
if(stack[ssize].d == 0) {
1231
tr_copy(ISA, SA, first, a, b, last, ISAd - ISA);
1232
} else {
1233
if(0 <= trlink) { stack[trlink].d = -1; }
1234
tr_partialcopy(ISA, SA, first, a, b, last, ISAd - ISA);
1235
}
1236
STACK_POP5(ISAd, first, last, limit, trlink);
1237
} else {
1238
/* sorted partition */
1239
if(0 <= *first) {
1240
a = first;
1241
do { ISA[*a] = a - SA; } while((++a < last) && (0 <= *a));
1242
first = a;
1243
}
1244
if(first < last) {
1245
a = first; do { *a = ~*a; } while(*++a < 0);
1246
next = (ISA[*a] != ISAd[*a]) ? tr_ilg(a - first + 1) : -1;
1247
if(++a < last) { for(b = first, v = a - SA - 1; b < a; ++b) { ISA[*b] = v; } }
1248
1249
/* push */
1250
if(trbudget_check(budget, a - first)) {
1251
if((a - first) <= (last - a)) {
1252
STACK_PUSH5(ISAd, a, last, -3, trlink);
1253
ISAd += incr, last = a, limit = next;
1254
} else {
1255
if(1 < (last - a)) {
1256
STACK_PUSH5(ISAd + incr, first, a, next, trlink);
1257
first = a, limit = -3;
1258
} else {
1259
ISAd += incr, last = a, limit = next;
1260
}
1261
}
1262
} else {
1263
if(0 <= trlink) { stack[trlink].d = -1; }
1264
if(1 < (last - a)) {
1265
first = a, limit = -3;
1266
} else {
1267
STACK_POP5(ISAd, first, last, limit, trlink);
1268
}
1269
}
1270
} else {
1271
STACK_POP5(ISAd, first, last, limit, trlink);
1272
}
1273
}
1274
continue;
1275
}
1276
1277
if((last - first) <= TR_INSERTIONSORT_THRESHOLD) {
1278
tr_insertionsort(ISAd, first, last);
1279
limit = -3;
1280
continue;
1281
}
1282
1283
if(limit-- == 0) {
1284
tr_heapsort(ISAd, first, last - first);
1285
for(a = last - 1; first < a; a = b) {
1286
for(x = ISAd[*a], b = a - 1; (first <= b) && (ISAd[*b] == x); --b) { *b = ~*b; }
1287
}
1288
limit = -3;
1289
continue;
1290
}
1291
1292
/* choose pivot */
1293
a = tr_pivot(ISAd, first, last);
1294
SWAP(*first, *a);
1295
v = ISAd[*first];
1296
1297
/* partition */
1298
tr_partition(ISAd, first, first + 1, last, &a, &b, v);
1299
if((last - first) != (b - a)) {
1300
next = (ISA[*a] != v) ? tr_ilg(b - a) : -1;
1301
1302
/* update ranks */
1303
for(c = first, v = a - SA - 1; c < a; ++c) { ISA[*c] = v; }
1304
if(b < last) { for(c = a, v = b - SA - 1; c < b; ++c) { ISA[*c] = v; } }
1305
1306
/* push */
1307
if((1 < (b - a)) && (trbudget_check(budget, b - a))) {
1308
if((a - first) <= (last - b)) {
1309
if((last - b) <= (b - a)) {
1310
if(1 < (a - first)) {
1311
STACK_PUSH5(ISAd + incr, a, b, next, trlink);
1312
STACK_PUSH5(ISAd, b, last, limit, trlink);
1313
last = a;
1314
} else if(1 < (last - b)) {
1315
STACK_PUSH5(ISAd + incr, a, b, next, trlink);
1316
first = b;
1317
} else {
1318
ISAd += incr, first = a, last = b, limit = next;
1319
}
1320
} else if((a - first) <= (b - a)) {
1321
if(1 < (a - first)) {
1322
STACK_PUSH5(ISAd, b, last, limit, trlink);
1323
STACK_PUSH5(ISAd + incr, a, b, next, trlink);
1324
last = a;
1325
} else {
1326
STACK_PUSH5(ISAd, b, last, limit, trlink);
1327
ISAd += incr, first = a, last = b, limit = next;
1328
}
1329
} else {
1330
STACK_PUSH5(ISAd, b, last, limit, trlink);
1331
STACK_PUSH5(ISAd, first, a, limit, trlink);
1332
ISAd += incr, first = a, last = b, limit = next;
1333
}
1334
} else {
1335
if((a - first) <= (b - a)) {
1336
if(1 < (last - b)) {
1337
STACK_PUSH5(ISAd + incr, a, b, next, trlink);
1338
STACK_PUSH5(ISAd, first, a, limit, trlink);
1339
first = b;
1340
} else if(1 < (a - first)) {
1341
STACK_PUSH5(ISAd + incr, a, b, next, trlink);
1342
last = a;
1343
} else {
1344
ISAd += incr, first = a, last = b, limit = next;
1345
}
1346
} else if((last - b) <= (b - a)) {
1347
if(1 < (last - b)) {
1348
STACK_PUSH5(ISAd, first, a, limit, trlink);
1349
STACK_PUSH5(ISAd + incr, a, b, next, trlink);
1350
first = b;
1351
} else {
1352
STACK_PUSH5(ISAd, first, a, limit, trlink);
1353
ISAd += incr, first = a, last = b, limit = next;
1354
}
1355
} else {
1356
STACK_PUSH5(ISAd, first, a, limit, trlink);
1357
STACK_PUSH5(ISAd, b, last, limit, trlink);
1358
ISAd += incr, first = a, last = b, limit = next;
1359
}
1360
}
1361
} else {
1362
if((1 < (b - a)) && (0 <= trlink)) { stack[trlink].d = -1; }
1363
if((a - first) <= (last - b)) {
1364
if(1 < (a - first)) {
1365
STACK_PUSH5(ISAd, b, last, limit, trlink);
1366
last = a;
1367
} else if(1 < (last - b)) {
1368
first = b;
1369
} else {
1370
STACK_POP5(ISAd, first, last, limit, trlink);
1371
}
1372
} else {
1373
if(1 < (last - b)) {
1374
STACK_PUSH5(ISAd, first, a, limit, trlink);
1375
first = b;
1376
} else if(1 < (a - first)) {
1377
last = a;
1378
} else {
1379
STACK_POP5(ISAd, first, last, limit, trlink);
1380
}
1381
}
1382
}
1383
} else {
1384
if(trbudget_check(budget, last - first)) {
1385
limit = tr_ilg(last - first), ISAd += incr;
1386
} else {
1387
if(0 <= trlink) { stack[trlink].d = -1; }
1388
STACK_POP5(ISAd, first, last, limit, trlink);
1389
}
1390
}
1391
}
1392
#undef STACK_SIZE
1393
}
1394
1395
1396
1397
/*---------------------------------------------------------------------------*/
1398
1399
/* Tandem repeat sort */
1400
static
1401
void
1402
trsort(int *ISA, int *SA, int n, int depth) {
1403
int *ISAd;
1404
int *first, *last;
1405
trbudget_t budget;
1406
int t, skip, unsorted;
1407
1408
trbudget_init(&budget, tr_ilg(n) * 2 / 3, n);
1409
/* trbudget_init(&budget, tr_ilg(n) * 3 / 4, n); */
1410
for(ISAd = ISA + depth; -n < *SA; ISAd += ISAd - ISA) {
1411
first = SA;
1412
skip = 0;
1413
unsorted = 0;
1414
do {
1415
if((t = *first) < 0) { first -= t; skip += t; }
1416
else {
1417
if(skip != 0) { *(first + skip) = skip; skip = 0; }
1418
last = SA + ISA[t] + 1;
1419
if(1 < (last - first)) {
1420
budget.count = 0;
1421
tr_introsort(ISA, ISAd, SA, first, last, &budget);
1422
if(budget.count != 0) { unsorted += budget.count; }
1423
else { skip = first - last; }
1424
} else if((last - first) == 1) {
1425
skip = -1;
1426
}
1427
first = last;
1428
}
1429
} while(first < (SA + n));
1430
if(skip != 0) { *(first + skip) = skip; }
1431
if(unsorted == 0) { break; }
1432
}
1433
}
1434
1435
1436
/*---------------------------------------------------------------------------*/
1437
1438
/* Sorts suffixes of type B*. */
1439
static
1440
int
1441
sort_typeBstar(const unsigned char *T, int *SA,
1442
int *bucket_A, int *bucket_B,
1443
int n, int openMP) {
1444
int *PAb, *ISAb, *buf;
1445
#ifdef LIBBSC_OPENMP
1446
int *curbuf;
1447
int l;
1448
#endif
1449
int i, j, k, t, m, bufsize;
1450
int c0, c1;
1451
#ifdef LIBBSC_OPENMP
1452
int d0, d1;
1453
#endif
1454
(void)openMP;
1455
1456
/* Initialize bucket arrays. */
1457
for(i = 0; i < BUCKET_A_SIZE; ++i) { bucket_A[i] = 0; }
1458
for(i = 0; i < BUCKET_B_SIZE; ++i) { bucket_B[i] = 0; }
1459
1460
/* Count the number of occurrences of the first one or two characters of each
1461
type A, B and B* suffix. Moreover, store the beginning position of all
1462
type B* suffixes into the array SA. */
1463
for(i = n - 1, m = n, c0 = T[n - 1]; 0 <= i;) {
1464
/* type A suffix. */
1465
do { ++BUCKET_A(c1 = c0); } while((0 <= --i) && ((c0 = T[i]) >= c1));
1466
if(0 <= i) {
1467
/* type B* suffix. */
1468
++BUCKET_BSTAR(c0, c1);
1469
SA[--m] = i;
1470
/* type B suffix. */
1471
for(--i, c1 = c0; (0 <= i) && ((c0 = T[i]) <= c1); --i, c1 = c0) {
1472
++BUCKET_B(c0, c1);
1473
}
1474
}
1475
}
1476
m = n - m;
1477
/*
1478
note:
1479
A type B* suffix is lexicographically smaller than a type B suffix that
1480
begins with the same first two characters.
1481
*/
1482
1483
/* Calculate the index of start/end point of each bucket. */
1484
for(c0 = 0, i = 0, j = 0; c0 < ALPHABET_SIZE; ++c0) {
1485
t = i + BUCKET_A(c0);
1486
BUCKET_A(c0) = i + j; /* start point */
1487
i = t + BUCKET_B(c0, c0);
1488
for(c1 = c0 + 1; c1 < ALPHABET_SIZE; ++c1) {
1489
j += BUCKET_BSTAR(c0, c1);
1490
BUCKET_BSTAR(c0, c1) = j; /* end point */
1491
i += BUCKET_B(c0, c1);
1492
}
1493
}
1494
1495
if(0 < m) {
1496
/* Sort the type B* suffixes by their first two characters. */
1497
PAb = SA + n - m; ISAb = SA + m;
1498
for(i = m - 2; 0 <= i; --i) {
1499
t = PAb[i], c0 = T[t], c1 = T[t + 1];
1500
SA[--BUCKET_BSTAR(c0, c1)] = i;
1501
}
1502
t = PAb[m - 1], c0 = T[t], c1 = T[t + 1];
1503
SA[--BUCKET_BSTAR(c0, c1)] = m - 1;
1504
1505
/* Sort the type B* substrings using sssort. */
1506
#ifdef LIBBSC_OPENMP
1507
if (openMP)
1508
{
1509
buf = SA + m;
1510
c0 = ALPHABET_SIZE - 2, c1 = ALPHABET_SIZE - 1, j = m;
1511
#pragma omp parallel default(shared) private(bufsize, curbuf, k, l, d0, d1)
1512
{
1513
bufsize = (n - (2 * m)) / omp_get_num_threads();
1514
curbuf = buf + omp_get_thread_num() * bufsize;
1515
k = 0;
1516
for(;;) {
1517
#pragma omp critical(sssort_lock)
1518
{
1519
if(0 < (l = j)) {
1520
d0 = c0, d1 = c1;
1521
do {
1522
k = BUCKET_BSTAR(d0, d1);
1523
if(--d1 <= d0) {
1524
d1 = ALPHABET_SIZE - 1;
1525
if(--d0 < 0) { break; }
1526
}
1527
} while(((l - k) <= 1) && (0 < (l = k)));
1528
c0 = d0, c1 = d1, j = k;
1529
}
1530
}
1531
if(l == 0) { break; }
1532
sssort(T, PAb, SA + k, SA + l,
1533
curbuf, bufsize, 2, n, *(SA + k) == (m - 1));
1534
}
1535
}
1536
}
1537
else
1538
{
1539
buf = SA + m, bufsize = n - (2 * m);
1540
for(c0 = ALPHABET_SIZE - 2, j = m; 0 < j; --c0) {
1541
for(c1 = ALPHABET_SIZE - 1; c0 < c1; j = i, --c1) {
1542
i = BUCKET_BSTAR(c0, c1);
1543
if(1 < (j - i)) {
1544
sssort(T, PAb, SA + i, SA + j,
1545
buf, bufsize, 2, n, *(SA + i) == (m - 1));
1546
}
1547
}
1548
}
1549
}
1550
#else
1551
buf = SA + m, bufsize = n - (2 * m);
1552
for(c0 = ALPHABET_SIZE - 2, j = m; 0 < j; --c0) {
1553
for(c1 = ALPHABET_SIZE - 1; c0 < c1; j = i, --c1) {
1554
i = BUCKET_BSTAR(c0, c1);
1555
if(1 < (j - i)) {
1556
sssort(T, PAb, SA + i, SA + j,
1557
buf, bufsize, 2, n, *(SA + i) == (m - 1));
1558
}
1559
}
1560
}
1561
#endif
1562
1563
/* Compute ranks of type B* substrings. */
1564
for(i = m - 1; 0 <= i; --i) {
1565
if(0 <= SA[i]) {
1566
j = i;
1567
do { ISAb[SA[i]] = i; } while((0 <= --i) && (0 <= SA[i]));
1568
SA[i + 1] = i - j;
1569
if(i <= 0) { break; }
1570
}
1571
j = i;
1572
do { ISAb[SA[i] = ~SA[i]] = j; } while(SA[--i] < 0);
1573
ISAb[SA[i]] = j;
1574
}
1575
1576
/* Construct the inverse suffix array of type B* suffixes using trsort. */
1577
trsort(ISAb, SA, m, 1);
1578
1579
/* Set the sorted order of type B* suffixes. */
1580
for(i = n - 1, j = m, c0 = T[n - 1]; 0 <= i;) {
1581
for(--i, c1 = c0; (0 <= i) && ((c0 = T[i]) >= c1); --i, c1 = c0) { }
1582
if(0 <= i) {
1583
t = i;
1584
for(--i, c1 = c0; (0 <= i) && ((c0 = T[i]) <= c1); --i, c1 = c0) { }
1585
SA[ISAb[--j]] = ((t == 0) || (1 < (t - i))) ? t : ~t;
1586
}
1587
}
1588
1589
/* Calculate the index of start/end point of each bucket. */
1590
BUCKET_B(ALPHABET_SIZE - 1, ALPHABET_SIZE - 1) = n; /* end point */
1591
for(c0 = ALPHABET_SIZE - 2, k = m - 1; 0 <= c0; --c0) {
1592
i = BUCKET_A(c0 + 1) - 1;
1593
for(c1 = ALPHABET_SIZE - 1; c0 < c1; --c1) {
1594
t = i - BUCKET_B(c0, c1);
1595
BUCKET_B(c0, c1) = i; /* end point */
1596
1597
/* Move all type B* suffixes to the correct position. */
1598
for(i = t, j = BUCKET_BSTAR(c0, c1);
1599
j <= k;
1600
--i, --k) { SA[i] = SA[k]; }
1601
}
1602
BUCKET_BSTAR(c0, c0 + 1) = i - BUCKET_B(c0, c0) + 1; /* start point */
1603
BUCKET_B(c0, c0) = i; /* end point */
1604
}
1605
}
1606
1607
return m;
1608
}
1609
1610
/* Constructs the suffix array by using the sorted order of type B* suffixes. */
1611
static
1612
void
1613
construct_SA(const unsigned char *T, int *SA,
1614
int *bucket_A, int *bucket_B,
1615
int n, int m) {
1616
int *i, *j, *k;
1617
int s;
1618
int c0, c1, c2;
1619
1620
if(0 < m) {
1621
/* Construct the sorted order of type B suffixes by using
1622
the sorted order of type B* suffixes. */
1623
for(c1 = ALPHABET_SIZE - 2; 0 <= c1; --c1) {
1624
/* Scan the suffix array from right to left. */
1625
for(i = SA + BUCKET_BSTAR(c1, c1 + 1),
1626
j = SA + BUCKET_A(c1 + 1) - 1, k = NULL, c2 = -1;
1627
i <= j;
1628
--j) {
1629
if(0 < (s = *j)) {
1630
assert(T[s] == c1);
1631
assert(((s + 1) < n) && (T[s] <= T[s + 1]));
1632
assert(T[s - 1] <= T[s]);
1633
*j = ~s;
1634
c0 = T[--s];
1635
if((0 < s) && (T[s - 1] > c0)) { s = ~s; }
1636
if(c0 != c2) {
1637
if(0 <= c2) { BUCKET_B(c2, c1) = k - SA; }
1638
k = SA + BUCKET_B(c2 = c0, c1);
1639
}
1640
assert(k < j); assert(k != NULL);
1641
*k-- = s;
1642
} else {
1643
assert(((s == 0) && (T[s] == c1)) || (s < 0));
1644
*j = ~s;
1645
}
1646
}
1647
}
1648
}
1649
1650
/* Construct the suffix array by using
1651
the sorted order of type B suffixes. */
1652
k = SA + BUCKET_A(c2 = T[n - 1]);
1653
*k++ = (T[n - 2] < c2) ? ~(n - 1) : (n - 1);
1654
/* Scan the suffix array from left to right. */
1655
for(i = SA, j = SA + n; i < j; ++i) {
1656
if(0 < (s = *i)) {
1657
assert(T[s - 1] >= T[s]);
1658
c0 = T[--s];
1659
if((s == 0) || (T[s - 1] < c0)) { s = ~s; }
1660
if(c0 != c2) {
1661
BUCKET_A(c2) = k - SA;
1662
k = SA + BUCKET_A(c2 = c0);
1663
}
1664
assert(i < k);
1665
*k++ = s;
1666
} else {
1667
assert(s < 0);
1668
*i = ~s;
1669
}
1670
}
1671
}
1672
1673
/* Constructs the burrows-wheeler transformed string directly
1674
by using the sorted order of type B* suffixes. */
1675
static
1676
int
1677
construct_BWT(const unsigned char *T, int *SA,
1678
int *bucket_A, int *bucket_B,
1679
int n, int m) {
1680
int *i, *j, *k, *orig;
1681
int s;
1682
int c0, c1, c2;
1683
1684
if(0 < m) {
1685
/* Construct the sorted order of type B suffixes by using
1686
the sorted order of type B* suffixes. */
1687
for(c1 = ALPHABET_SIZE - 2; 0 <= c1; --c1) {
1688
/* Scan the suffix array from right to left. */
1689
for(i = SA + BUCKET_BSTAR(c1, c1 + 1),
1690
j = SA + BUCKET_A(c1 + 1) - 1, k = NULL, c2 = -1;
1691
i <= j;
1692
--j) {
1693
if(0 < (s = *j)) {
1694
assert(T[s] == c1);
1695
assert(((s + 1) < n) && (T[s] <= T[s + 1]));
1696
assert(T[s - 1] <= T[s]);
1697
c0 = T[--s];
1698
*j = ~((int)c0);
1699
if((0 < s) && (T[s - 1] > c0)) { s = ~s; }
1700
if(c0 != c2) {
1701
if(0 <= c2) { BUCKET_B(c2, c1) = k - SA; }
1702
k = SA + BUCKET_B(c2 = c0, c1);
1703
}
1704
assert(k < j); assert(k != NULL);
1705
*k-- = s;
1706
} else if(s != 0) {
1707
*j = ~s;
1708
#ifndef NDEBUG
1709
} else {
1710
assert(T[s] == c1);
1711
#endif
1712
}
1713
}
1714
}
1715
}
1716
1717
/* Construct the BWTed string by using
1718
the sorted order of type B suffixes. */
1719
k = SA + BUCKET_A(c2 = T[n - 1]);
1720
*k++ = (T[n - 2] < c2) ? ~((int)T[n - 2]) : (n - 1);
1721
/* Scan the suffix array from left to right. */
1722
for(i = SA, j = SA + n, orig = SA; i < j; ++i) {
1723
if(0 < (s = *i)) {
1724
assert(T[s - 1] >= T[s]);
1725
c0 = T[--s];
1726
*i = c0;
1727
if((0 < s) && (T[s - 1] < c0)) { s = ~((int)T[s - 1]); }
1728
if(c0 != c2) {
1729
BUCKET_A(c2) = k - SA;
1730
k = SA + BUCKET_A(c2 = c0);
1731
}
1732
assert(i < k);
1733
*k++ = s;
1734
} else if(s != 0) {
1735
*i = ~s;
1736
} else {
1737
orig = i;
1738
}
1739
}
1740
1741
return orig - SA;
1742
}
1743
1744
/* Constructs the burrows-wheeler transformed string directly
1745
by using the sorted order of type B* suffixes. */
1746
static
1747
int
1748
construct_BWT_indexes(const unsigned char *T, int *SA,
1749
int *bucket_A, int *bucket_B,
1750
int n, int m,
1751
unsigned char * num_indexes, int * indexes) {
1752
int *i, *j, *k, *orig;
1753
int s;
1754
int c0, c1, c2;
1755
1756
int mod = n / 8;
1757
{
1758
mod |= mod >> 1; mod |= mod >> 2;
1759
mod |= mod >> 4; mod |= mod >> 8;
1760
mod |= mod >> 16; mod >>= 1;
1761
1762
*num_indexes = (unsigned char)((n - 1) / (mod + 1));
1763
}
1764
1765
if(0 < m) {
1766
/* Construct the sorted order of type B suffixes by using
1767
the sorted order of type B* suffixes. */
1768
for(c1 = ALPHABET_SIZE - 2; 0 <= c1; --c1) {
1769
/* Scan the suffix array from right to left. */
1770
for(i = SA + BUCKET_BSTAR(c1, c1 + 1),
1771
j = SA + BUCKET_A(c1 + 1) - 1, k = NULL, c2 = -1;
1772
i <= j;
1773
--j) {
1774
if(0 < (s = *j)) {
1775
assert(T[s] == c1);
1776
assert(((s + 1) < n) && (T[s] <= T[s + 1]));
1777
assert(T[s - 1] <= T[s]);
1778
1779
if ((s & mod) == 0) indexes[s / (mod + 1) - 1] = j - SA;
1780
1781
c0 = T[--s];
1782
*j = ~((int)c0);
1783
if((0 < s) && (T[s - 1] > c0)) { s = ~s; }
1784
if(c0 != c2) {
1785
if(0 <= c2) { BUCKET_B(c2, c1) = k - SA; }
1786
k = SA + BUCKET_B(c2 = c0, c1);
1787
}
1788
assert(k < j); assert(k != NULL);
1789
*k-- = s;
1790
} else if(s != 0) {
1791
*j = ~s;
1792
#ifndef NDEBUG
1793
} else {
1794
assert(T[s] == c1);
1795
#endif
1796
}
1797
}
1798
}
1799
}
1800
1801
/* Construct the BWTed string by using
1802
the sorted order of type B suffixes. */
1803
k = SA + BUCKET_A(c2 = T[n - 1]);
1804
if (T[n - 2] < c2) {
1805
if (((n - 1) & mod) == 0) indexes[(n - 1) / (mod + 1) - 1] = k - SA;
1806
*k++ = ~((int)T[n - 2]);
1807
}
1808
else {
1809
*k++ = n - 1;
1810
}
1811
1812
/* Scan the suffix array from left to right. */
1813
for(i = SA, j = SA + n, orig = SA; i < j; ++i) {
1814
if(0 < (s = *i)) {
1815
assert(T[s - 1] >= T[s]);
1816
1817
if ((s & mod) == 0) indexes[s / (mod + 1) - 1] = i - SA;
1818
1819
c0 = T[--s];
1820
*i = c0;
1821
if(c0 != c2) {
1822
BUCKET_A(c2) = k - SA;
1823
k = SA + BUCKET_A(c2 = c0);
1824
}
1825
assert(i < k);
1826
if((0 < s) && (T[s - 1] < c0)) {
1827
if ((s & mod) == 0) indexes[s / (mod + 1) - 1] = k - SA;
1828
*k++ = ~((int)T[s - 1]);
1829
} else
1830
*k++ = s;
1831
} else if(s != 0) {
1832
*i = ~s;
1833
} else {
1834
orig = i;
1835
}
1836
}
1837
1838
return orig - SA;
1839
}
1840
1841
1842
/*---------------------------------------------------------------------------*/
1843
1844
/*- Function -*/
1845
1846
int
1847
divsufsort(const unsigned char *T, int *SA, int n, int openMP) {
1848
int *bucket_A, *bucket_B;
1849
int m;
1850
int err = 0;
1851
1852
/* Check arguments. */
1853
if((T == NULL) || (SA == NULL) || (n < 0)) { return -1; }
1854
else if(n == 0) { return 0; }
1855
else if(n == 1) { SA[0] = 0; return 0; }
1856
else if(n == 2) { m = (T[0] < T[1]); SA[m ^ 1] = 0, SA[m] = 1; return 0; }
1857
1858
bucket_A = (int *)malloc(BUCKET_A_SIZE * sizeof(int));
1859
bucket_B = (int *)malloc(BUCKET_B_SIZE * sizeof(int));
1860
1861
/* Suffixsort. */
1862
if((bucket_A != NULL) && (bucket_B != NULL)) {
1863
m = sort_typeBstar(T, SA, bucket_A, bucket_B, n, openMP);
1864
construct_SA(T, SA, bucket_A, bucket_B, n, m);
1865
} else {
1866
err = -2;
1867
}
1868
1869
free(bucket_B);
1870
free(bucket_A);
1871
1872
return err;
1873
}
1874
1875
int
1876
divbwt(const unsigned char *T, unsigned char *U, int *A, int n, unsigned char * num_indexes, int * indexes, int openMP) {
1877
int *B;
1878
int *bucket_A, *bucket_B;
1879
int m, pidx, i;
1880
1881
/* Check arguments. */
1882
if((T == NULL) || (U == NULL) || (n < 0)) { return -1; }
1883
else if(n <= 1) { if(n == 1) { U[0] = T[0]; } return n; }
1884
1885
if((B = A) == NULL) { B = (int *)malloc((size_t)(n + 1) * sizeof(int)); }
1886
bucket_A = (int *)malloc(BUCKET_A_SIZE * sizeof(int));
1887
bucket_B = (int *)malloc(BUCKET_B_SIZE * sizeof(int));
1888
1889
/* Burrows-Wheeler Transform. */
1890
if((B != NULL) && (bucket_A != NULL) && (bucket_B != NULL)) {
1891
m = sort_typeBstar(T, B, bucket_A, bucket_B, n, openMP);
1892
1893
if (num_indexes == NULL || indexes == NULL) {
1894
pidx = construct_BWT(T, B, bucket_A, bucket_B, n, m);
1895
} else {
1896
pidx = construct_BWT_indexes(T, B, bucket_A, bucket_B, n, m, num_indexes, indexes);
1897
}
1898
1899
/* Copy to output string. */
1900
U[0] = T[n - 1];
1901
for(i = 0; i < pidx; ++i) { U[i + 1] = (unsigned char)B[i]; }
1902
for(i += 1; i < n; ++i) { U[i] = (unsigned char)B[i]; }
1903
pidx += 1;
1904
} else {
1905
pidx = -2;
1906
}
1907
1908
free(bucket_B);
1909
free(bucket_A);
1910
if(A == NULL) { free(B); }
1911
1912
return pidx;
1913
}
1914
1915