From cfe07362beeb3e102d4f2e72163e25fd1fc24584 Mon Sep 17 00:00:00 2001 From: Aidan Reilly Date: Tue, 7 Feb 2017 10:31:13 -0500 Subject: [PATCH] Working on debugging errors. Most currently comming from integration of class EList in parallel indexing updates. --- binary_sa_search.h | 4 +- blockwise_sa.h | 243 +++++++++++++++-------------------------------------- diff_sample.h | 18 ++-- ebwt_build.cpp | 3 +- multikey_qsort.h | 45 +++++----- zbox.h | 4 +- 6 files changed, 101 insertions(+), 216 deletions(-) diff --git a/binary_sa_search.h b/binary_sa_search.h index f76ee8a..fd754ce 100644 --- a/binary_sa_search.h +++ b/binary_sa_search.h @@ -27,7 +27,7 @@ template inline TIndexOffU binarySASearch(const TStr& host, TIndexOffU qry, - const std::vector& sa) + const String& sa) { TIndexOffU lLcp = 0, rLcp = 0; // greatest observed LCPs on left and right TIndexOffU l = 0, r = (TIndexOffU)length(sa)+1; // binary-search window @@ -38,7 +38,7 @@ TIndexOffU binarySASearch(const TStr& host, if(m == l) { // Binary-search window has closed: we have an answer if(m > 0 && sa[m-1] == qry) return std::numeric_limits::max(); // qry matches - assert_leq(m, sa.size()); + assert_leq(m, length(sa)); return m; // Return index of right-hand suffix } assert_gt(m, 0); diff --git a/blockwise_sa.h b/blockwise_sa.h index cbc203e..8d0504d 100644 --- a/blockwise_sa.h +++ b/blockwise_sa.h @@ -43,8 +43,6 @@ if(this->verbose()) { \ } #endif -#define EBWTB_CAT (int (2)) - /** * Abstract parent class for blockwise suffix-array building schemes. */ @@ -94,11 +92,11 @@ class BlockwiseSA { * returns the lexicographically-first suffix. */ void resetSuffixItr() { - _itrBucket.clear(); - _itrBucketPos = OFF_MASK; - _itrPushedBackSuffix = OFF_MASK; - reset(); - assert(suffixItrIsReset()); + clear(_itrBucket); + _itrBucketPos = OFF_MASK; + _itrPushedBackSuffix = OFF_MASK; + reset(); + assert(suffixItrIsReset()); } /** @@ -145,7 +143,7 @@ class BlockwiseSA { const bool _sanityCheck; /// whether to perform sanity checks const bool _passMemExc; /// true -> pass on memory exceptions const bool _verbose; /// be talkative - std::vector _itrBucket; /// current bucket + String _itrBucket; /// current bucket TIndexOffU _itrBucketPos;/// offset into current bucket TIndexOffU _itrPushedBackSuffix; /// temporary slot for lookahead ostream& _logger; /// write log messages here @@ -179,7 +177,6 @@ class KarkkainenBlockwiseSA : public InorderBlockwiseSA { KarkkainenBlockwiseSA(const TStr& __text, TIndexOffU __bucketSz, - int __nthreads, uint32_t __dcV, uint32_t __seed = 0, bool __sanityCheck = false, @@ -237,7 +234,7 @@ class KarkkainenBlockwiseSA : public InorderBlockwiseSA { cerr << "Could not open file for writing a reference graph: \"" << fname << "\"" << endl; throw 1; } - const std::vector& bucket = sa->_itrBuckets[tid]; + const EList& bucket = sa->_itrBuckets[tid]; writeU(sa_file, (TIndexOffU)bucket.size(), sa->_bigEndian); for(size_t i = 0; i < bucket.size(); i++) { writeU(sa_file, bucket[i], sa->_bigEndian); @@ -255,14 +252,11 @@ class KarkkainenBlockwiseSA : public InorderBlockwiseSA { // Launch threads if not if(this->_nthreads > 1) { if(_threads.size() == 0) { - _done.resize(length(_sampleSuffs) + 1); - for(std::vector::iterator it = _done.begin(); it != _done.end(); it++) { - *it = false; - } + _done.resize(_sampleSuffs.size() + 1); + _done.fill(false); _itrBuckets.resize(this->_nthreads); for(int tid = 0; tid < this->_nthreads; tid++) { - pair temp; - _tparams.push_back(temp); + _tparams.expand(); _tparams.back().first = this; _tparams.back().second = tid; _threads.push_back(new tthread::thread(nextBlock_Worker, (void*)&_tparams.back())); @@ -302,7 +296,7 @@ class KarkkainenBlockwiseSA : public InorderBlockwiseSA { throw 1; } size_t numSAs = readU(sa_file, _bigEndian); - this->_itrBucket.resize(numSAs); + this->_itrBucket.resizeExact(numSAs); for(size_t i = 0; i < numSAs; i++) { this->_itrBucket[i] = readU(sa_file, _bigEndian); } @@ -316,10 +310,10 @@ class KarkkainenBlockwiseSA : public InorderBlockwiseSA { } /// Defined in blockwise_sa.cpp - virtual void nextBlock(int cur_block, int tid = 0); + virtual void nextBlock(); /// Defined in blockwise_sa.cpp - virtual void qsort(std::vector& bucket); + virtual void qsort(String& bucket); /// Return true iff more blocks are available virtual bool hasMoreBlocks() const { @@ -360,7 +354,7 @@ class KarkkainenBlockwiseSA : public InorderBlockwiseSA { assert(_dc == NULL); if(_dcV != 0) { _dc = new TDC(this->text(), _dcV, this->verbose(), this->sanityCheck()); - _dc->build(this->_nthreads); + _dc->build(); } // Calculate sample suffixes if(this->bucketSz() <= length(this->text())) { @@ -394,13 +388,13 @@ class KarkkainenBlockwiseSA : public InorderBlockwiseSA { int64_t& j, int64_t& k, bool& kSoft, - const std::vector& z); + const String& z); void buildSamples(); - std::vector _sampleSuffs; /// sample suffixes - int _nthreads; /// # of threads + String _sampleSuffs; /// sample suffixes + int n_threadss; /// # of threads TIndexOffU _itrBucketIdx; TIndexOffU _cur; /// offset to 1st elt of next block const uint32_t _dcV; /// difference-cover periodicity @@ -412,7 +406,7 @@ class KarkkainenBlockwiseSA : public InorderBlockwiseSA { bool _bigEndian; /// bigEndian? std::vector _threads; /// thread list std::vector > _tparams; - std::vector > _itrBuckets; /// buckets + std::vector _itrBuckets; /// buckets std::vector _done; /// is a block processed? }; @@ -420,11 +414,11 @@ class KarkkainenBlockwiseSA : public InorderBlockwiseSA { * Qsort the set of suffixes whose offsets are in 'bucket'. */ template -void KarkkainenBlockwiseSA::qsort(std::vector& bucket) { +void KarkkainenBlockwiseSA::qsort(String& bucket) { typedef typename Value::Type TAlphabet; const TStr& t = this->text(); - TIndexOffU *s = &bucket.front(); - TIndexOffU slen = (TIndexOffU)bucket.size(); + TIndexOffU *s = begin(bucket); + TIndexOffU slen = (TIndexOffU)seqan::length(bucket); TIndexOffU len = (TIndexOffU)seqan::length(t); if(_dc != NULL) { // Use the difference cover as a tie-breaker if we have it @@ -451,10 +445,10 @@ void KarkkainenBlockwiseSA::qsort(std::vector& bucket) { * packed means that the array cannot be sorted directly. */ template<> -void KarkkainenBlockwiseSA > >::qsort(std::vector& bucket) { +void KarkkainenBlockwiseSA > >::qsort(String& bucket) { const String >& t = this->text(); - TIndexOffU *s = &bucket.front(); - TIndexOffU slen = (TIndexOffU) bucket.size(); + TIndexOffU *s = begin(bucket); + TIndexOffU slen = (TIndexOffU)seqan::length(bucket); TIndexOffU len = (TIndexOffU)seqan::length(t); if(_dc != NULL) { // Use the difference cover as a tie-breaker if we have it @@ -476,9 +470,9 @@ void KarkkainenBlockwiseSA > >::qsort(std::vector struct BinarySortingParam { const TStr* t; - const std::vector* sampleSuffs; - std::vector bucketSzs; - std::vector bucketReps; + const EList* sampleSuffs; + EList bucketSzs; + EList bucketReps; size_t begin; size_t end; }; @@ -488,10 +482,10 @@ static void BinarySorting_worker(void *vp) { BinarySortingParam* param = (BinarySortingParam*)vp; const TStr& t = *(param->t); - size_t len = length(t); - const std::vector& sampleSuffs = *(param->sampleSuffs); - std::vector& bucketSzs = param->bucketSzs; - std::vector& bucketReps = param->bucketReps; + size_t len = t.length(); + const EList& sampleSuffs = *(param->sampleSuffs); + EList& bucketSzs = param->bucketSzs; + EList& bucketReps = param->bucketReps; ASSERT_ONLY(size_t numBuckets = bucketSzs.size()); size_t begin = param->begin; size_t end = param->end; @@ -527,31 +521,31 @@ void KarkkainenBlockwiseSA::buildSamples() { TIndexOffU bsz = this->bucketSz()-1; // subtract 1 to leave room for sample size_t len = length(this->text()); // Prepare _sampleSuffs array - _sampleSuffs.clear(); + clear(_sampleSuffs); TIndexOffU numSamples = (TIndexOffU)((len/bsz)+1)<<1; // ~len/bsz x 2 assert_gt(numSamples, 0); VMSG_NL("Reserving space for " << numSamples << " sample suffixes"); if(this->_passMemExc) { - _sampleSuffs.reserve(numSamples); //Exact() ?? + reserve(_sampleSuffs, numSamples, Exact()); // Randomly generate samples. Allow duplicates for now. VMSG_NL("Generating random suffixes"); for(size_t i = 0; i < numSamples; i++) { #ifdef BOWTIE_64BIT_INDEX - _sampleSuffs.push_back((TIndexOffU)(_randomSrc.nextU64() % len)); + appendValue(_sampleSuffs, (TIndexOffU)(_randomSrc.nextU64() % len)); #else - _sampleSuffs.push_back((TIndexOffU)(_randomSrc.nextU32() % len)); + appendValue(_sampleSuffs, (TIndexOffU)(_randomSrc.nextU32() % len)); #endif } } else { try { - _sampleSuffs.reserve(numSamples); //Exact()?? + reserve(_sampleSuffs, numSamples, Exact()); // Randomly generate samples. Allow duplicates for now. VMSG_NL("Generating random suffixes"); for(size_t i = 0; i < numSamples; i++) { #ifdef BOWTIE_64BIT_INDEX - _sampleSuffs.push_back((TIndexOffU)(_randomSrc.nextU64() % len)); + appendValue(_sampleSuffs, (TIndexOffU)(_randomSrc.nextU64() % len)); #else - _sampleSuffs.push_back((TIndexOffU)(_randomSrc.nextU32() % len)); + appendValue(_sampleSuffs, (TIndexOffU)(_randomSrc.nextU32() % len)); #endif } } catch(bad_alloc &e) { @@ -593,25 +587,20 @@ void KarkkainenBlockwiseSA::buildSamples() { int limit = 5; // Iterate until all buckets are less than while(--limit >= 0) { - TIndexOffU numBuckets = (TIndexOffU)length(_sampleSuffs)+1; + TIndexOffU numBuckets = (TIndexOffU)_sampleSuffs.size()+1; AutoArray threads(this->_nthreads); - std::vector > tparams; + EList > tparams; for(int tid = 0; tid < this->_nthreads; tid++) { // Calculate bucket sizes by doing a binary search for each // suffix and noting where it lands - //tparams.expand(); - BinarySortingParam temp; - tparams.push_back(temp); + tparams.expand(); try { // Allocate and initialize containers for holding bucket // sizes and representatives. - tparams.back().bucketSzs.resize(numBuckets); - tparams.back().bucketReps.resize(numBuckets); + tparams.back().bucketSzs.resizeExact(numBuckets); + tparams.back().bucketReps.resizeExact(numBuckets); tparams.back().bucketSzs.fillZero(); - //fill(OFF_MASK); - for (std::vector::iterator it = tparams.back().bucketReps.begin(); it != tparams.back().bucketReps.end(); it++) { - *it = OFF_MASK; - } + tparams.back().bucketReps.fill(OFF_MASK); } catch(bad_alloc &e) { if(this->_passMemExc) { throw e; // rethrow immediately @@ -639,8 +628,8 @@ void KarkkainenBlockwiseSA::buildSamples() { } } - std::vector& bucketSzs = tparams[0].bucketSzs; - std::vector& bucketReps = tparams[0].bucketReps; + EList& bucketSzs = tparams[0].bucketSzs; + EList& bucketReps = tparams[0].bucketReps; for(int tid = 1; tid < this->_nthreads; tid++) { for(size_t j = 0; j < numBuckets; j++) { bucketSzs[j] += tparams[tid].bucketSzs[j]; @@ -685,7 +674,7 @@ void KarkkainenBlockwiseSA::buildSamples() { // Add an additional sample from the bucketReps[] // set accumulated in the binarySASearch loop; this // effectively splits the bucket - _sampleSuffs.insert(_sampleSuffs.begin() + TIndexOffU(i + (added++)), bucketReps[i]); + insertValue(_sampleSuffs, TIndexOffU(i + (added++)), bucketReps[i]); } } } @@ -776,9 +765,9 @@ static TIndexOffU lookupSuffixZ( const T& t, TIndexOffU zOff, TIndexOffU off, - const std::vector& z) + const String& z) { - if(zOff < z.size()) { + if(zOff < length(z)) { TIndexOffU ret = z[zOff]; assert_eq(ret, suffixLcp(t, off + zOff, off)); return ret; @@ -798,7 +787,7 @@ bool KarkkainenBlockwiseSA::suffixCmp( int64_t& j, int64_t& k, bool& kSoft, - const std::vector& z) + const String& z) { const TStr& t = this->text(); TIndexOffU len = TIndexOffU(length(t)); @@ -899,27 +888,27 @@ bool KarkkainenBlockwiseSA::suffixCmp( } } - /** - * Retrieve the next block. This is the most performance-critical part - * of the blockwise suffix sorting process. - */ +/** + * Retrieve the next block. This is the most performance-critical part + * of the blockwise suffix sorting process. + */ template void KarkkainenBlockwiseSA::nextBlock(int cur_block, int tid) { -#ifndef NDEBUG + #ifndef NDEBUG if(this->_nthreads > 1) { - assert_lt(tid, (int)this->_itrBuckets.size()); + assert_lt(tid, this->_itrBuckets.size()); } #endif - std::vector& bucket = (this->_nthreads > 1 ? this->_itrBuckets[tid] : this->_itrBucket); + EList& bucket = (this->_nthreads > 1 ? this->_itrBuckets[tid] : this->_itrBucket); { ThreadSafe ts(&_mutex, this->_nthreads > 1); VMSG_NL("Getting block " << (cur_block+1) << " of " << _sampleSuffs.size()+1); } assert(_built); assert_gt(_dcV, 3); - assert_leq(cur_block, (int)_sampleSuffs.size()); + assert_leq(cur_block, _sampleSuffs.size()); const TStr& t = this->text(); - TIndexOffU len = (TIndexOffU)length(t); + TIndexOffU len = (TIndexOffU)t.length(); // Set up the bucket bucket.clear(); TIndexOffU lo = OFF_MASK, hi = OFF_MASK; @@ -933,7 +922,7 @@ void KarkkainenBlockwiseSA::nextBlock(int cur_block, int tid) { assert_eq(0, cur_block); try { if(bucket.capacity() < this->bucketSz()) { - bucket.reserve(len+1); + bucket.reserveExact(len+1); } bucket.resize(len); for(TIndexOffU i = 0; i < len; i++) { @@ -958,7 +947,7 @@ void KarkkainenBlockwiseSA::nextBlock(int cur_block, int tid) { // BTL: Add a +100 fudge factor; there seem to be instances // where a bucket ends up having one more elt than bucketSz() if(bucket.size() < this->bucketSz()+100) { - bucket.reserve(this->bucketSz()+100); + bucket.reserveExact(this->bucketSz()+100); } } catch(bad_alloc &e) { if(this->_passMemExc) { @@ -973,7 +962,7 @@ void KarkkainenBlockwiseSA::nextBlock(int cur_block, int tid) { // Select upper and lower bounds from _sampleSuffs[] and // calculate the Z array up to the difference-cover periodicity // for both. Be careful about first/last buckets. - std::vector zLo(EBWTB_CAT), zHi(EBWTB_CAT); + EList zLo(EBWTB_CAT), zHi(EBWTB_CAT); assert_geq(cur_block, 0); assert_leq((size_t)cur_block, _sampleSuffs.size()); bool first = (cur_block == 0); @@ -986,9 +975,9 @@ void KarkkainenBlockwiseSA::nextBlock(int cur_block, int tid) { } if(!last) { // Not the last bucket - assert_lt(cur_block, (int)_sampleSuffs.size()); + assert_lt(cur_block, _sampleSuffs.size()); hi = _sampleSuffs[cur_block]; - zHi.resize(_dcV); + zHi.resizeExact(_dcV); zHi.fillZero(); assert_eq(zHi[0], 0); calcZ(t, hi, zHi, this->verbose(), this->sanityCheck()); @@ -996,107 +985,13 @@ void KarkkainenBlockwiseSA::nextBlock(int cur_block, int tid) { if(!first) { // Not the first bucket assert_gt(cur_block, 0); - assert_leq(cur_block, (int)_sampleSuffs.size()); + assert_leq(cur_block, _sampleSuffs.size()); lo = _sampleSuffs[cur_block-1]; - zLo.resize(_dcV); + zLo.resizeExact(_dcV); zLo.fillZero(); assert_gt(_dcV, 3); - assert_eq(zLo[0], 0); - calcZ(t, lo, zLo, this->verbose(), this->sanityCheck()); - } - } catch(bad_alloc &e) { - if(this->_passMemExc) { - throw e; // rethrow immediately - } else { - cerr << "Could not allocate a z-array of " << (_dcV * 4) << " bytes" << endl; - cerr << "Please try using a larger number of blocks by specifying a smaller --bmax or" << endl - << "a larger --bmaxdivn" << endl; - throw 1; - } - } - - // This is the most critical loop in the algorithm; this is where - // we iterate over all suffixes in the text and pick out those that - // fall into the current bucket. - // - // This loop is based on the SMALLERSUFFIXES function outlined on - // p7 of the "Fast BWT" paper - // - int64_t kHi = -1, kLo = -1; - int64_t jHi = -1, jLo = -1; - bool kHiSoft = false, kLoSoft = false; - assert_eq(0, bucket.size()); - { - // Timer timer(cout, " Block accumulator loop time: ", this->verbose()); - { - ThreadSafe ts(&_mutex, this->_nthreads > 1); - VMSG_NL(" Entering block accumulator loop for bucket " << (cur_block+1) << ":"); - } - TIndexOffU lenDiv10 = (len + 9) / 10; - for(TIndexOffU iten = 0, ten = 0; iten < len; iten += lenDiv10, ten++) { - TIndexOffU itenNext = iten + lenDiv10; - { - ThreadSafe ts(&_mutex, this->_nthreads > 1); - if(ten > 0) VMSG_NL(" bucket " << (cur_block+1) << ": " << (ten * 10) << "%"); - } - for(TIndexOffU i = iten; i < itenNext && i < len; i++) { - assert_lt(jLo, (TIndexOff)i); assert_lt(jHi, (TIndexOff)i); - // Advance the upper-bound comparison by one character - if(i == hi || i == lo) continue; // equal to one of the bookends - if(hi != OFF_MASK && !suffixCmp(hi, i, jHi, kHi, kHiSoft, zHi)) { - continue; // not in the bucket - } - if(lo != OFF_MASK && suffixCmp(lo, i, jLo, kLo, kLoSoft, zLo)) { - continue; // not in the bucket - } - // In the bucket! - add it - assert_lt(i, len); - try { - bucket.push_back(i); - } catch(bad_alloc &e) { - cerr << "Could not append element to block of " << ((bucket.size()) * OFF_SIZE) << " bytes" << endl; - if(this->_passMemExc) { - throw e; // rethrow immediately - } else { - cerr << "Please try using a larger number of blocks by specifying a smaller --bmax or" << endl - << "a larger --bmaxdivn" << endl; - throw 1; - } - } - // Not necessarily true; we allow overflowing buckets - // since we can't guarantee that a good set of sample - // suffixes can be found in a reasonable amount of time - //assert_lt(bucket.size(), this->bucketSz()); - } - } // end loop over all suffixes of t - { - ThreadSafe ts(&_mutex, this->_nthreads > 1); - VMSG_NL(" bucket " << (cur_block+1) << ": 100%"); - } - } - } // end else clause of if(_sampleSuffs.size() == 0) - // Sort the bucket - if(bucket.size() > 0) { - Timer timer(cout, " Sorting block time: ", this->verbose()); - { - ThreadSafe ts(&_mutex, this->_nthreads > 1); - VMSG_NL(" Sorting block of length " << bucket.size() << " for bucket " << (cur_block+1)); - } - this->qsort(bucket); - } - - if(hi != OFF_MASK) { - // Not the final bucket; throw in the sample on the RHS - bucket.push_back(hi); - } else { - // Final bucket; throw in $ suffix - bucket.push_back(len); - } - { - ThreadSafe ts(&_mutex, this->_nthreads > 1); - VMSG_NL("Returning block of " << bucket.size() << " for bucket " << (cur_block+1)); - } - } - + assert_eq(zLo[0], 0); + calcZ(t, lo, zLo, this->verbose(), this->sanit +} #endif /*BLOCKWISE_SA_H_*/ diff --git a/diff_sample.h b/diff_sample.h index 9965796..76f297f 100644 --- a/diff_sample.h +++ b/diff_sample.h @@ -766,7 +766,7 @@ struct VSortingParam { size_t sPrimeSz; TIndexOffU* sPrimeOrderArr; size_t depth; - const std::vector* boundaries; + const EList* boundaries; size_t* cur; MUTEX_T* mutex; }; @@ -777,7 +777,7 @@ static void VSorting_worker(void *vp) VSortingParam* param = (VSortingParam*)vp; DifferenceCoverSample* dcs = param->dcs; const TStr& host = dcs->text(); - const size_t hlen = length(host); + const size_t hlen = host.length(); uint32_t v = dcs->v(); while(true) { size_t cur = 0; @@ -821,13 +821,8 @@ void DifferenceCoverSample::build(int nthreads) { assert_gt(v, 2); // Build s' String sPrime; - // Need to allocate 2 extra elements at the end of the sPrime and _isaPrime - // arrays. One element that's less than all others, and another that acts - // as needed padding for the Larsson-Sadakane sorting code. - size_t padding = 1; VMSG_NL(" Building sPrime"); buildSPrime(sPrime); - size_t sPrimeSz = length(sPrime) - padding; assert_gt(length(sPrime), 0); assert_leq(length(sPrime), length(t)+1); // +1 is because of the end-cap TIndexOffU nextRank = 0; @@ -871,7 +866,7 @@ void DifferenceCoverSample::build(int nthreads) { query_depth++; tmp_nthreads >>= 1; } - std::vector boundaries; // bucket boundaries for parallelization + EList boundaries; // bucket boundaries for parallelization TIndexOffU *sOrig = NULL; if(this->sanityCheck()) { sOrig = new TIndexOffU[sPrimeSz]; @@ -881,14 +876,13 @@ void DifferenceCoverSample::build(int nthreads) { this->verbose(), false, query_depth, &boundaries); if(boundaries.size() > 0) { AutoArray threads(nthreads); - std::vector > tparams; + EList > tparams; size_t cur = 0; MUTEX_T mutex; for(int tid = 0; tid < nthreads; tid++) { // Calculate bucket sizes by doing a binary search for each // suffix and noting where it lands - VSortingParam temp; - tparams.push_back(temp); // tparams.expand(); + tparams.expand(); tparams.back().dcs = this; tparams.back().sPrimeArr = sPrimeArr; tparams.back().sPrimeSz = sPrimeSz; @@ -904,7 +898,7 @@ void DifferenceCoverSample::build(int nthreads) { } } if(this->sanityCheck()) { - sanityCheckOrderedSufs(t, length(t), sPrimeArr, sPrimeSz, v); + sanityCheckOrderedSufs(t, t.length(), sPrimeArr, sPrimeSz, v); for(size_t i = 0; i < sPrimeSz; i++) { assert_eq(sPrimeArr[i], sOrig[sPrimeOrderArr[i]]); } diff --git a/ebwt_build.cpp b/ebwt_build.cpp index db39266..c47603d 100644 --- a/ebwt_build.cpp +++ b/ebwt_build.cpp @@ -150,7 +150,7 @@ static void printUsage(ostream& out) { << "that you run the wrapper script 'bowtie-build' instead." << endl << endl; } - + } static const char *short_options = "qraph?nscfl:i:o:t:h:3C"; @@ -666,3 +666,4 @@ extern "C" { } } } + diff --git a/multikey_qsort.h b/multikey_qsort.h index b99c9c6..0a13850 100644 --- a/multikey_qsort.h +++ b/multikey_qsort.h @@ -488,17 +488,13 @@ void mkeyQSortSuf2( size_t slen, TIndexOffU *s2, int hi, - size_t _begin, - size_t _end, - size_t _depth, + size_t begin, + size_t end, + size_t depth, size_t upto = OFF_MASK, - std::vector* boundaries = NULL) + EList* boundaries = NULL) { - std::vector > block_list; - for (int i = 0; i < 3; i++) { - std::vector temp; - block_list.push_back(temp); - } + ELList block_list; while(true) { size_t begin = 0, end = 0, depth = 0; if(block_list.size() == 0) { @@ -510,7 +506,7 @@ void mkeyQSortSuf2( begin = block_list.back()[0].begin; end = block_list.back()[0].end; depth = block_list.back()[0].depth; - block_list.back().erase(block_list.back().begin()); + block_list.back().erase(0); } else { block_list.resize(block_list.size() - 1); if(block_list.size() == 0) { @@ -583,12 +579,10 @@ void mkeyQSortSuf2( r = min(d-c, end-d-1); VECSWAP2(s, s2, b, end-r, r); // swap right = to center assert(assertPartitionedSuf2(host, s, slen, hi, v, begin, end, depth)); // check post-=-swap invariant r = b-a; // r <- # of <'s - std::vector QSRVec; - block_list.push_back(QSRVec); + block_list.expand(); block_list.back().clear(); if(r > 0) { // recurse on <'s - QSortRange QSR1; - block_list.back().push_back(QSR1); + block_list.back().expand(); block_list.back().back().begin = begin; block_list.back().back().end = begin + r; block_list.back().back().depth = depth; @@ -596,16 +590,22 @@ void mkeyQSortSuf2( // Do not recurse on ='s if the pivot was the off-the-end value; // they're already fully sorted if(v != hi) { // recurse on ='s - QSortRange QSR2; - block_list.back().push_back(QSR2); + block_list.back().expand(); block_list.back().back().begin = begin + r; block_list.back().back().end = begin + r + (a-begin) + (end-d-1); block_list.back().back().depth = depth + 1; } - r = d-c; // r <- # of >'s exclu + r = d-c; // r <- # of >'s excluding those exhausted + if(r > 0 && v < hi-1) { // recurse on >'s + block_list.back().expand(); + block_list.back().back().begin = end - r; + block_list.back().back().end = end; + block_list.back().back().depth = depth; + } } } + /** * Toplevel function for multikey quicksort over suffixes with double * swapping. @@ -620,7 +620,7 @@ void mkeyQSortSuf2( bool verbose = false, bool sanityCheck = false, size_t upto = OFF_MASK, - std::vector* boundaries = NULL) + EList* boundaries = NULL) { size_t hlen = length(host); if(sanityCheck) sanityCheckInputSufs(s, slen); @@ -1001,11 +1001,7 @@ static void bucketSortSufDcU8( for(size_t i = 0; i < 4; i++) { bkts[i] = new TIndexOffU[4 * 1024 * 1024]; } - std::vector > block_list; - for (int i = 0; i < 5; i++) { - std::vector temp; - block_list.push_back(temp); - } + ELList block_list; while(true) { size_t begin = 0, end = 0; if(block_list.size() == 0) { @@ -1065,8 +1061,7 @@ static void bucketSortSufDcU8( // This frame is now totally finished with bkts[][], so recursive // callees can safely clobber it; we're not done with cnts[], but // that's local to the stack frame. - std::vector temp; - block_list.push_back(temp); + block_list.expand(); block_list.back().clear(); block_list.back().push_back(begin); for(size_t i = 0; i < 4; i++) { diff --git a/zbox.h b/zbox.h index dbe8008..152f909 100644 --- a/zbox.h +++ b/zbox.h @@ -10,12 +10,12 @@ template void calcZ(const T& s, TIndexOffU off, - std::vector& z, + String& z, bool verbose = false, bool sanityCheck = false) { size_t lCur = 0, rCur = 0; - size_t zlen = z.size(); + size_t zlen = length(z); size_t slen = length(s); assert_gt(zlen, 0); assert_eq(z[0], 0);