testing
[SXSI/XMLTree.git] / bp.c
1 #include "bp.h"\r
2 \r
3 //#define CHECK\r
4 #define RANDOM\r
5 \r
6 int msize=0;\r
7 #define mymalloc(p,n,f) {p =(__typeof__(p)) malloc((n)*sizeof(*p)); msize += (f)*(n)*sizeof(*p); /* if (f) printf("malloc %d bytes at line %d total %d\n",(n)*sizeof(*p),__LINE__,msize);  */ if ((p)==NULL) {printf("not enough memory (%d bytes) in line %d\n",msize,__LINE__); exit(1);};}\r
8 \r
9 int postorder_select_bsearch(bp *b,int s);\r
10 \r
11 int naive_depth(bp *b, int s)\r
12 {\r
13   int i,d;\r
14   if (s < 0) return 0;\r
15   d = 0;\r
16   for (i=0; i<=s; i++) {\r
17     if (getbit(b->B,i)==OP) {\r
18       d++;\r
19     } else {\r
20       d--;\r
21     }\r
22   }\r
23   return d;\r
24 }\r
25 \r
26 void printbp(bp *b, int s, int t)\r
27 {\r
28   int i,c,d;\r
29   d = 0;\r
30   for (i=s; i<=t; i++) {\r
31     if (getbit(b->B,i)==OP) {\r
32       c = '(';\r
33       d++;\r
34     } else {\r
35       c = ')';\r
36       d--;\r
37     }\r
38     putchar(c);\r
39   }\r
40 }\r
41 \r
42 int *matchtbl,*parenttbl;\r
43 void make_naivetbl(pb *B,int n)\r
44 {\r
45   int i,v;\r
46   int *stack,s;\r
47 \r
48   mymalloc(matchtbl,n,0);\r
49   mymalloc(parenttbl,n,0);\r
50   mymalloc(stack,n,0);\r
51 \r
52   for (i=0; i<n; i++) matchtbl[i] = parenttbl[i] = -1;\r
53 \r
54   s = 0;\r
55   v = 0;\r
56   stack[0] = -1;\r
57   for (i=0; i<n; i++) {\r
58     if (getbit(B,i)==OP) {\r
59       v++;\r
60       if (v > 0) {\r
61         parenttbl[i] = stack[v-1];\r
62         stack[v] = i;\r
63       }\r
64     } else {\r
65       if (v > 0) {\r
66         matchtbl[stack[v]] = i;  // close\r
67         matchtbl[i] = stack[v];   // open\r
68       }\r
69       v--;\r
70     }\r
71   }\r
72 \r
73   free(stack);\r
74 }\r
75 \r
76 int popCount[1<<ETW];\r
77 int fwdtbl[(2*ETW+1)*(1<<ETW)];\r
78 int bwdtbl[(2*ETW+1)*(1<<ETW)];\r
79 #if 0\r
80 int mintbl_li[1<<ETW], mintbl_lv[1<<ETW];\r
81 int mintbl_ri[1<<ETW], mintbl_rv[1<<ETW];\r
82 int maxtbl_li[1<<ETW], maxtbl_lv[1<<ETW];\r
83 int maxtbl_ri[1<<ETW], maxtbl_rv[1<<ETW];\r
84 #endif\r
85 int minmaxtbl_i[4][1<<ETW], minmaxtbl_v[4][1<<ETW];\r
86 int degtbl[1<<ETW];\r
87 int degtbl2[(2*ETW+1)*(1<<ETW)];\r
88 int childtbl[(ETW)*(1<<ETW)];\r
89 int childtbl2[2*ETW+1][ETW][(1<<ETW)];\r
90 int depthtbl[(2*ETW+1)*(1<<ETW)];\r
91 \r
92 void make_matchtbl(void)\r
93 {\r
94   int i,j,x,r;\r
95   int m,M;\r
96   pb buf[1];\r
97   int deg;\r
98 \r
99   for (x = 0; x < (1<<ETW); x++) {\r
100     setbits(buf,0,ETW,x);\r
101     for (r=-ETW; r<=ETW; r++) fwdtbl[((r+ETW)<<ETW)+x] = ETW;\r
102     for (r=-ETW; r<=ETW; r++) bwdtbl[((r+ETW)<<ETW)+x] = ETW;\r
103     for (r=-ETW; r<=ETW; r++) degtbl2[((r+ETW)<<ETW)+x] = 0;\r
104     for (r=-ETW; r<=ETW; r++) depthtbl[((r+ETW)<<ETW)+x] = 0;\r
105 \r
106     r = 0;\r
107     for (i=0; i<ETW; i++) {\r
108       if (getbit(buf,i)==OP) {\r
109         r++;\r
110       } else {\r
111         r--;\r
112       }\r
113       if (fwdtbl[((r+ETW)<<ETW)+x] == ETW) fwdtbl[((r+ETW)<<ETW)+x] = i;\r
114     }\r
115 \r
116     r = 0;\r
117     for (i=ETW-1; i>=0; i--) {\r
118       if (getbit(buf,i)==OP) {\r
119         r--;\r
120       } else {\r
121         r++;\r
122       }\r
123       if (bwdtbl[((r+ETW)<<ETW)+x] == ETW) bwdtbl[((r+ETW)<<ETW)+x] = ETW-1-i;\r
124     }\r
125 \r
126     r = 0;\r
127     for (i=0; i<ETW; i++) {\r
128       if (getbit(buf,i)==OP) {\r
129         r++;\r
130       } else {\r
131         r--;\r
132       }\r
133       depthtbl[((r+ETW)<<ETW)+x] += (1<<(ETW-1));\r
134     }\r
135 \r
136     r = 0;\r
137     for (i=0; i<ETW; i++) {\r
138       if (getbit(buf,i)==OP) r++;\r
139     }\r
140     popCount[x] = r;\r
141 \r
142     r = 0;  m = 0;  M = 0;\r
143     m = ETW+1;  M = -ETW-1;\r
144     //maxtbl_lv[x] = -ETW-1;\r
145     //mintbl_lv[x] = ETW+1;\r
146     minmaxtbl_v[OPT_MAX | OPT_LEFT][x] = -ETW-1;\r
147     minmaxtbl_v[OPT_MIN | OPT_LEFT][x] = ETW+1;\r
148     deg = 0;\r
149     for (i=0; i<ETW; i++) {\r
150       if (getbit(buf,i)==OP) {\r
151         r++;\r
152         if (r > M) {\r
153           M = r;  \r
154           //maxtbl_li[x] = i;  maxtbl_lv[x] = r;\r
155           minmaxtbl_i[OPT_MAX | OPT_LEFT][x] = i;\r
156           minmaxtbl_v[OPT_MAX | OPT_LEFT][x] = r;\r
157         }\r
158       } else {\r
159         r--;\r
160         if (r == m) {\r
161           deg++;\r
162           childtbl[((deg-1)<<ETW) + x] = i;\r
163         }\r
164         if (r < m) {\r
165           m = r;\r
166           //mintbl_li[x] = i;  mintbl_lv[x] = r;\r
167           minmaxtbl_i[OPT_MIN | OPT_LEFT][x] = i;\r
168           minmaxtbl_v[OPT_MIN | OPT_LEFT][x] = r;\r
169           deg = 1;\r
170           childtbl[((deg-1)<<ETW) + x] = i;\r
171         }\r
172       }\r
173       if (r <= m) degtbl2[((r+ETW)<<ETW)+x]++;\r
174     }\r
175     degtbl[x] = deg;\r
176 \r
177     r = 0;  m = 0;  M = 0;\r
178     //maxtbl_rv[x] = -ETW-1;\r
179     //mintbl_rv[x] = ETW+1;\r
180     minmaxtbl_v[OPT_MAX | OPT_RIGHT][x] = -ETW-1;\r
181     minmaxtbl_v[OPT_MIN | OPT_RIGHT][x] = ETW+1;\r
182     for (i=0; i<ETW; i++) {\r
183       if (getbit(buf,i)==OP) {\r
184         r++;\r
185         if (r >= M) {\r
186           M = r;  \r
187           //maxtbl_ri[x] = i;  maxtbl_rv[x] = r;\r
188           minmaxtbl_i[OPT_MAX | OPT_RIGHT][x] = i;\r
189           minmaxtbl_v[OPT_MAX | OPT_RIGHT][x] = r;\r
190         }\r
191       } else {\r
192         r--;\r
193         if (r <= m) {\r
194           m = r;\r
195           //mintbl_ri[x] = i;  mintbl_rv[x] = r;\r
196           minmaxtbl_i[OPT_MIN | OPT_RIGHT][x] = i;\r
197           minmaxtbl_v[OPT_MIN | OPT_RIGHT][x] = r;\r
198         }\r
199       }\r
200     }\r
201 \r
202     for (i = 0; i < ETW; i++) {\r
203       for (j = -ETW; j <= ETW; j++) {\r
204         childtbl2[j+ETW][i][x] = -1;\r
205       }\r
206     }\r
207 \r
208     for (j=-ETW; j<=ETW; j++) {\r
209       int ith;\r
210       ith = 0;\r
211       r = 0;\r
212       for (i = 0; i < ETW; i++) {\r
213         if (getbit(buf,i)==OP) {\r
214           r++;\r
215         } else {\r
216           r--;\r
217           if (r < j) break;\r
218           if (r == j) {\r
219             ith++;\r
220             childtbl2[j+ETW][ith-1][x] = i;\r
221           }\r
222         }\r
223       }\r
224     }\r
225   }\r
226 \r
227 }\r
228 \r
229 \r
230 int bp_construct(bp *b,int n, pb *B, int opt)\r
231 {\r
232   int i,j,d;\r
233   int m,M,ds;\r
234   int ns,nm;\r
235   byte *sm, *sM;\r
236   byte *sd;\r
237   int *mm, *mM;\r
238   int *md;\r
239   int m_ofs;\r
240   int r; // # of minimum values\r
241 \r
242 #if 0\r
243   if (SB % D != 0) {\r
244     printf("warning: SB=%d should be a multiple of D=%d\n",SB,D);\r
245     // not necessarily?\r
246   }\r
247   if (SB % RRR != 0) {\r
248     printf("warning: SB=%d should be a multiple of RRR=%d\n",SB,RRR);\r
249   }\r
250 #endif\r
251 \r
252   b->B = B;\r
253   b->n = n;\r
254   b->opt = opt;\r
255   b->idx_size = 0;\r
256   b->sm = NULL;\r
257   b->sM = NULL;\r
258   b->sd = NULL;\r
259   b->mm = NULL;\r
260   b->mM = NULL;\r
261   b->md = NULL;\r
262   b->da_leaf = NULL;\r
263   b->da_inorder = NULL;\r
264   b->da_postorder = NULL;\r
265   b->da_dfuds_leaf = NULL;\r
266   mymalloc(b->da,1,0);\r
267   darray_construct(b->da,n,B, opt & OPT_FAST_PREORDER_SELECT);\r
268   b->idx_size += b->da->idx_size;\r
269   printf("preorder rank/select table: %d bytes (%1.2f bpc)\n",b->da->idx_size,(double)b->da->idx_size*8/n);\r
270 \r
271   make_matchtbl();\r
272 \r
273   ns = (n+SB-1)/SB;\r
274   mymalloc(sm, ns, 0);  b->idx_size += ns * sizeof(*sm);\r
275   mymalloc(sM, ns, 0);  b->idx_size += ns * sizeof(*sM);\r
276   b->sm = sm;\r
277   b->sM = sM;\r
278   if (opt & OPT_DEGREE) {\r
279     mymalloc(sd, ns, 0);  b->idx_size += ns * sizeof(*sd);\r
280     b->sd = sd;\r
281     printf("SB degree table: %d bytes (%1.2f bpc)\n",ns * sizeof(*sd), (double)ns * sizeof(*sd) * 8/n);\r
282   }\r
283   printf("SB table: %d bytes (%1.2f bpc)\n",ns * sizeof(*sm) * 2, (double)ns * sizeof(*sm)*2 * 8/n);\r
284 \r
285   for (i=0; i<n; i++) {\r
286     if (i % SB == 0) {\r
287       ds = depth(b,i);\r
288       m = M = ds;\r
289       r = 1;\r
290     } else {\r
291       d = depth(b,i);\r
292       if (d == m) r++;\r
293       if (d < m) {\r
294         m = d;\r
295         r = 1;\r
296       }\r
297       if (d > M) M = d;\r
298     }\r
299     if (i % SB == SB-1 || i==n-1) {\r
300       ds = depth(b,(i/SB)*SB-1);\r
301       if (m - ds + SB < 0 || m - ds + SB > 255) {\r
302         printf("error m=%d ds=%d\n",m,ds);\r
303       }\r
304       if (M - ds + 1 < 0 || M - ds + 1 > 255) {\r
305         printf("error M=%d ds=%d\n",M,ds);\r
306       }\r
307       sm[i/SB] = m - ds + SB;\r
308       sM[i/SB] = M - ds + 1;\r
309       if (opt & OPT_DEGREE) sd[i/SB] = r;\r
310     }\r
311   }\r
312 \r
313 #if 0\r
314   printf("sd: ");\r
315   for (i=0;i<n/SB;i++) printf("%d ",sd[i]);\r
316   printf("\n");\r
317 #endif\r
318 \r
319 \r
320   nm = (n+MB-1)/MB;\r
321   m_ofs = 1 << blog(nm-1);\r
322   b->m_ofs = m_ofs;\r
323 \r
324   mymalloc(mm, nm + m_ofs, 0);  b->idx_size += (nm+m_ofs) * sizeof(*mm);\r
325   mymalloc(mM, nm + m_ofs, 0);  b->idx_size += (nm+m_ofs) * sizeof(*mM);\r
326   b->mm = mm;\r
327   b->mM = mM;\r
328   if (opt & OPT_DEGREE) {\r
329     mymalloc(md, nm + m_ofs, 0);  b->idx_size += (nm+m_ofs) * sizeof(*md);\r
330     b->md = md;\r
331     printf("MB degree table: %d bytes (%1.2f bpc)\n",(nm+m_ofs) * sizeof(*md), (double)(nm+m_ofs) * sizeof(*md) * 8/n);\r
332   }\r
333   printf("MB table: %d bytes (%1.2f bpc)\n",(nm+m_ofs) * sizeof(*mm) * 2, (double)(nm+m_ofs) * sizeof(*mm)*2 * 8/n);\r
334 \r
335   for (i=0; i<n; i++) {\r
336     d = depth(b,i);\r
337     if (i % MB == 0) {\r
338       m = M = d;\r
339       r = 1;\r
340     } else {\r
341       if (d == m) r++;\r
342       if (d < m) {\r
343         m = d;\r
344         r = 1;\r
345       }\r
346       if (d > M) M = d;\r
347     }\r
348     if (i % MB == MB-1 || i==n-1) {\r
349       mm[m_ofs+ i/MB] = m;\r
350       mM[m_ofs+ i/MB] = M;\r
351       if (opt & OPT_DEGREE) md[m_ofs+ i/MB] = r;\r
352     }\r
353   }\r
354   \r
355   for (j=m_ofs-1; j > 0; j--) {\r
356     m = 0;\r
357     if (j*2 < nm + m_ofs) m = mm[j*2];\r
358     if (j*2+1 < nm + m_ofs) m = min(m,mm[j*2+1]);\r
359     M = 0;\r
360     if (j*2 < nm + m_ofs) M = mM[j*2];\r
361     if (j*2+1 < nm + m_ofs) M = max(M,mM[j*2+1]);\r
362     mm[j] = m;  mM[j] = M;\r
363     if (opt & OPT_DEGREE) {\r
364       d = 0;\r
365       if (j*2 < nm + m_ofs) d = md[j*2];\r
366       if (j*2+1 < nm + m_ofs) {\r
367         if (mm[j*2] == mm[j*2+1]) d += md[j*2+1];\r
368         if (mm[j*2] > mm[j*2+1]) d = md[j*2+1];\r
369       }\r
370       md[j] = d;\r
371     }\r
372   }\r
373   mm[0] = -1;\r
374   mM[0] = mM[1];\r
375   if (opt & OPT_DEGREE) {\r
376     md[0] = -1;\r
377   }\r
378 \r
379 \r
380 #if 0\r
381   printf("md: ");\r
382   for (i=0;i<m_ofs + n/MB;i++) printf("%d ",md[i]);\r
383   printf("\n");\r
384 #endif\r
385 \r
386   if (opt & OPT_LEAF) {\r
387     mymalloc(b->da_leaf,1,0);\r
388     darray_pat_construct(b->da_leaf, n, B, 2, 0x2, opt & OPT_FAST_LEAF_SELECT);\r
389     printf("leaf rank/select table: %d bytes (%1.2f bpc)\n",b->da_leaf->idx_size,(double)b->da_leaf->idx_size*8/n);\r
390     b->idx_size += b->da_leaf->idx_size;  \r
391   } else {\r
392     b->da_leaf = NULL;\r
393   }\r
394 \r
395   if (opt & OPT_INORDER) {\r
396     mymalloc(b->da_inorder,1,0);\r
397     darray_pat_construct(b->da_inorder, n, B, 2, 0x1, opt & OPT_FAST_INORDER_SELECT);\r
398     printf("inorder rank/select table: %d bytes (%1.2f bpc)\n",b->da_inorder->idx_size,(double)b->da_inorder->idx_size*8/n);\r
399     b->idx_size += b->da_inorder->idx_size;\r
400   } else {\r
401     b->da_inorder = NULL;\r
402   }\r
403 \r
404   if (opt & OPT_FAST_POSTORDER_SELECT) {\r
405     mymalloc(b->da_postorder,1,0);\r
406     darray_pat_construct(b->da_postorder, n, B, 1, 0x0, (opt & OPT_FAST_POSTORDER_SELECT) | OPT_NO_RANK);\r
407     printf("postorder rank/select table: %d bytes (%1.2f bpc)\n",b->da_postorder->idx_size,(double)b->da_postorder->idx_size*8/n);\r
408     b->idx_size += b->da_postorder->idx_size;\r
409   } else {\r
410     b->da_postorder = NULL;\r
411   }\r
412 \r
413   if (opt & OPT_DFUDS_LEAF) {\r
414     mymalloc(b->da_dfuds_leaf,1,0);\r
415     darray_pat_construct(b->da_dfuds_leaf, n, B, 2, 0x0, opt & OPT_FAST_DFUDS_LEAF_SELECT);\r
416     printf("dfuds leaf rank/select table: %d bytes (%1.2f bpc)\n",b->da_dfuds_leaf->idx_size,(double)b->da_dfuds_leaf->idx_size*8/n);\r
417     b->idx_size += b->da_dfuds_leaf->idx_size;\r
418   } else {\r
419     b->da_dfuds_leaf = NULL;\r
420   }\r
421 \r
422   return 0;\r
423 }\r
424 \r
425 // destroyTree: frees the memory of tree.\r
426 void destroyTree(bp *b) {\r
427    if (!b) return; // nothing to free\r
428 \r
429    destroyDarray(b->da); // destroys da data structure\r
430    if (b->da) free(b->da);     \r
431    \r
432    if (b->sm) free(b->sm);\r
433    if (b->sM) free(b->sM);\r
434    if (b->sd) free(b->sd);\r
435    if (b->mm) free(b->mm);\r
436    if (b->mM) free(b->mM);\r
437    if (b->md) free(b->md);\r
438    \r
439    destroyDarray(b->da_leaf);\r
440    if (b->da_leaf) free(b->da_leaf);\r
441    \r
442    destroyDarray(b->da_inorder);\r
443    if (b->da_inorder) free(b->da_inorder);\r
444    \r
445    destroyDarray(b->da_postorder);\r
446    if (b->da_postorder) free(b->da_postorder);\r
447    \r
448    destroyDarray(b->da_dfuds_leaf);\r
449    if (b->da_dfuds_leaf) free(b->da_dfuds_leaf);\r
450 }\r
451 \r
452 \r
453 // saveTree: saves parentheses data structure to file\r
454 // By Diego Arroyuelo\r
455 void saveTree(bp *b, FILE *fp) {\r
456 \r
457    if (fwrite(&(b->n), sizeof(int), 1, fp) != 1) {\r
458       printf("Error: cannot save number of parentheses to file\n");\r
459       exit(1);\r
460    }\r
461 \r
462    if (fwrite(b->B, sizeof(pb), (b->n+D-1)/D, fp) != ((b->n+D-1)/D)) {\r
463       printf("Error: cannot save parentheses sequence to file\n");\r
464       exit(1);\r
465    }\r
466 \r
467    if (fwrite(&(b->opt), sizeof(int), 1, fp) != 1) {\r
468       printf("Error: cannot save opt in parentheses to file\n");\r
469       exit(1);\r
470    }\r
471 }\r
472 \r
473 // loadTree: load parentheses data structure from file\r
474 // By Diego Arroyuelo\r
475 void loadTree(bp *b, FILE *fp) {\r
476 \r
477    pb *B;\r
478    int n, opt;\r
479 \r
480    if (fread(&n, sizeof(int), 1, fp) != 1) {\r
481       printf("Error: cannot read number of parentheses from file\n");\r
482       exit(1);\r
483    }\r
484 \r
485    mymalloc(B,(n+D-1)/D,0);\r
486    \r
487    if (fread(B, sizeof(pb), (n+D-1)/D, fp) != ((n+D-1)/D)) {\r
488       printf("Error: cannot read parentheses sequence from file\n");\r
489       exit(1);\r
490    }\r
491 \r
492    if (fread(&opt, sizeof(int), 1, fp) != 1) {\r
493       printf("Error: cannot read opt in parentheses from file\n");\r
494       exit(1);\r
495    }\r
496    \r
497    bp_construct(b, n, B, opt); \r
498    \r
499 }\r
500 \r
501 \r
502 \r
503 int naive_fwd_excess(bp *b,int s, int rel)\r
504 {\r
505   int i,v,n;\r
506   pb *B;\r
507   n = b->n;  B = b->B;\r
508   v = 0;\r
509   for (i=s+1; i<n; i++) {\r
510     if (getbit(B,i)==OP) {\r
511       v++;\r
512     } else {\r
513       v--;\r
514     }\r
515     if (v == rel) return i;\r
516   }\r
517   return -1;\r
518 }\r
519 \r
520 int naive_bwd_excess(bp *b,int s, int rel)\r
521 {\r
522   int i,v;\r
523   pb *B;\r
524   B = b->B;\r
525   v = 0;\r
526   for (i=s; i>=0; i--) {\r
527     if (getbit(B,i)==OP) {\r
528       v--;\r
529     } else {\r
530       v++;\r
531     }\r
532     if (v == rel) return i-1;\r
533   }\r
534   return -2;\r
535 }\r
536 \r
537 int naive_search_SB_l(bp *b, int i, int rel)\r
538 {\r
539   int il,v;\r
540 \r
541   il = (i / SB) * SB;\r
542   for (; i>=il; i--) {\r
543     if (getbit(b->B,i)==OP) {\r
544       rel++;\r
545     } else {\r
546       rel--;\r
547     }\r
548     if (rel == 0) return i-1;\r
549   }\r
550   if (i < 0) return -2;\r
551   return -3;\r
552 }\r
553 \r
554 int naive_rmq(bp *b, int s, int t,int opt)\r
555 {\r
556   int d,i,dm,im;\r
557 \r
558   if (opt & OPT_RIGHT) {\r
559     d = dm = depth(b,t);  im = t;\r
560     i = t-1;\r
561     while (i >= s) {\r
562       if (getbit(b->B,i+1)==CP) {\r
563         d++;\r
564         if (opt & OPT_MAX) {\r
565           if (d > dm) {\r
566             dm = d;  im = i;\r
567           }\r
568         }\r
569       } else {\r
570         d--;\r
571         if (!(opt & OPT_MAX)) {\r
572           if (d < dm) {\r
573             dm = d;  im = i;\r
574           }\r
575         }\r
576       }\r
577       i--;\r
578     }\r
579   } else {\r
580     d = dm = depth(b,s);  im = s;\r
581     i = s+1;\r
582     while (i <= t) {\r
583       if (getbit(b->B,i)==OP) {\r
584         d++;\r
585         if (opt & OPT_MAX) {\r
586           if (d > dm) {\r
587             dm = d;  im = i;\r
588           }\r
589         }\r
590       } else {\r
591         d--;\r
592         if (!(opt & OPT_MAX)) {\r
593           if (d < dm) {\r
594             dm = d;  im = i;\r
595           }\r
596         }\r
597       }\r
598       i++;\r
599     }\r
600   }\r
601   return im;\r
602 }\r
603 \r
604 int root_node(bp *b)\r
605 {\r
606   return 0;\r
607 }\r
608 \r
609 \r
610 int rank_open(bp *b, int s)\r
611 {\r
612   return darray_rank(b->da,s);\r
613 }\r
614 \r
615 int rank_close(bp *b, int s)\r
616 {\r
617   return s+1 - darray_rank(b->da,s);\r
618 }\r
619 \r
620 int select_open(bp *b, int s)\r
621 {\r
622   if (b->opt & OPT_FAST_PREORDER_SELECT) {\r
623     return darray_select(b->da,s,1);\r
624   } else {\r
625     return darray_select_bsearch(b->da,s,getpat_preorder);\r
626   }\r
627 }\r
628 \r
629 int select_close(bp *b, int s)\r
630 {\r
631   if (b->opt & OPT_FAST_POSTORDER_SELECT) {\r
632     return darray_pat_select(b->da_postorder,s,getpat_postorder);\r
633   } else {\r
634     return postorder_select_bsearch(b,s);\r
635   }\r
636 }\r
637 \r
638 ///////////////////////////////////////////\r
639 //  find_close(bp *b,int s)\r
640 //    returns the matching close parenthesis of s\r
641 ///////////////////////////////////////////\r
642 int find_close(bp *b,int s)\r
643 {\r
644   return fwd_excess(b,s,-1);\r
645 }\r
646 \r
647 ///////////////////////////////////////////\r
648 //  find_open(bp *b,int s)\r
649 //    returns the matching open parenthesis of s\r
650 ///////////////////////////////////////////\r
651 int find_open(bp *b,int s)\r
652 {\r
653   int r;\r
654   r = bwd_excess(b,s,0);\r
655   if (r >= -1) return r+1;\r
656   return -1;\r
657 }\r
658 \r
659 ///////////////////////////////////////////\r
660 //  parent(bp *b,int s)\r
661 //    returns the parent of s\r
662 //            -1 if s is the root\r
663 ///////////////////////////////////////////\r
664 int parent(bp *b,int s)\r
665 {\r
666   int r;\r
667   r = bwd_excess(b,s,-2);\r
668   if (r >= -1) return r+1;\r
669   return -1;\r
670 }\r
671 \r
672 int enclose(bp *b,int s)\r
673 {\r
674   return parent(b,s);\r
675 }\r
676 \r
677 ///////////////////////////////////////////\r
678 //  level_ancestor(bp *b,int s,int d)\r
679 //    returns the ancestor of s with relative depth d (d < 0)\r
680 //            -1 if no such node\r
681 ///////////////////////////////////////////\r
682 int level_ancestor(bp *b,int s,int d)\r
683 {\r
684   int r;\r
685   r = bwd_excess(b,s,d-1);\r
686   if (r >= -1) return r+1;\r
687   return -1;\r
688 }\r
689 \r
690 ///////////////////////////////////////////\r
691 //  lca(bp *b, int s, int t)\r
692 //    returns the lowest common ancestor of s and t\r
693 ///////////////////////////////////////////\r
694 int lca(bp *b, int s, int t)\r
695 {\r
696   return parent(b,rmq(b,s,t,0)+1);\r
697 }\r
698 \r
699 \r
700 ///////////////////////////////////////////\r
701 //  preorder_rank(bp *b,int s)\r
702 //    returns the preorder (>= 1) of node s (s >= 0)\r
703 ///////////////////////////////////////////\r
704 int preorder_rank(bp *b,int s)\r
705 {\r
706   return darray_rank(b->da,s);\r
707 }\r
708 \r
709 ///////////////////////////////////////////\r
710 //  preorder_select(bp *b,int s)\r
711 //    returns the node with preorder s (s >= 1)\r
712 //            -1 if no such node\r
713 ///////////////////////////////////////////\r
714 int preorder_select(bp *b,int s)\r
715 {\r
716   //  no error handling\r
717   if (b->opt & OPT_FAST_PREORDER_SELECT) {\r
718     return darray_select(b->da,s,1);\r
719   } else {\r
720     return darray_select_bsearch(b->da,s,getpat_preorder);\r
721   }\r
722 }\r
723 \r
724 ///////////////////////////////////////////\r
725 //  postorder_rank(bp *b,int s)\r
726 //    returns the postorder (>= 1) of node s (s >= 0)\r
727 //            -1 if s-th bit is not OP\r
728 ///////////////////////////////////////////\r
729 int postorder_rank(bp *b,int s)\r
730 {\r
731   int t;\r
732   if (inspect(b,s) == CP) return -1;\r
733   t = find_close(b,s);\r
734   //  return t+1 - darray_rank(b->da,t);\r
735   return rank_close(b,t);\r
736 }\r
737 \r
738 int postorder_select_bsearch(bp *b,int s)\r
739 {\r
740   int l,r,m;\r
741 \r
742   if (s == 0) return -1;\r
743 \r
744   if (s > b->da->n - b->da->m) {\r
745     return -1;\r
746   }\r
747   l = 0;  r = b->da->n - 1;\r
748 \r
749   while (l < r) {\r
750     m = (l+r)/2;\r
751     //printf("m=%d rank=%d s=%d\n",m,m+1 - darray_rank(b->da,m),s);\r
752     if (m+1 - darray_rank(b->da,m) >= s) {\r
753       r = m;\r
754     } else {\r
755       l = m+1;\r
756     }\r
757   }\r
758   return l;\r
759 }\r
760 \r
761 ///////////////////////////////////////////\r
762 //  postorder_select(bp *b,int s)\r
763 //    returns the position of CP of the node with postorder s (>= 1)\r
764 ///////////////////////////////////////////\r
765 int postorder_select(bp *b,int s)\r
766 {\r
767 #if 0\r
768   if (b->opt & OPT_FAST_POSTORDER_SELECT) {\r
769     return darray_pat_select(b->da_postorder,s,getpat_postorder);\r
770   } else {\r
771     return postorder_select_bsearch(b->da,s);\r
772   }\r
773 #else\r
774   return select_close(b,s);\r
775 #endif\r
776 }\r
777 \r
778 ///////////////////////////////////////////\r
779 //  leaf_rank(bp *b,int s)\r
780 //    returns the number of leaves to the left of s\r
781 ///////////////////////////////////////////\r
782 int leaf_rank(bp *b,int s)\r
783 {\r
784   if ((b->opt & OPT_LEAF) == 0) {\r
785     printf("leaf_rank: error!!!   not supported\n");\r
786     return -1;\r
787   }\r
788   if (s >= b->n-1) {\r
789     s = b->n-2;\r
790   }\r
791   return darray_pat_rank(b->da_leaf,s,getpat_leaf);\r
792 }\r
793 \r
794 ///////////////////////////////////////////\r
795 //  leaf_select(bp *b,int s)\r
796 //    returns the position of s-th leaf\r
797 ///////////////////////////////////////////\r
798 int leaf_select(bp *b,int s)\r
799 {\r
800   if ((b->opt & OPT_LEAF) == 0) {\r
801     printf("leaf_select: error!!!   not supported\n");\r
802     return -1;\r
803   }\r
804   if (s > b->da_leaf->m) return -1;\r
805   if (b->opt & OPT_FAST_LEAF_SELECT) {\r
806     return darray_pat_select(b->da_leaf,s,getpat_leaf);\r
807   } else {\r
808     return darray_select_bsearch(b->da_leaf,s,getpat_leaf);\r
809   }\r
810 }\r
811 \r
812 \r
813 ///////////////////////////////////////////\r
814 //  inorder_rank(bp *b,int s)\r
815 //    returns the number of ")("  (s >= 0)\r
816 ///////////////////////////////////////////\r
817 int inorder_rank(bp *b,int s)\r
818 {\r
819   if ((b->opt & OPT_INORDER) == 0) {\r
820     printf("inorder_rank: error!!!   not supported\n");\r
821     return -1;\r
822   }\r
823   if (s >= b->n-1) {\r
824     s = b->n-2;\r
825   }\r
826   return darray_pat_rank(b->da_inorder,s,getpat_inorder);\r
827 }\r
828 \r
829 ///////////////////////////////////////////\r
830 //  inorder_select(bp *b,int s)\r
831 //    returns the s-th position of ")("  (s >= 1)\r
832 ///////////////////////////////////////////\r
833 int inorder_select(bp *b,int s)\r
834 {\r
835   if ((b->opt & OPT_INORDER) == 0) {\r
836     printf("inorder_select: error!!!   not supported\n");\r
837     return -1;\r
838   }\r
839   if (b->opt & OPT_FAST_INORDER_SELECT) {\r
840     return darray_pat_select(b->da_inorder,s,getpat_inorder);\r
841   } else {\r
842     return darray_select_bsearch(b->da_inorder,s,getpat_inorder);\r
843   }\r
844 }\r
845 \r
846 ///////////////////////////////////////////\r
847 //  leftmost_leaf(bp *b, int s)\r
848 ///////////////////////////////////////////\r
849 int leftmost_leaf(bp *b, int s)\r
850 {\r
851   if ((b->opt & OPT_LEAF) == 0) {\r
852     printf("leftmost_leaf: error!!!   not supported\n");\r
853     return -1;\r
854   }\r
855   return leaf_select(b,leaf_rank(b,s)+1);\r
856 }\r
857 \r
858 ///////////////////////////////////////////\r
859 //  rightmost_leaf(bp *b, int s)\r
860 ///////////////////////////////////////////\r
861 int rightmost_leaf(bp *b, int s)\r
862 {\r
863   int t;\r
864   if ((b->opt & OPT_LEAF) == 0) {\r
865     printf("leftmost_leaf: error!!!   not supported\n");\r
866     return -1;\r
867   }\r
868   t = find_close(b,s);\r
869   return leaf_select(b,leaf_rank(b,t));\r
870 }\r
871 \r
872 \r
873 \r
874 ///////////////////////////////////////////\r
875 //  inspect(bp *b, int s)\r
876 //    returns OP (==1) or CP (==0) at s-th bit (0 <= s < n)\r
877 ///////////////////////////////////////////\r
878 int inspect(bp *b, int s)\r
879 {\r
880   if (s < 0 || s >= b->n) {\r
881     printf("inspect: error s=%d is out of [%d,%d]\n",s,0,b->n-1);\r
882   }\r
883   return getbit(b->B,s);\r
884 }\r
885 \r
886 int isleaf(bp *b, int s)\r
887 {\r
888   if (inspect(b,s) != OP) {\r
889     printf("isleaf: error!!! B[%d] = OP\n",s);\r
890   }\r
891   if (inspect(b,s+1) == CP) return 1;\r
892   else return 0;\r
893 }\r
894 \r
895 \r
896 ///////////////////////////////////////////\r
897 //  subtree_size(bp *b, int s)\r
898 //    returns the number of nodes in the subtree of s\r
899 ///////////////////////////////////////////\r
900 int subtree_size(bp *b, int s)\r
901 {\r
902   return (find_close(b,s) - s + 1) / 2;\r
903 }\r
904 \r
905 ///////////////////////////////////////////\r
906 //  first_child(bp *b, int s)\r
907 //    returns the first child\r
908 //            -1 if s is a leaf\r
909 ///////////////////////////////////////////\r
910 int first_child(bp *b, int s)\r
911 {\r
912   if (inspect(b,s+1) == CP) return -1;\r
913   return s+1;\r
914 }\r
915 \r
916 ///////////////////////////////////////////\r
917 //  next_sibling(bp *b,int s)\r
918 //    returns the next sibling of parent(s)\r
919 //            -1 if s is the last child\r
920 //////////////////////////////////////////\r
921 int next_sibling(bp *b, int s)\r
922 {\r
923   int t;\r
924   t = find_close(b,s)+1;\r
925   if (t >= b->n) {\r
926     printf("next_sibling: error s=%d t=%d\n",s,t);\r
927   }\r
928   if (inspect(b,t) == CP) return -1;\r
929   return t;\r
930 }\r
931 \r
932 ///////////////////////////////////////////\r
933 //  prev_sibling(bp *b,int s)\r
934 //    returns the previous sibling of parent(s)\r
935 //            -1 if s is the first child\r
936 //////////////////////////////////////////\r
937 int prev_sibling(bp *b, int s)\r
938 {\r
939   int t;\r
940   if (s < 0) {\r
941     printf("prev_sibling: error s=%d\n",s);\r
942   }\r
943   if (s == 0) return -1;\r
944   if (inspect(b,s-1) == OP) return -1;\r
945   t = find_open(b,s-1);\r
946   return t;\r
947 }\r
948 \r
949 ///////////////////////////////////////////\r
950 //  deepest_node(bp *b,int s)\r
951 //    returns the first node with the largest depth in the subtree of s\r
952 ///////////////////////////////////////////\r
953 int deepest_node(bp *b,int s)\r
954 {\r
955   int t,m;\r
956   t = find_close(b,s);\r
957   m = rmq(b,s,t, OPT_MAX);\r
958   return m;\r
959 }\r
960 \r
961 ///////////////////////////////////////////\r
962 //  subtree_height(bp *b,int s)\r
963 //    returns the height of the subtree of s\r
964 //            0 if s is a leaf\r
965 ///////////////////////////////////////////\r
966 int subtree_height(bp *b,int s)\r
967 {\r
968   int t;\r
969   t = deepest_node(b,s);\r
970   return depth(b,t) - depth(b,s);\r
971 }\r
972 \r
973 int naive_degree(bp *b, int s)\r
974 {\r
975   int t,d;\r
976   d = 0;\r
977   t = first_child(b,s);\r
978   while (t >= 0) {\r
979     d++;\r
980     t = next_sibling(b,t);\r
981   }\r
982   return d;\r
983 }\r
984 \r
985 ///////////////////////////////////////////\r
986 //  degree(bp *b, int s)\r
987 //    returns the number of children of s\r
988 //            0 if s is a leaf\r
989 ///////////////////////////////////////////\r
990 int degree(bp *b, int s)\r
991 {\r
992   if (b->opt & OPT_DEGREE) {\r
993     return fast_degree(b,s,b->n,0);\r
994   } else {\r
995     return naive_degree(b,s);\r
996   }\r
997 }\r
998 \r
999 int naive_child(bp *b, int s, int d)\r
1000 {\r
1001   int t,i;\r
1002   t = first_child(b,s);\r
1003   for (i = 1; i < d; i++) {\r
1004     if (t == -1) break;\r
1005     t = next_sibling(b,t);\r
1006   }\r
1007   return t;\r
1008 }\r
1009 \r
1010 ///////////////////////////////////////////\r
1011 //  child(bp *b, int s, int d)\r
1012 //    returns the d-th child of s  (1 <= d <= degree(s))\r
1013 //            -1 if no such node\r
1014 ///////////////////////////////////////////\r
1015 int child(bp *b, int s, int d)\r
1016 {\r
1017   int r;\r
1018   if (b->opt & OPT_DEGREE) {\r
1019     //return find_open(b,fast_degree(b,s,b->n,d));\r
1020     if (d==1) return first_child(b,s);\r
1021     r = fast_degree(b,s,b->n,d-1)+1;\r
1022     if (inspect(b,r) == CP) return -1;\r
1023     return r;\r
1024   } else {\r
1025     return naive_child(b,s,d);\r
1026   }\r
1027     \r
1028 }\r
1029 \r
1030 \r
1031 int naive_child_rank(bp *b, int t)\r
1032 {\r
1033   int v,d;\r
1034   d = 0;\r
1035   while (t != -1) {\r
1036     d++;\r
1037     t = prev_sibling(b,t);\r
1038   }\r
1039   return d;\r
1040 }\r
1041 \r
1042 ///////////////////////////////////////////\r
1043 //  child_rank(bp *b, int t)\r
1044 //    returns d if t is the d-th child of the parent of t (d >= 1)\r
1045 //            1 if t is the root\r
1046 ///////////////////////////////////////////\r
1047 int child_rank(bp *b, int t)\r
1048 {\r
1049   int r;\r
1050   if (t == root_node(b)) return 1;\r
1051   if (b->opt & OPT_DEGREE) {\r
1052     r = parent(b,t);\r
1053     return fast_degree(b,r,t,0)+1;\r
1054   } else {\r
1055     return naive_child_rank(b,t);\r
1056   }\r
1057 }\r
1058 \r
1059 \r
1060 \r
1061 ///////////////////////////////////////////\r
1062 //  is_ancestor(bp *b, int s, int t)\r
1063 //     returns 1 if s is an ancestor of t\r
1064 //             0 otherwise\r
1065 ///////////////////////////////////////////\r
1066 int is_ancestor(bp *b, int s, int t)\r
1067 {\r
1068   int v;\r
1069   v = find_close(b,s);\r
1070   if (s <= t && t <= v) return 1;\r
1071   return 0;\r
1072 }\r
1073 \r
1074 ///////////////////////////////////////////\r
1075 //  distance(bp *b, int s, int t)\r
1076 //    returns the length of the shortest path from s to t in the tree\r
1077 ///////////////////////////////////////////\r
1078 int distance(bp *b, int s, int t)\r
1079 {\r
1080   int v,d;\r
1081   v = lca(b,s,t);\r
1082   d = depth(b,v);\r
1083   return (depth(b,s) - d) + (depth(b,t) - d);\r
1084 }\r
1085 \r
1086 ///////////////////////////////////////////\r
1087 //  level_next(bp *b, int d)\r
1088 ///////////////////////////////////////////\r
1089 int level_next(bp *b,int s)\r
1090 {\r
1091   int t;\r
1092   t = fwd_excess(b,s,0);\r
1093   return t;\r
1094 }\r
1095 \r
1096 ///////////////////////////////////////////\r
1097 //  level_prev(bp *b, int d)\r
1098 ///////////////////////////////////////////\r
1099 int level_prev(bp *b,int s)\r
1100 {\r
1101   int t;\r
1102   t = bwd_excess(b,s,0);\r
1103   return t;\r
1104 }\r
1105 \r
1106 ///////////////////////////////////////////\r
1107 //  level_leftmost(bp *b, int d)\r
1108 ///////////////////////////////////////////\r
1109 int level_leftmost(bp *b, int d)\r
1110 {\r
1111   int t;\r
1112   if (d < 1) return -1;\r
1113   if (d == 1) return 0;\r
1114   t = fwd_excess(b,0,d);\r
1115   return t;\r
1116 }\r
1117 \r
1118 ///////////////////////////////////////////\r
1119 //  level_rigthmost(bp *b, int d)\r
1120 ///////////////////////////////////////////\r
1121 int level_rigthmost(bp *b, int d)\r
1122 {\r
1123   int t;\r
1124   if (d < 1) return -1;\r
1125   if (d == 1) return 0;\r
1126   t = bwd_excess(b,0,d-1);\r
1127   return find_open(b,t);\r
1128 }\r
1129 \r
1130 ///////////////////////////////////////////\r
1131 //  leaf_size(bp *b, int s)\r
1132 ///////////////////////////////////////////\r
1133 int leaf_size(bp *b, int s)\r
1134 {\r
1135   int t;\r
1136   if ((b->opt & OPT_LEAF) == 0) {\r
1137     printf("leaf_size: error!!!   not supported\n");\r
1138     return -1;\r
1139   }\r
1140   t = find_close(b,s);\r
1141   return leaf_rank(b,t) - leaf_rank(b,s);\r
1142 }\r