File Coverage

c-lib/libdivsufsort/divsufsort.c
Criterion Covered Total %
statement 101 104 97.1
branch 80 108 74.0
condition n/a
subroutine n/a
pod n/a
total 181 212 85.3


line stmt bran cond sub pod time code
1             /*
2             * divsufsort.c for libdivsufsort
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             #include "divsufsort_private.h"
28             #ifdef _OPENMP
29             # include
30             #endif
31              
32              
33             /*- Private Functions -*/
34              
35             /* Sorts suffixes of type B*. */
36             static
37             saidx_t
38 48           sort_typeBstar(const sauchar_t *T, saidx_t *SA,
39             saidx_t *bucket_A, saidx_t *bucket_B,
40             saidx_t n) {
41             saidx_t *PAb, *ISAb, *buf;
42             #ifdef _OPENMP
43             saidx_t *curbuf;
44             saidx_t l;
45             #endif
46             saidx_t i, j, k, t, m, bufsize;
47             saint_t c0, c1;
48             #ifdef _OPENMP
49             saint_t d0, d1;
50             int tmp;
51             #endif
52              
53             /* Initialize bucket arrays. */
54 12336 100         for(i = 0; i < BUCKET_A_SIZE; ++i) { bucket_A[i] = 0; }
55 3145776 100         for(i = 0; i < BUCKET_B_SIZE; ++i) { bucket_B[i] = 0; }
56              
57             /* Count the number of occurrences of the first one or two characters of each
58             type A, B and B* suffix. Moreover, store the beginning position of all
59             type B* suffixes into the array SA. */
60 4560096 100         for(i = n - 1, m = n, c0 = T[n - 1]; 0 <= i;) {
61             /* type A suffix. */
62 4560000 50         do { ++BUCKET_A(c1 = c0); } while((0 <= --i) && ((c0 = T[i]) >= c1));
    50          
63 4560000 50         if(0 <= i) {
64             /* type B* suffix. */
65 4560000           ++BUCKET_BSTAR(c0, c1);
66 4560000           SA[--m] = i;
67             /* type B suffix. */
68 18240000 100         for(--i, c1 = c0; (0 <= i) && ((c0 = T[i]) <= c1); --i, c1 = c0) {
    100          
69 13680000           ++BUCKET_B(c0, c1);
70             }
71             }
72             }
73 48           m = n - m;
74             /*
75             note:
76             A type B* suffix is lexicographically smaller than a type B suffix that
77             begins with the same first two characters.
78             */
79              
80             /* Calculate the index of start/end point of each bucket. */
81 12336 100         for(c0 = 0, i = 0, j = 0; c0 < ALPHABET_SIZE; ++c0) {
82 12288           t = i + BUCKET_A(c0);
83 12288           BUCKET_A(c0) = i + j; /* start point */
84 12288           i = t + BUCKET_B(c0, c0);
85 1579008 100         for(c1 = c0 + 1; c1 < ALPHABET_SIZE; ++c1) {
86 1566720           j += BUCKET_BSTAR(c0, c1);
87 1566720           BUCKET_BSTAR(c0, c1) = j; /* end point */
88 1566720           i += BUCKET_B(c0, c1);
89             }
90             }
91              
92 48 50         if(0 < m) {
93             /* Sort the type B* suffixes by their first two characters. */
94 48           PAb = SA + n - m; ISAb = SA + m;
95 4560000 100         for(i = m - 2; 0 <= i; --i) {
96 4559952           t = PAb[i], c0 = T[t], c1 = T[t + 1];
97 4559952           SA[--BUCKET_BSTAR(c0, c1)] = i;
98             }
99 48           t = PAb[m - 1], c0 = T[t], c1 = T[t + 1];
100 48           SA[--BUCKET_BSTAR(c0, c1)] = m - 1;
101              
102             /* Sort the type B* substrings using sssort. */
103             #ifdef _OPENMP
104             tmp = omp_get_max_threads();
105             buf = SA + m, bufsize = (n - (2 * m)) / tmp;
106             c0 = ALPHABET_SIZE - 2, c1 = ALPHABET_SIZE - 1, j = m;
107             #pragma omp parallel default(shared) private(curbuf, k, l, d0, d1, tmp)
108             {
109             tmp = omp_get_thread_num();
110             curbuf = buf + tmp * bufsize;
111             k = 0;
112             for(;;) {
113             #pragma omp critical(sssort_lock)
114             {
115             if(0 < (l = j)) {
116             d0 = c0, d1 = c1;
117             do {
118             k = BUCKET_BSTAR(d0, d1);
119             if(--d1 <= d0) {
120             d1 = ALPHABET_SIZE - 1;
121             if(--d0 < 0) { break; }
122             }
123             } while(((l - k) <= 1) && (0 < (l = k)));
124             c0 = d0, c1 = d1, j = k;
125             }
126             }
127             if(l == 0) { break; }
128             sssort(T, PAb, SA + k, SA + l,
129             curbuf, bufsize, 2, n, *(SA + k) == (m - 1));
130             }
131             }
132             #else
133 48           buf = SA + m, bufsize = n - (2 * m);
134 11760 100         for(c0 = ALPHABET_SIZE - 2, j = m; 0 < j; --c0) {
135 1446432 100         for(c1 = ALPHABET_SIZE - 1; c0 < c1; j = i, --c1) {
136 1434720           i = BUCKET_BSTAR(c0, c1);
137 1434720 100         if(1 < (j - i)) {
138 48           sssort(T, PAb, SA + i, SA + j,
139 48           buf, bufsize, 2, n, *(SA + i) == (m - 1));
140             }
141             }
142             }
143             #endif
144              
145             /* Compute ranks of type B* substrings. */
146 96 50         for(i = m - 1; 0 <= i; --i) {
147 96 100         if(0 <= SA[i]) {
148 48           j = i;
149 48 50         do { ISAb[SA[i]] = i; } while((0 <= --i) && (0 <= SA[i]));
    0          
150 48           SA[i + 1] = i - j;
151 48 50         if(i <= 0) { break; }
152             }
153 48           j = i;
154 4559904 100         do { ISAb[SA[i] = ~SA[i]] = j; } while(SA[--i] < 0);
155 48           ISAb[SA[i]] = j;
156             }
157              
158             /* Construct the inverse suffix array of type B* suffixes using trsort. */
159 48           trsort(ISAb, SA, m, 1);
160              
161             /* Set the sorted order of tyoe B* suffixes. */
162 4560096 100         for(i = n - 1, j = m, c0 = T[n - 1]; 0 <= i;) {
163 4560000 50         for(--i, c1 = c0; (0 <= i) && ((c0 = T[i]) >= c1); --i, c1 = c0) { }
    50          
164 4560000 50         if(0 <= i) {
165 4560000           t = i;
166 18240000 100         for(--i, c1 = c0; (0 <= i) && ((c0 = T[i]) <= c1); --i, c1 = c0) { }
    100          
167 4560000 50         SA[ISAb[--j]] = ((t == 0) || (1 < (t - i))) ? t : ~t;
    50          
168             }
169             }
170              
171             /* Calculate the index of start/end point of each bucket. */
172 48           BUCKET_B(ALPHABET_SIZE - 1, ALPHABET_SIZE - 1) = n; /* end point */
173 12288 100         for(c0 = ALPHABET_SIZE - 2, k = m - 1; 0 <= c0; --c0) {
174 12240           i = BUCKET_A(c0 + 1) - 1;
175 1578960 100         for(c1 = ALPHABET_SIZE - 1; c0 < c1; --c1) {
176 1566720           t = i - BUCKET_B(c0, c1);
177 1566720           BUCKET_B(c0, c1) = i; /* end point */
178              
179             /* Move all type B* suffixes to the correct position. */
180 1566720           for(i = t, j = BUCKET_BSTAR(c0, c1);
181 6126720 100         j <= k;
182 4560000           --i, --k) { SA[i] = SA[k]; }
183             }
184 12240           BUCKET_BSTAR(c0, c0 + 1) = i - BUCKET_B(c0, c0) + 1; /* start point */
185 12240           BUCKET_B(c0, c0) = i; /* end point */
186             }
187             }
188              
189 48           return m;
190             }
191              
192             /* Constructs the suffix array by using the sorted order of type B* suffixes. */
193             static
194             void
195 48           construct_SA(const sauchar_t *T, saidx_t *SA,
196             saidx_t *bucket_A, saidx_t *bucket_B,
197             saidx_t n, saidx_t m) {
198             saidx_t *i, *j, *k;
199             saidx_t s;
200             saint_t c0, c1, c2;
201              
202 48 50         if(0 < m) {
203             /* Construct the sorted order of type B suffixes by using
204             the sorted order of type B* suffixes. */
205 12288 100         for(c1 = ALPHABET_SIZE - 2; 0 <= c1; --c1) {
206             /* Scan the suffix array from right to left. */
207 12240           for(i = SA + BUCKET_BSTAR(c1, c1 + 1),
208 12240           j = SA + BUCKET_A(c1 + 1) - 1, k = NULL, c2 = -1;
209 18252240 100         i <= j;
210 18240000           --j) {
211 18240000 100         if(0 < (s = *j)) {
212             assert(T[s] == c1);
213             assert(((s + 1) < n) && (T[s] <= T[s + 1]));
214             assert(T[s - 1] <= T[s]);
215 13680000           *j = ~s;
216 13680000           c0 = T[--s];
217 13680000 100         if((0 < s) && (T[s - 1] > c0)) { s = ~s; }
    100          
218 13680000 100         if(c0 != c2) {
219 144 50         if(0 <= c2) { BUCKET_B(c2, c1) = k - SA; }
220 144           k = SA + BUCKET_B(c2 = c0, c1);
221             }
222             assert(k < j);
223 13680000           *k-- = s;
224             } else {
225             assert(((s == 0) && (T[s] == c1)) || (s < 0));
226 4560000           *j = ~s;
227             }
228             }
229             }
230             }
231              
232             /* Construct the suffix array by using
233             the sorted order of type B suffixes. */
234 48           k = SA + BUCKET_A(c2 = T[n - 1]);
235 48 50         *k++ = (T[n - 2] < c2) ? ~(n - 1) : (n - 1);
236             /* Scan the suffix array from left to right. */
237 22800048 100         for(i = SA, j = SA + n; i < j; ++i) {
238 22800000 100         if(0 < (s = *i)) {
239             assert(T[s - 1] >= T[s]);
240 4559952           c0 = T[--s];
241 4559952 50         if((s == 0) || (T[s - 1] < c0)) { s = ~s; }
    50          
242 4559952 50         if(c0 != c2) {
243 0           BUCKET_A(c2) = k - SA;
244 0           k = SA + BUCKET_A(c2 = c0);
245             }
246             assert(i < k);
247 4559952           *k++ = s;
248             } else {
249             assert(s < 0);
250 18240048           *i = ~s;
251             }
252             }
253 48           }
254              
255             /* Constructs the burrows-wheeler transformed string directly
256             by using the sorted order of type B* suffixes. */
257             #if 0
258             static
259             saidx_t
260             construct_BWT(const sauchar_t *T, saidx_t *SA,
261             saidx_t *bucket_A, saidx_t *bucket_B,
262             saidx_t n, saidx_t m) {
263             saidx_t *i, *j, *k, *orig;
264             saidx_t s;
265             saint_t c0, c1, c2;
266              
267             if(0 < m) {
268             /* Construct the sorted order of type B suffixes by using
269             the sorted order of type B* suffixes. */
270             for(c1 = ALPHABET_SIZE - 2; 0 <= c1; --c1) {
271             /* Scan the suffix array from right to left. */
272             for(i = SA + BUCKET_BSTAR(c1, c1 + 1),
273             j = SA + BUCKET_A(c1 + 1) - 1, k = NULL, c2 = -1;
274             i <= j;
275             --j) {
276             if(0 < (s = *j)) {
277             assert(T[s] == c1);
278             assert(((s + 1) < n) && (T[s] <= T[s + 1]));
279             assert(T[s - 1] <= T[s]);
280             c0 = T[--s];
281             *j = ~((saidx_t)c0);
282             if((0 < s) && (T[s - 1] > c0)) { s = ~s; }
283             if(c0 != c2) {
284             if(0 <= c2) { BUCKET_B(c2, c1) = k - SA; }
285             k = SA + BUCKET_B(c2 = c0, c1);
286             }
287             assert(k < j);
288             *k-- = s;
289             } else if(s != 0) {
290             *j = ~s;
291             #ifndef NDEBUG
292             } else {
293             assert(T[s] == c1);
294             #endif
295             }
296             }
297             }
298             }
299              
300             /* Construct the BWTed string by using
301             the sorted order of type B suffixes. */
302             k = SA + BUCKET_A(c2 = T[n - 1]);
303             *k++ = (T[n - 2] < c2) ? ~((saidx_t)T[n - 2]) : (n - 1);
304             /* Scan the suffix array from left to right. */
305             for(i = SA, j = SA + n, orig = SA; i < j; ++i) {
306             if(0 < (s = *i)) {
307             assert(T[s - 1] >= T[s]);
308             c0 = T[--s];
309             *i = c0;
310             if((0 < s) && (T[s - 1] < c0)) { s = ~((saidx_t)T[s - 1]); }
311             if(c0 != c2) {
312             BUCKET_A(c2) = k - SA;
313             k = SA + BUCKET_A(c2 = c0);
314             }
315             assert(i < k);
316             *k++ = s;
317             } else if(s != 0) {
318             *i = ~s;
319             } else {
320             orig = i;
321             }
322             }
323              
324             return orig - SA;
325             }
326             #endif
327              
328              
329             /*---------------------------------------------------------------------------*/
330              
331             /*- Function -*/
332              
333             saint_t
334 48           divsufsort(const sauchar_t *T, saidx_t *SA, saidx_t n, struct s_bsdipa_diff_ctx *dcp) {
335             saidx_t *bucket_A, *bucket_B;
336             saidx_t m;
337 48           saint_t err = 0;
338              
339             /* Check arguments. */
340 48 50         if((T == NULL) || (SA == NULL) || (n < 0)) { return -1; }
    50          
    50          
341 48 50         else if(n == 0) { return 0; }
342 48 50         else if(n == 1) { SA[0] = 0; return 0; }
343 48 50         else if(n == 2) { m = (T[0] < T[1]); SA[m ^ 1] = 0, SA[m] = 1; return 0; }
344              
345 48           bucket_A = (saidx_t *)(*dcp->dc_mem.mc_custom_alloc)(dcp->dc_mem.mc_custom_cookie, BUCKET_A_SIZE * sizeof(saidx_t));
346 48           bucket_B = (saidx_t *)(*dcp->dc_mem.mc_custom_alloc)(dcp->dc_mem.mc_custom_cookie, BUCKET_B_SIZE * sizeof(saidx_t));
347              
348             /* Suffixsort. */
349 48 50         if((bucket_A != NULL) && (bucket_B != NULL)) {
    50          
350 48           m = sort_typeBstar(T, SA, bucket_A, bucket_B, n);
351 48           construct_SA(T, SA, bucket_A, bucket_B, n, m);
352             } else {
353 0           err = -2;
354             }
355              
356 48           (*dcp->dc_mem.mc_custom_free)(dcp->dc_mem.mc_custom_cookie, bucket_B);
357 48           (*dcp->dc_mem.mc_custom_free)(dcp->dc_mem.mc_custom_cookie, bucket_A);
358              
359 48           return err;
360             }
361              
362             #if 0
363             saidx_t
364             divbwt(const sauchar_t *T, sauchar_t *U, saidx_t *A, saidx_t n) {
365             saidx_t *B;
366             saidx_t *bucket_A, *bucket_B;
367             saidx_t m, pidx, i;
368              
369             /* Check arguments. */
370             if((T == NULL) || (U == NULL) || (n < 0)) { return -1; }
371             else if(n <= 1) { if(n == 1) { U[0] = T[0]; } return n; }
372              
373             if((B = A) == NULL) { B = (saidx_t *)malloc((size_t)(n + 1) * sizeof(saidx_t)); }
374             bucket_A = (saidx_t *)malloc(BUCKET_A_SIZE * sizeof(saidx_t));
375             bucket_B = (saidx_t *)malloc(BUCKET_B_SIZE * sizeof(saidx_t));
376              
377             /* Burrows-Wheeler Transform. */
378             if((B != NULL) && (bucket_A != NULL) && (bucket_B != NULL)) {
379             m = sort_typeBstar(T, B, bucket_A, bucket_B, n);
380             pidx = construct_BWT(T, B, bucket_A, bucket_B, n, m);
381              
382             /* Copy to output string. */
383             U[0] = T[n - 1];
384             for(i = 0; i < pidx; ++i) { U[i + 1] = (sauchar_t)B[i]; }
385             for(i += 1; i < n; ++i) { U[i] = (sauchar_t)B[i]; }
386             pidx += 1;
387             } else {
388             pidx = -2;
389             }
390              
391             free(bucket_B);
392             free(bucket_A);
393             if(A == NULL) { free(B); }
394              
395             return pidx;
396             }
397              
398             const char *
399             divsufsort_version(void) {
400             return PROJECT_VERSION_FULL;
401             }
402             #endif /* if 0 */