diff --git a/Makefile b/Makefile old mode 100755 new mode 100644 index b7ad423..caeb7ad --- a/Makefile +++ b/Makefile @@ -1,45 +1,72 @@ -# CPPFLAGS=-g3 -Wall -O0 -fPIC -DVERBOSE -CPPFLAGS=-O9 -Wall -DNDEBUG -fPIC - -all: libcompact tests - -doc: - @echo " [DOC] Generating documentation" - @doxygen - -libcompact: - @echo " [MSG] Entering directory src" - @CPPFLAGS="$(CPPFLAGS)" make --no-print-directory -C src - -tests: libcompact - @echo " [MSG] Entering directory tests" - @CPPFLAGS="$(CPPFLAGS)" make --no-print-directory -C tests - -shared_lib: libcompact - @echo " [C++] Compiling shared library" - @g++ -shared $(CPPFLAGS) -w -o lib/libcds.so ./lib/libcds.a - -shared_lib_install: - @cp ./lib/libcds.so /usr/lib - @cp ./lib/libcds.a /usr/lib - @echo " [MSG] Library copied to /usr/lib" - @mkdir -p /usr/include/libcds - @cp -rf ./includes /usr/include/libcds - @echo " [MSG] Headers copied to /usr/include/libcds" +CPP=g++ -clean: - @echo " [MSG] Entering directory src" - @make --no-print-directory -C src clean - @echo " [MSG] Entering directory tests" - @make --no-print-directory -C tests clean - @echo " [CLN] Cleaning docs folder" - @rm -rf docs/* - @touch docs/delete_me - @echo " [CLN] Cleaning lib folder" - @rm -f lib/* - @touch lib/delete_me - @echo " [CLN] Cleaning includes folder" - @rm -f includes/* - @touch includes/delete_me +#CPPFLAGS=-g3 -Wall -O0 -I../includes/ +#CPPFLAGS=-O3 -Wall -DNDEBUG -I../includes/ +INCS=-I../includes/ +LIB=../lib/libcds.a + +OBJECTS= testArray.o testBitSequence.o testSequence.o testQuantile.o testHuffman.o timeSequence.o toArray.o toArray2.o +BIN= testArray testBitSequence testSequence testHuffman timeSequence toArray toArray2 testQuantile + +%.o: %.cpp + @echo " [C++] Compiling $<" + @$(CPP) $(CPPFLAGS) $(INCS) -c $< -o $@ + +all: clean $(OBJECTS) $(BIN) + @echo " [MSG] Done compiling tests" + @echo " [FLG] $(CPPFLAGS)" + +testHuffman: + @echo " [LNK] Building testHuffman" + @$(CPP) $(CPPFLAGS) -o testHuffman testHuffman.o $(LIB) + +testSequence: + @echo " [LNK] Building testSequence" + @$(CPP) $(CPPFLAGS) -o testSequence testSequence.o $(LIB) + +testQuantile: + @echo " [LNK] Building testSequence" + @$(CPP) $(CPPFLAGS) -o testQuantile testQuantile.o $(LIB) + +testBitSequence: + @echo " [LNK] Building testBitSequence" + @$(CPP) $(CPPFLAGS) -o testBitSequence testBitSequence.o $(LIB) + +testArray: + @echo " [LNK] Building testArray" + @$(CPP) $(CPPFLAGS) -o testArray testArray.o $(LIB) + +testTextIndex: + @echo " [LNK] Building testTextIndex" + @$(CPP) $(CPPFLAGS) -o testTextIndex testTextIndex.o $(LIB) +testLCP: + @echo " [LNK] Building testLCP" + @$(CPP) $(CPPFLAGS) -o testLCP testLCP.o $(LIB) + +testNPR: + @echo " [LNK] Building testNPR" + @$(CPP) $(CPPFLAGS) -o testNPR testNPR.o $(LIB) + +toArray2: + @echo " [LNK] Building toArray2" + @$(CPP) $(CPPFLAGS) -o toArray2 toArray2.o $(LIB) + +toArray: + @echo " [LNK] Building toArray" + @$(CPP) $(CPPFLAGS) -o toArray toArray.o $(LIB) + +testSuffixTree: + @echo " [LNK] Building testSuffixTree" + @$(CPP) $(CPPFLAGS) -o testSuffixTree testSuffixTree.o $(LIB) + +timeSequence: + @echo " [LNK] Building timeSequence" + @$(CPP) $(CPPFLAGS) -o timeSequence timeSequence.o $(LIB) + + + +clean: + @echo " [CLN] Cleaning object and binary files" + @rm -f $(OBJECTS) $(BIN) diff --git a/src/Makefile b/src/Makefile index bbcbe34..402e535 100755 --- a/src/Makefile +++ b/src/Makefile @@ -8,7 +8,7 @@ UTILS_OBJ=utils/Array.o utils/libcdsBitString.o utils/cppUtils.o utils/timing.o # OBJECTS FROM cds_static PACKAGE STATIC_MAPPER_OBJ=static/mapper/Mapper.o static/mapper/MapperNone.o static/mapper/MapperCont.o static/mapper/MapperRev.o -STATIC_BITSEQ_OBJ= static/bitsequence/BitSequence.o static/bitsequence/BitSequenceRG.o static/bitsequence/BitSequenceSDArray.o static/bitsequence/sdarraySadakane.o static/bitsequence/BitSequenceDArray.o static/bitsequence/BitSequenceRRR.o static/bitsequence/BitSequenceBuilderRG.o static/bitsequence/BitSequenceBuilderRRR.o static/bitsequence/BitSequenceBuilderSDArray.o static/bitsequence/BitSequenceBuilderDArray.o static/bitsequence/TableOffsetRRR.o +STATIC_BITSEQ_OBJ= static/bitsequence/BitSequence.o static/bitsequence/BitSequenceRG.o static/bitsequence/BitSequenceSDArray.o static/bitsequence/sdarraySadakane.o static/bitsequence/BitSequenceDArray.o static/bitsequence/BitSequenceRRR.o static/bitsequence/BitSequenceBuilderRG.o static/bitsequence/BitSequenceBuilderRRR.o static/bitsequence/BitSequenceBuilderSDArray.o static/bitsequence/BitSequenceBuilderDArray.o static/bitsequence/TableOffsetRRR.o static/bitsequence/BitSequenceRGK.o STATIC_CODER_OBJ=static/coders/huff.o static/coders/HuffmanCoder.o STATIC_SEQ_OBJ=static/sequence/Sequence.o static/sequence/BitmapsSequence.o static/sequence/wt_coder.o static/sequence/wt_coder_binary.o static/sequence/wt_coder_huff.o static/sequence/wt_node.o static/sequence/wt_node_internal.o static/sequence/wt_node_leaf.o static/sequence/WaveletTree.o static/sequence/WaveletTreeNoptrs.o static/sequence/WaveletTreeNoptrsS.o static/sequence/WaveletMatrix.o static/sequence/SequenceGMR.o static/sequence/SequenceGMRChunk.o static/sequence/SequenceBuilderWaveletTreeNoptrs.o static/sequence/SequenceBuilderWaveletTreeNoptrsS.o static/sequence/SequenceBuilderWaveletTree.o static/sequence/SequenceBuilderGMR.o static/sequence/SequenceBuilderGMRChunk.o static/sequence/SequenceAlphPart.o static/sequence/SequenceBuilderStr.o static/sequence/SequenceBuilderAlphPart.o static/sequence/SequenceBuilderWaveletMatrix.o diff --git a/src/static/bitsequence/BitSequenceRGK.cpp b/src/static/bitsequence/BitSequenceRGK.cpp new file mode 100644 index 0000000..a64c6f0 --- /dev/null +++ b/src/static/bitsequence/BitSequenceRGK.cpp @@ -0,0 +1,678 @@ +/* BitSequenceRGK.cpp + Copyright (C) 2005, Rodrigo Gonzalez, Francisco Claude, Roberto Konow + all rights reserved. + + New RANK, SELECT, SELECT-NEXT and SPARSE RANK implementations. + Addaptation to libcds by Francisco Claude + + NEW SELECT_T Operation, 2 times faster select by Roberto Konow + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Stones, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#include +#include +#include +#include +#include +// #include +cds_static::BitSequenceRGK::Builder cds_static::BitSequenceRGK::builder; + +namespace cds_static +{ + ///////////// + //Rank(B,i)// + ///////////// + //_factor = 0 => s=W*lgn + //_factor = P => s=W*P + //Is interesting to notice + //factor=2 => overhead 50% + //factor=3 => overhead 33% + //factor=4 => overhead 25% + //factor=20=> overhead 5% + + + BitSequenceRGK::BitSequenceRGK() { + data=NULL; + // this->owner = true; + this->n=0; + this->factor=0; + } + + BitSequenceRGK::BitSequenceRGK(Builder builder) { + BitString &bs = *builder.bs_; + uint _factor = builder.factor_; + select1sampling = builder.sonesamp_; + select0sampling = builder.szerosamp_; + fastselect0 = builder.fastselect0_; + fastselect1 = builder.fastselect1_; + + const uint * bitarray = bs.getData(); + size_t _n = bs.getLength(); + if(_factor==0) exit(-1); + data=new uint[_n/W+1]; + for(size_t i=0;iowner = true; + this->n=_n; + uint lgn=bits(n-1); + this->factor=_factor; + if (_factor==0) this->factor=lgn; + else this->factor=_factor; + b=32; + s=b*this->factor; + integers = n/W+1; + BuildRank(); + this->length = n; + this->ones = rank1(n-1); + if (fastselect1) { + // cout << "entered here" << endl; + this->Stones = new uint[ones/select1sampling+1]; + Stones[0] = 0; + for (size_t i = 0 ; i <= ones;i+=select1sampling) { + if (i==0) continue; + Stones[i/select1sampling] = this->select1_s(i); + } + } + if (fastselect0) { + this->Stzero = new uint[(n-ones)/select0sampling+1]; + Stzero[0] = 0; + for (size_t i = 0 ; i <= (n-ones);i+=select0sampling) { + if (i==0) continue; + Stzero[i/select0sampling] = this->select0_s((i)); + } + } + } + + + BitSequenceRGK::BitSequenceRGK(const BitString & bs, uint _factor, uint selectsampling) { + const uint * bitarray = bs.getData(); + size_t _n = bs.getLength(); + // cout << _factor << endl; + if(_factor==0) exit(-1); + // cout << "_n/W+1=" << _n/W+1 << endl; + data=new uint[_n/W+1]; + // cout << "_n/W+1=" << _n/W+1 << endl; + for(size_t i=0;iowner = true; + this->n=_n; + uint lgn=bits(n-1); + this->factor=_factor; + if (_factor==0) this->factor=lgn; + else this->factor=_factor; + b=32; + s=b*this->factor; + integers = n/W+1; + BuildRank(); + this->length = n; + this->ones = rank1(n-1); + fastselect0 = true; + fastselect1 = true; + select1sampling = selectsampling; + select0sampling = selectsampling; + if (fastselect1) { + // cout << "entered here" << endl; + this->Stones = new uint[ones/select1sampling+1]; + Stones[0] = 0; + for (size_t i = 0 ; i <= ones;i+=select1sampling) { + if (i==0) continue; + Stones[i/select1sampling] = this->select1_s(i); + } + } + if (fastselect0) { + this->Stzero = new uint[(n-ones)/select0sampling+1]; + Stzero[0] = 0; + for (size_t i = 0 ; i <= (n-ones);i+=select0sampling) { + if (i==0) continue; + Stzero[i/select0sampling] = this->select0_s((i)); + } + } + } + + + + + + BitSequenceRGK::BitSequenceRGK( uint *bitarray, size_t _n, uint _factor,uint selectsampling) { + if(_factor==0) exit(-1); + data=new uint[_n/W+1]; + for(size_t i=0;iowner = true; + this->n=_n; + uint lgn=bits(n-1); + this->factor=_factor; + if (_factor==0) this->factor=lgn; + else this->factor=_factor; + b=32; + s=b*this->factor; + integers = n/W+1; + BuildRank(); + this->length = n; + this->ones = rank1(n-1); + fastselect0 = true; + fastselect1 = true; + select1sampling = selectsampling; + select0sampling = selectsampling; + if (fastselect1) { + // cout << "entered here" << endl; + this->Stones = new uint[ones/select1sampling+1]; + Stones[0] = 0; + for (size_t i = 0 ; i <= ones;i+=select1sampling) { + if (i==0) continue; + Stones[i/select1sampling] = this->select1_s(i); + } + } + if (fastselect0) { + this->Stzero = new uint[(n-ones)/select0sampling+1]; + Stzero[0] = 0; + for (size_t i = 0 ; i <= (n-ones);i+=select0sampling) { + if (i==0) continue; + Stzero[i/select0sampling] = this->select0_s((i)); + } + } + } + + BitSequenceRGK::~BitSequenceRGK() { + delete [] Rs; + delete [] data; + if (fastselect1) + delete [] Stones; + if (fastselect0) + delete [] Stzero; + } + + size_t BitSequenceRGK::select1_t(size_t x) const { + if(x>ones) return (uint)(-1); + uint pos = (x/select1sampling); + register uint bits_restantes = 0; + uint r = Stones[pos]/s; + uint ini = 0; + if (s < select1sampling) { + size_t incr = 1; + while(Rs[r+incr] < x) { + incr = incr*2; + if (r+incr > n/s) + break; + } + r = r+incr/2-1; + while(Rs[r+1] < x) { + r = r+1; + if (r >= n/s) { + r=r-1; + break; + } + } + } + if (pos !=0) { + if (Stones[pos] >= r*s) { + ini = Stones[pos]+1; + bits_restantes = x - pos*select1sampling; + } else { + // cout << "here2!" << endl; + ini = r*factor*W; + bits_restantes = x-Rs[r]; + } + } else{ + bits_restantes = x; + ini = 0; + } + uint posini = ini/32; + uint dataj = data[posini]; + dataj = dataj >> ini%32; + uint ones = __builtin_popcount(dataj); + while (ones < bits_restantes) { + bits_restantes-=ones; + posini++; + if (posini > integers) return n; + dataj = data[posini]; + ones = __builtin_popcount(dataj); + ini = posini*32; + } + uint rankmid = __builtin_popcount(dataj&0xff); + if (rankmid < bits_restantes) { + dataj=dataj>>8; + bits_restantes-=rankmid; + ini+=8; + rankmid = __builtin_popcount(dataj&0xff); + if (rankmid < bits_restantes) { + dataj=dataj>>8; + bits_restantes-=rankmid; + ini+=8; + rankmid = __builtin_popcount(dataj&0xff); + if (rankmid < bits_restantes) { + dataj=dataj>>8; + bits_restantes-=rankmid; + ini+=8; + } + } + } + while (bits_restantes>0) { + if (dataj&1) bits_restantes--; + dataj=dataj>>1; + ini++; + } + return ini-1; +} + + +size_t BitSequenceRGK::select0_t(size_t x) const { + + if(x>n-ones) return (uint)(-1); + uint pos = (x/select0sampling); + register uint bits_restantes = 0; + uint ini = 0; + uint r = Stzero[pos]/s; + if (s < select0sampling) { + size_t incr = 1; + while(((r+incr)*s-Rs[r+incr]) < x) { + incr = incr*2; + if (r+incr > n/s) + break; + } + r = r+incr/2-1; + // cout << "r = \t" << r << endl; + while((((r+1)*s)-Rs[r+1]) < x) { + r = r+1; + if (r >= n/s) { + r=r-1; + break; + } + } + } + if (pos !=0) { + if (Stzero[pos] >= r*s) { + ini = Stzero[pos]+1; + bits_restantes = x - pos*select0sampling; + } else { + ini = r*factor*W; + bits_restantes = x-(r*s-Rs[r]); + } + } else{ + ini = 0; + bits_restantes = x; + } + + uint posini = ini/32; + uint dataj = data[posini]; + uint mod = ini%32; + dataj = dataj >> mod; + uint zeros = 32 - __builtin_popcount(dataj) - mod ; + // cout << "posini \t = " << posini << endl; + + while (zeros < bits_restantes) { + bits_restantes-=zeros; + posini++; + if (posini > integers) return n; + dataj = data[posini]; + zeros = W - __builtin_popcount(dataj); + ini = posini*32; + } + + uint rankmid = 8 - popcount8(dataj); + if (rankmid < bits_restantes) { + dataj=dataj>>8; + bits_restantes-=rankmid; + ini+=8; + rankmid = 8 - popcount8(dataj); + if (rankmid < bits_restantes) { + // cout << "here3" << endl; + dataj=dataj>>8; + bits_restantes-=rankmid; + ini+=8; + rankmid = 8 - popcount8(dataj); + if (rankmid < bits_restantes) { + // cout << "here4" << endl; + dataj=dataj>>8; + bits_restantes-=rankmid; + ini+=8; + } + } + } + while (bits_restantes>0) { + if (dataj%2 == 0 ) bits_restantes--; + dataj=dataj>>1; + ini++; + } + ini--; + if (ini > n+1) return n; + else return ini; +} + + void BitSequenceRGK::BuildRank() { + size_t num_sblock = n/s; + // +1 pues sumo la pos cero + Rs = new uint[num_sblock+5]; + for(uint i=0;i(fastselect0)); + saveValue(f,static_cast(fastselect1)); + + if (fastselect0) { + saveValue(f,select0sampling); + saveValue(f,Stzero,(n-ones)/select0sampling+1); + } + if (fastselect1) { + saveValue(f,Stones,ones/select1sampling+1); + saveValue(f,select1sampling); + } + + } + + BitSequenceRGK * BitSequenceRGK::load(ifstream & f) { + assert(f.good()); + uint type = loadValue(f); + if(type!=BRW32_HDR) { // throw exception + abort(); + } + BitSequenceRGK * ret = new BitSequenceRGK(); + ret->n = loadValue(f); + ret->b = 32; + ret->factor = loadValue(f); + ret->s = ret->b*ret->factor; + ret->integers = (ret->n+1)/W+((ret->n+1)%W!=0?1:0); + ret->data = loadValue(f,ret->integers); + ret->Rs = loadValue(f,ret->n/ret->s+1); + ret->length = ret->n; + ret->ones = ret->rank1(ret->n-1); + ret->fastselect0 = static_cast(loadValue(f)); + ret->fastselect1 = static_cast(loadValue(f)); + if (ret->fastselect0) { + ret->select0sampling = loadValue(f); + ret->Stzero = loadValue(f,(ret->n-ret->ones)/ret->select0sampling+1); + } + if (ret->fastselect1) { + ret->select1sampling = loadValue(f); + ret->Stones = loadValue(f,(ret->ones)/ret->select0sampling+1); + } + return ret; + } + + size_t BitSequenceRGK::SpaceRequirementInBits() const + { + return getSize()*8; // note that his might be wrong + } + + size_t BitSequenceRGK::getSize() const { + size_t total = n/8; // raw bits + total += n/s*4; // rank table + total += sizeof(this); // rest + if (fastselect0) { // select0 table + total += ((n-ones)/select0sampling)*4; + } + if (fastselect1) { // select1 table + total += (ones/select1sampling)*4; + } + return total; + // return /*sizeof(BitSequenceRGK)+*/SpaceRequirementInBits()/8; + } + + size_t BitSequenceRGK::SpaceRequirement() const { + return getSize(); + } + + size_t BitSequenceRGK::selectPrev1(const size_t start) const + { + // returns the position of the previous 1 bit before and including start. + // tuned to 32 bit machine + + uint i = start >> 5; + int offset = (start % W); + uint aux2 = data[i] & (-1u >> (31-offset)); + + if (aux2 > 0) { + if ((aux2&0xFF000000) > 0) return i*W+23+prev_tab[(aux2>>24)&0xFF]; + else if ((aux2&0xFF0000) > 0) return i*W+15+prev_tab[(aux2>>16)&0xFF]; + else if ((aux2&0xFF00) > 0) return i*W+7+prev_tab[(aux2>>8)&0xFF]; + else return i*W+prev_tab[aux2&0xFF]-1; + } + for (uint k=i-1;;k--) { + aux2=data[k]; + if (aux2 > 0) { + if ((aux2&0xFF000000) > 0) return k*W+23+prev_tab[(aux2>>24)&0xFF]; + else if ((aux2&0xFF0000) > 0) return k*W+15+prev_tab[(aux2>>16)&0xFF]; + else if ((aux2&0xFF00) > 0) return k*W+7+prev_tab[(aux2>>8)&0xFF]; + else return k*W+prev_tab[aux2&0xFF]-1; + } + } + return 0; + } + + size_t BitSequenceRGK::selectNext1(const size_t k1) const + { + uint k = (uint)k1; + uint count = k; + uint des,aux2; + des=count%W; + aux2= data[count/W] >> des; + if (aux2 > 0) { + if ((aux2&0xff) > 0) return count+select_tab[aux2&0xff]-1; + else if ((aux2&0xff00) > 0) return count+8+select_tab[(aux2>>8)&0xff]-1; + else if ((aux2&0xff0000) > 0) return count+16+select_tab[(aux2>>16)&0xff]-1; + else {return count+24+select_tab[(aux2>>24)&0xff]-1;} + } + + for (uint i=count/W+1;i 0) { + if ((aux2&0xff) > 0) return i*W+select_tab[aux2&0xff]-1; + else if ((aux2&0xff00) > 0) return i*W+8+select_tab[(aux2>>8)&0xff]-1; + else if ((aux2&0xff0000) > 0) return i*W+16+select_tab[(aux2>>16)&0xff]-1; + else {return i*W+24+select_tab[(aux2>>24)&0xff]-1;} + } + } + return n; + } + size_t BitSequenceRGK::select1(const size_t x1) const { + if (this->fastselect1) { + return this->select1_t(x1); + } else { + return this->select1_s(x1); + } + } + size_t BitSequenceRGK::select0(const size_t x1) const { + if (this->fastselect0) { + return this->select0_t(x1); + } else { + return this->select0_s(x1); + } + } + + size_t BitSequenceRGK::select1_s(const size_t x1) const + { + uint x=x1; + // returns i such that x=rank(i) && rank(i-1)ones) return (uint)(-1); + + //binary search over first level rank structure + uint l=0, r=n/s; + uint mid=(l+r)/2; + uint rankmid = Rs[mid]; + while (l<=r) { + if (rankmid integers) return n; + j = data[left]; + ones = popcount(j); + } + //sequential search using popcount over a char + left=left*b; + rankmid = popcount8(j); + if (rankmid < x) { + j=j>>8; + x-=rankmid; + left+=8; + rankmid = popcount8(j); + if (rankmid < x) { + j=j>>8; + x-=rankmid; + left+=8; + rankmid = popcount8(j); + if (rankmid < x) { + j=j>>8; + x-=rankmid; + left+=8; + } + } + } + + // then sequential search bit a bit + while (x>0) { + if (j&1) x--; + j=j>>1; + left++; + } + return left-1; + } + + size_t BitSequenceRGK::select0_s(const size_t x1) const + { + uint x = (uint)x1; + // returns i such that x=rank_0(i) && rank_0(i-1)n-ones) return (uint)(-1); + + //binary search over first level rank structure + if(x==0) return 0; + uint l=0, r=n/s; + uint mid=(l+r)/2; + uint rankmid = mid*factor*W-Rs[mid]; + while (l<=r) { + if (rankmid integers) return n; + j = data[left]; + zeros = W-popcount(j); + } + //sequential search using popcount over a char + left=left*b; + rankmid = 8-popcount8(j); + if (rankmid < x) { + j=j>>8; + x-=rankmid; + left+=8; + rankmid = 8-popcount8(j); + if (rankmid < x) { + j=j>>8; + x-=rankmid; + left+=8; + rankmid = 8-popcount8(j); + if (rankmid < x) { + j=j>>8; + x-=rankmid; + left+=8; + } + } + } + + // then sequential search bit a bit + while (x>0) { + if (j%2 == 0 ) x--; + j=j>>1; + left++; + } + left--; + if (left > n) return n; + else return left; + } +}; \ No newline at end of file diff --git a/src/static/bitsequence/BitSequenceRGK.h b/src/static/bitsequence/BitSequenceRGK.h new file mode 100644 index 0000000..78fff64 --- /dev/null +++ b/src/static/bitsequence/BitSequenceRGK.h @@ -0,0 +1,167 @@ +/* BitSequenceRG.h + Copyright (C) 2005, Rodrigo Gonzalez, Francisco Claude(2008), Roberto Konow (2014) all rights reserved. + + New RANK, SELECT, SELECT-NEXT and SPARSE RANK implementations. + Adaptation to libcds by Francisco Claude + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#ifndef _STATIC_BITSEQUENCE_RGK_H +#define _STATIC_BITSEQUENCE_RGK_H + +#include +#include +#include + +using namespace cds_utils; + +namespace cds_static +{ + + ///////////// + //Rank(B,i)// + ///////////// + //_factor = 0 => s=W*lgn + //_factor = P => s=W*P + //Is interesting to notice + //factor=2 => overhead 50% + //factor=3 => overhead 33% + //factor=4 => overhead 25% + //factor=20=> overhead 5% + + /** Implementation of Rodrigo Gonzalez et al. practical rank/select solution [1]. + * The interface was adapted. + * + * [1] Rodrigo Gonzalez, Szymon Grabowski, Veli Makinen, and Gonzalo Navarro. + * Practical Implementation of Rank and Select Queries. WEA05. + * + * @author Rodrigo Gonzalez + */ + class BitSequenceRGK : public BitSequence + { + private: + //bool owner; + size_t n,integers; + size_t factor,b,s,select1sampling,select0sampling; + uint *Rs; //superblock array + uint *Stones; // Select Table + uint *Stzero; // Select Table + bool fastselect1,fastselect0; + + + //uso interno para contruir el indice rank + size_t BuildRankSub(size_t ini,size_t fin); + void BuildRank(); //crea indice para rank + BitSequenceRGK(); + size_t SpaceRequirementInBits() const; + size_t SpaceRequirement() const; + + public: + uint *data; + /** Build the BitSequenceRG with a sampling factor factor + * The factor value has to be either 2,3,4 or 20, being the first one the fastest/bigger. + */ + BitSequenceRGK(uint *bitarray, size_t n, uint factor, uint selectsampling=256); + + /** Build the BitSequenceRG with a sampling factor factor + * The factor value has to be either 2,3,4 or 20, being the first one the fastest/bigger. + */ + BitSequenceRGK(const BitString & bs, uint factor, uint selectsampling=256); + + ~BitSequenceRGK(); //destructor + + virtual bool access(const size_t i) const; + //Nivel 1 bin, nivel 2 sec-pop y nivel 3 sec-bit + virtual size_t rank1(const size_t i) const; + size_t select1_t(const size_t x) const; + size_t select1_s(const size_t x) const; + + size_t select0_t(const size_t x) const; + size_t select0_s(const size_t x) const; + // gives the largest index i<=start such that IsBitSet(i)=true + virtual size_t selectPrev1(const size_t start) const; + // gives the smallest index i>=start such that IsBitSet(i)=true + virtual size_t selectNext1(const size_t start) const; + // gives the position of the x:th 1. + virtual size_t select0(size_t x) const; + // gives the position of the x:th 1. + virtual size_t select1(size_t x) const; + virtual size_t getSize() const; + + /*load-save functions*/ + virtual void save(ofstream & f) const; + static BitSequenceRGK * load(ifstream & f); + + class Builder { + public: + bool fastselect1_; + bool fastselect0_; + uint factor_; + uint sonesamp_; + uint szerosamp_; + BitString *bs_; + + Builder() { + fastselect1_ = false; + fastselect0_ = false; + factor_ = 20; + sonesamp_ = 256; + szerosamp_ = 256; + bs_ = NULL; + } + Builder fastselect1() { + fastselect1_ = true; + // cout << "fastselect1_ = " << fastselect1_ << endl; + return *this; + } + Builder fastselect0() { + fastselect0_ = true; + return *this; + } + Builder s1factor(int val) { + fastselect1_ = true; + // cout << "fastselect1_ = " << fastselect1_ << endl; + sonesamp_ = val; + return *this; + } + Builder s0factor(int val) { + fastselect0_ = true; + // cout << "fastselect1_ = " << fastselect1_ << endl; + + szerosamp_ = val; + return *this; + } + Builder bitstring(BitString &bs) { + // cout << "fastselect1_ = " << fastselect1_ << endl; + bs_ = &bs; + return *this; + } + Builder rfactor(int val) { + factor_ = val; + return *this; + } + BitSequenceRGK *build() { + // cout << "fastselect1_ = " << fastselect1_ << endl; + return new BitSequenceRGK(*this); + } + + }; + static Builder builder; + BitSequenceRGK(Builder b); + }; +} +#endif diff --git a/src/static/sequence/WaveletTreeNoptrs.cpp b/src/static/sequence/WaveletTreeNoptrs.cpp index ba65bc9..1c93b1b 100644 --- a/src/static/sequence/WaveletTreeNoptrs.cpp +++ b/src/static/sequence/WaveletTreeNoptrs.cpp @@ -23,6 +23,14 @@ #include +#include +#include +#include +#include +#include + +using namespace std; + namespace cds_static { WaveletTreeNoptrs::WaveletTreeNoptrs(const Array & a, BitSequenceBuilder * bmb, Mapper * am) : Sequence(0) { @@ -332,6 +340,54 @@ namespace cds_static return am->unmap(ret); } + void WaveletTreeNoptrs::TopK(size_t ini, size_t fin, int k, vector &result) { + + //tuples have: length, ini, fin, level + priority_queue > q; + q.push(make_tuple(fin-ini+1, ini, fin, 0, 0)); + + while (!q.empty()) { + auto t = q.top(); + q.pop(); + size_t len = get<0>(t); + size_t left = get<1>(t); + size_t right = get<2>(t); + uint level = get<3>(t); + uint symb = get<4>(t); + + if (level == height) { + if (symb == 0) continue; + result.push_back(am->unmap(symb)); + if (result.size() == (uint)k) return; + continue; + } + + size_t before = 0; + if (OCC[symb] > 0) + before = bitstring[level]->rank1(OCC[symb] - 1); + + size_t rank_before_left = 0; + if (left > 0) + rank_before_left = bitstring[level]->rank1(left-1); + + size_t total_until_right = bitstring[level]->rank1(right); + + size_t num_right = total_until_right - rank_before_left; + if (num_right > 0) { // right + uint symb2 = symb + (1ul << (height - level - 1)); + size_t a = OCC[symb2] + rank_before_left - before; + size_t b = OCC[symb2] + total_until_right - before - 1; + q.push(make_tuple(b - a + 1, a, b, level+1, symb2)); + } + + if (len != num_right) { // left + size_t a = left - rank_before_left + before; + size_t b = right - total_until_right + before; + q.push(make_tuple(b - a + 1, a, b, level+1, symb)); + } + } + } + size_t WaveletTreeNoptrs::rank(uint symbol, size_t pos) const { symbol = am->map(symbol);; diff --git a/src/static/sequence/WaveletTreeNoptrs.h b/src/static/sequence/WaveletTreeNoptrs.h index b3b8b14..188c03c 100644 --- a/src/static/sequence/WaveletTreeNoptrs.h +++ b/src/static/sequence/WaveletTreeNoptrs.h @@ -88,6 +88,8 @@ namespace cds_static virtual void save(ofstream & fp) const; static WaveletTreeNoptrs * load(ifstream & fp); + void TopK(size_t ini, size_t fin, int k, vector &result); + protected: WaveletTreeNoptrs(); diff --git a/src/utils/libcdsBitString.cpp b/src/utils/libcdsBitString.cpp index a1a3311..c5e878b 100644 --- a/src/utils/libcdsBitString.cpp +++ b/src/utils/libcdsBitString.cpp @@ -36,6 +36,7 @@ namespace cds_utils void BitString::initData(const size_t len) { length = len; uintLength = length/W+1; + // cout << "uintlentgh = " << length/W+1 << endl; data = new uint[uintLength]; for(uint i=0;i