Add nextNodeBefore primitive.
[SXSI/XMLTree.git] / libcds / src / static_bitsequence / static_bitsequence_rrr02_light.cpp
1 /* static_bitsequence_rrr02_light.cpp
2  * Copyright (C) 2008, Francisco Claude, all rights reserved.
3  *
4  * static_bitsequence_rrr02_light definition
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  */
21
22 #include <static_bitsequence_rrr02_light.h>
23 using std::min;
24 using std::max;
25 #define VARS_NEEDED uint C_len = len/BLOCK_SIZE_LIGHT + (len%BLOCK_SIZE_LIGHT!=0);\
26 uint C_field_bits = bits(BLOCK_SIZE_LIGHT);\
27 uint O_len = uint_len(1,O_bits_len);\
28 uint C_sampling_len = C_len/sample_rate+2;\
29 uint C_sampling_field_bits = bits(ones);\
30 uint O_pos_len = C_len/sample_rate+1;\
31 uint O_pos_field_bits = bits(O_bits_len);
32
33
34 table_offset * static_bitsequence_rrr02_light::E = NULL;
35
36 static_bitsequence_rrr02_light::static_bitsequence_rrr02_light() {
37   ones=0;
38   len=0;
39   if(E==NULL) E = new table_offset(BLOCK_SIZE_LIGHT);
40   E->use();
41   C = NULL;
42   O = NULL;
43   C_sampling = NULL;
44   O_pos = NULL;
45   sample_rate = DEFAULT_SAMPLING_LIGHT;
46   O_bits_len = 0;
47 }
48
49 static_bitsequence_rrr02_light::static_bitsequence_rrr02_light(uint * bitseq, uint len, uint sample_rate) {
50   ones = 0;
51   this->len = len;
52   if(E==NULL) E = new table_offset(BLOCK_SIZE_LIGHT);
53   E->use();
54   // Table C
55   uint C_len = len/BLOCK_SIZE_LIGHT + (len%BLOCK_SIZE_LIGHT!=0);
56   uint C_field_bits = bits(BLOCK_SIZE_LIGHT);
57   C = new uint[uint_len(C_len,C_field_bits)];
58   for(uint i=0;i<uint_len(C_len,C_field_bits);i++)
59     C[i] = 0;
60   O_bits_len = 0;
61   for(uint i=0;i<C_len;i++) {
62     uint value = popcount(get_var_field(bitseq,i*BLOCK_SIZE_LIGHT,min((uint)len-1,(i+1)*BLOCK_SIZE_LIGHT-1)));
63     assert(value<=BLOCK_SIZE_LIGHT);
64     set_field(C,C_field_bits,i,value);
65     ones += value;
66     O_bits_len += E->get_log2binomial(BLOCK_SIZE_LIGHT,value);
67   }
68   // Table O
69   uint O_len = uint_len(1,O_bits_len);
70   O = new uint[O_len];
71   for(uint i=0;i<O_len;i++)
72     O[i] = 0;
73   uint O_pos = 0;
74   for(uint i=0;i<C_len;i++) {
75     uint value = (ushort)get_var_field(bitseq,i*BLOCK_SIZE_LIGHT,min((uint)len-1,(i+1)*BLOCK_SIZE_LIGHT-1));
76     set_var_field(O,O_pos,O_pos+E->get_log2binomial(BLOCK_SIZE_LIGHT,popcount(value))-1,E->compute_offset((ushort)value));
77     O_pos += E->get_log2binomial(BLOCK_SIZE_LIGHT,popcount(value));
78   }
79   C_sampling = NULL;
80   this->O_pos = NULL;
81   
82   create_sampling(sample_rate);
83 }
84
85 void static_bitsequence_rrr02_light::create_sampling(uint sample_rate) {
86   this->sample_rate = sample_rate;
87 /*  for(uint i=0;i<C_len;i++) {
88     O_bits_len += E->get_log2binomial(BLOCK_SIZE_LIGHT,get_field(C,C_field_bits,i));
89   }*/
90   // Sampling for C
91   uint C_len = len/BLOCK_SIZE_LIGHT + (len%BLOCK_SIZE_LIGHT!=0);
92   uint C_field_bits = bits(BLOCK_SIZE_LIGHT);
93   uint C_sampling_len = C_len/sample_rate+2;
94   uint C_sampling_field_bits = bits(ones);
95   if(C_sampling!=NULL) delete [] C_sampling;
96   C_sampling = new uint[max((uint)1,uint_len(C_sampling_len,C_sampling_field_bits))];
97   for(uint i=0;i<max((uint)1,uint_len(C_sampling_len,C_sampling_field_bits));i++)
98     C_sampling[i] = 0;
99   uint sum = 0;
100   for(uint i=0;i<C_len;i++) {
101     if(i%sample_rate==0)
102       set_field(C_sampling,C_sampling_field_bits,i/sample_rate,sum);
103     sum += get_field(C,C_field_bits,i);
104   }
105   for(uint i=(C_len-1)/sample_rate+1;i<C_sampling_len;i++)
106     set_field(C_sampling,C_sampling_field_bits,i,sum);
107   // Sampling for O (table S) (Code separated from previous construction for readability)
108   uint O_pos_len = C_len/sample_rate+1;
109   uint O_pos_field_bits = bits(O_bits_len);
110   if(O_pos!=NULL) delete [] O_pos;
111   O_pos = new uint[uint_len(O_pos_len,O_pos_field_bits)];
112   for(uint i=0;i<uint_len(O_pos_len,O_pos_field_bits);i++)
113     O_pos[i] = 0;
114   uint pos = 0;
115   for(uint i=0;i<C_len;i++) {
116     if(i%sample_rate==0)
117       set_field(O_pos,O_pos_field_bits,i/sample_rate,pos);
118     pos += E->get_log2binomial(BLOCK_SIZE_LIGHT,get_field(C,C_field_bits,i));
119   }
120 }
121
122 bool static_bitsequence_rrr02_light::access(uint i) {
123   uint C_field_bits = bits(BLOCK_SIZE_LIGHT);
124   uint O_pos_field_bits = bits(O_bits_len);
125   uint nearest_sampled_value = i/BLOCK_SIZE_LIGHT/sample_rate;
126   uint pos_O = get_field(O_pos,O_pos_field_bits,nearest_sampled_value);
127   uint pos = i/BLOCK_SIZE_LIGHT;
128   for(uint k=nearest_sampled_value*sample_rate;k<pos;k++) {
129     uint aux = get_field(C,C_field_bits,k);
130     pos_O += E->get_log2binomial(BLOCK_SIZE_LIGHT,aux);
131   }
132   uint c = get_field(C,C_field_bits,pos);
133   return ((1<<(i%BLOCK_SIZE_LIGHT))&E->short_bitmap(c,get_var_field(O,pos_O,pos_O+E->get_log2binomial(BLOCK_SIZE_LIGHT,c)-1)))!=0;
134 }
135
136 uint static_bitsequence_rrr02_light::rank0(uint i) {
137   if(i+1==0) return 0;
138   return 1+i-rank1(i);
139 }
140
141 uint static_bitsequence_rrr02_light::rank1(uint i) {
142   uint C_field_bits = bits(BLOCK_SIZE_LIGHT);
143   uint C_sampling_field_bits = bits(ones);
144   uint O_pos_field_bits = bits(O_bits_len);
145   if(i+1==0) return 0;
146   uint nearest_sampled_value = i/BLOCK_SIZE_LIGHT/sample_rate;
147   uint sum = get_field(C_sampling,C_sampling_field_bits,nearest_sampled_value);
148   uint pos_O = get_field(O_pos,O_pos_field_bits,nearest_sampled_value);
149   uint pos = i/BLOCK_SIZE_LIGHT;
150   uint k=nearest_sampled_value*sample_rate;
151   if(k%2==1 && k<pos) {
152     uint aux = get_field(C,C_field_bits,k);
153     sum += aux;
154     pos_O += E->get_log2binomial(BLOCK_SIZE_LIGHT,aux);
155     k++;
156   }
157   uchar * a = (uchar *)C;
158   uint mask = 0x0F;
159   a += k/2;
160   while(k<(uint)max(0,(int)pos-1)) {
161     assert(((*a)&mask)==get_field(C,C_field_bits,k));
162     assert((*a)/16==get_field(C,C_field_bits,k+1));
163     sum += ((*a)&mask)+(*a)/16;
164     pos_O += E->get_log2binomial(BLOCK_SIZE_LIGHT,((*a)&mask))+E->get_log2binomial(BLOCK_SIZE_LIGHT,((*a)/16));
165     a++;
166     k+=2;
167   }
168   if(k<pos) {
169     uint aux = get_field(C,C_field_bits,k);
170     sum += aux;
171     pos_O += E->get_log2binomial(BLOCK_SIZE_LIGHT,aux);
172     k++;
173   }
174   uint c = get_field(C,C_field_bits,pos);
175   sum += popcount(((2<<(i%BLOCK_SIZE_LIGHT))-1) & E->short_bitmap(c,get_var_field(O,pos_O,pos_O+E->get_log2binomial(BLOCK_SIZE_LIGHT,c)-1)));
176   return sum;
177 }
178
179 uint static_bitsequence_rrr02_light::select0(uint i) {
180   uint C_len = len/BLOCK_SIZE_LIGHT + (len%BLOCK_SIZE_LIGHT!=0);
181   uint C_field_bits = bits(BLOCK_SIZE_LIGHT);
182   uint C_sampling_len = C_len/sample_rate+2;
183   uint C_sampling_field_bits = bits(ones);
184   uint O_pos_field_bits = bits(O_bits_len);
185   if(i==0) return -1;
186   if(i>len-ones) return len;
187   // Search over partial sums
188   uint start=0;
189   uint end=C_sampling_len-1;
190   uint med, acc=0, pos;
191   while(start<end-1) {
192     med = (start+end)/2;
193     acc = med*sample_rate*BLOCK_SIZE_LIGHT-get_field(C_sampling,C_sampling_field_bits,med);
194     if(acc<i) {
195       if(med==start) break;
196       start=med;
197     }
198     else  {
199       if(end==0) break;
200       end = med-1;
201     }
202   }
203   acc = get_field(C_sampling,C_sampling_field_bits,start);
204   while(start<C_len-1 && acc+sample_rate*BLOCK_SIZE_LIGHT==get_field(C_sampling,C_sampling_field_bits,start+1)) {
205     start++;
206     acc +=sample_rate*BLOCK_SIZE_LIGHT;
207   }
208   acc = start*sample_rate*BLOCK_SIZE_LIGHT-acc;
209   pos = (start)*sample_rate;
210   uint pos_O = get_field(O_pos,O_pos_field_bits,start);
211   // Sequential search over C
212   uint s = 0;
213   for(;pos<C_len;pos++) {
214     s = get_field(C,C_field_bits,pos);
215     if(acc+BLOCK_SIZE_LIGHT-s>=i) break;
216     pos_O += E->get_log2binomial(BLOCK_SIZE_LIGHT,s);
217     acc += BLOCK_SIZE_LIGHT-s;
218   }
219   pos = (pos)*BLOCK_SIZE_LIGHT;
220   // Search inside the block
221   
222   while(acc<i) {
223     uint new_posO = pos_O+E->get_log2binomial(BLOCK_SIZE_LIGHT,s);
224     uint block = E->short_bitmap(s,get_var_field(O,pos_O,new_posO-1));
225     pos_O = new_posO;
226     new_posO = 0;
227     while(acc<i && new_posO<BLOCK_SIZE_LIGHT) {
228       pos++;new_posO++;
229       acc += (((block&1)==0)?1:0);
230       block = block/2;
231     }
232   }
233   pos--;
234   assert(acc==i);
235   assert(rank0(pos)==i);
236   assert(!access(pos));
237   return pos;
238 }
239
240 uint static_bitsequence_rrr02_light::select1(uint i) {
241   uint C_len = len/BLOCK_SIZE_LIGHT + (len%BLOCK_SIZE_LIGHT!=0);
242   uint C_field_bits = bits(BLOCK_SIZE_LIGHT);
243   uint C_sampling_len = C_len/sample_rate+2;
244   uint C_sampling_field_bits = bits(ones);
245   uint O_pos_field_bits = bits(O_bits_len);
246   if(i==0) return -1;
247   if(i>ones) return len;
248   // Search over partial sums
249   uint start=0;
250   uint end=C_sampling_len-1;
251   uint med, acc=0, pos;
252   while(start<end-1) {
253     med = (start+end)/2;
254     acc = get_field(C_sampling,C_sampling_field_bits,med);
255     if(acc<i) {
256       if(med==start) break;
257       start=med;
258     }
259     else  {
260       if(end==0) break;
261       end = med-1;
262     }
263   }
264   acc = get_field(C_sampling,C_sampling_field_bits,start);
265   while(start<C_len-1 && acc==get_field(C_sampling,C_sampling_field_bits,start+1)) start++;
266   pos = (start)*sample_rate;
267   uint pos_O = get_field(O_pos,O_pos_field_bits,start);
268   acc = get_field(C_sampling,C_sampling_field_bits,start);
269   // Sequential search over C
270   uint s = 0;
271   for(;pos<C_len;pos++) {
272     s = get_field(C,C_field_bits,pos);
273     if(acc+s>=i) break;
274     pos_O += E->get_log2binomial(BLOCK_SIZE_LIGHT,s);
275     acc += s;
276   }
277   pos = (pos)*BLOCK_SIZE_LIGHT;
278   //cout << "pos=" << pos << endl;
279   // Search inside the block
280   while(acc<i) {
281     uint new_posO = pos_O+E->get_log2binomial(BLOCK_SIZE_LIGHT,s);
282     uint block = E->short_bitmap(s,get_var_field(O,pos_O,new_posO-1));
283     pos_O = new_posO;
284     new_posO = 0;
285     while(acc<i && new_posO<BLOCK_SIZE_LIGHT) {
286       pos++;new_posO++;
287       acc += (((block&1)!=0)?1:0);
288       block = block/2;
289     }
290     //cout << "i=" << i << " len=" << len << " ones=" << ones << " pos=" << pos << " acc=" << acc << " rank=" << rank1(pos) << endl;
291   }
292   pos--;
293   assert(acc==i);
294   assert(rank1(pos)==i);
295   assert(access(pos));
296   return pos;
297 }
298
299 uint static_bitsequence_rrr02_light::size() {
300   VARS_NEEDED
301   /*cout << "RRR02 SIZE: " << endl;
302   cout << "Default: " << 9*sizeof(uint)+sizeof(uint*)*4 << endl;
303   cout << "Cs:      " << uint_len(C_len,C_field_bits)*sizeof(uint) << endl;
304   cout << "Os:      " << O_len*sizeof(uint) << endl;
305   cout << "CSamp:   " << uint_len(C_sampling_len,C_sampling_field_bits)*sizeof(uint) << endl;
306   cout << "OSamp:   " << uint_len(O_pos_len,O_pos_field_bits)*sizeof(uint) << endl;
307   cout << "E:       " << E->size() << endl;*/
308   uint sum = sizeof(uint)*8;//sizeof(static_bitsequence_rrr02_light);
309   sum += uint_len(C_len,C_field_bits)*sizeof(uint);
310   sum += O_len*sizeof(uint);
311   sum += uint_len(C_sampling_len,C_sampling_field_bits)*sizeof(uint);
312   sum += uint_len(O_pos_len,O_pos_field_bits)*sizeof(uint);
313   //sum += E->size();
314   return sum;
315 }
316
317 static_bitsequence_rrr02_light::~static_bitsequence_rrr02_light() {
318   if(C!=NULL) delete [] C;
319   if(O!=NULL) delete [] O;
320   if(C_sampling!=NULL) delete [] C_sampling;
321   if(O_pos!=NULL) delete [] O_pos;
322   E = E->unuse();
323 }
324
325 int static_bitsequence_rrr02_light::save(FILE * fp) {
326   uint C_len = len/BLOCK_SIZE_LIGHT + (len%BLOCK_SIZE_LIGHT!=0);
327   uint C_field_bits = bits(BLOCK_SIZE_LIGHT);
328   uint O_len = uint_len(1,O_bits_len);
329   uint wr = RRR02_LIGHT_HDR;
330   wr = fwrite(&wr,sizeof(uint),1,fp);
331   wr += fwrite(&len,sizeof(uint),1,fp);
332   wr += fwrite(&ones,sizeof(uint),1,fp);
333   wr += fwrite(&O_bits_len,sizeof(uint),1,fp);
334   wr += fwrite(&sample_rate,sizeof(uint),1,fp);
335   if(wr!=5) return -1;
336   wr = fwrite(C,sizeof(uint),uint_len(C_len,C_field_bits),fp);
337   if(wr!=uint_len(C_len,C_field_bits)) return -1;
338   wr = fwrite(O,sizeof(uint),O_len,fp);
339   if(wr!=O_len) return -1;
340   return 0;
341 }
342
343 static_bitsequence_rrr02_light * static_bitsequence_rrr02_light::load(FILE * fp) {
344   static_bitsequence_rrr02_light * ret = new static_bitsequence_rrr02_light();
345   uint rd = 0, type;
346   rd += fread(&type,sizeof(uint),1,fp);
347   rd += fread(&ret->len,sizeof(uint),1,fp);
348   rd += fread(&ret->ones,sizeof(uint),1,fp);
349   rd += fread(&ret->O_bits_len,sizeof(uint),1,fp);
350   rd += fread(&ret->sample_rate,sizeof(uint),1,fp);
351   uint C_len = ret->len/BLOCK_SIZE_LIGHT + (ret->len%BLOCK_SIZE_LIGHT!=0);
352   uint C_field_bits = bits(BLOCK_SIZE_LIGHT);
353   uint O_len = uint_len(1,ret->O_bits_len);
354   if(rd!=5 || type!=RRR02_LIGHT_HDR) {
355     delete ret;
356     return NULL;
357   }
358   ret->C = new uint[uint_len(C_len,C_field_bits)];
359   rd = fread(ret->C,sizeof(uint),uint_len(C_len,C_field_bits),fp);
360   if(rd!=uint_len(C_len,C_field_bits)) {
361     ret->C=NULL;
362     delete ret;
363     return NULL;
364   }
365   ret->O = new uint[O_len];
366   rd = fread(ret->O,sizeof(uint),O_len,fp);
367   if(rd!=O_len) {
368     ret->O=NULL;
369     delete ret;
370     return NULL;
371   }
372   ret->create_sampling(ret->sample_rate);
373   return ret;
374 }