diff --git a/dynamic_gbwt.cpp b/dynamic_gbwt.cpp index 19d2aad..4c8807b 100644 --- a/dynamic_gbwt.cpp +++ b/dynamic_gbwt.cpp @@ -301,7 +301,7 @@ updateRecords(DynamicGBWT& gbwt, std::vector& seqs, size_type iteratio size_type insert_count = 0; while(i < seqs.size() && seqs[i].curr == curr) { - rank_type outrank = current.edgeTo(seqs[i].next); + rank_type outrank = current.edgeToLinear(seqs[i].next); if(outrank >= current.outdegree()) // Add edge (curr, next) if it does not exist. { current.outgoing.push_back(edge_type(seqs[i].next, 0)); @@ -445,7 +445,7 @@ rebuildOffsets(DynamicGBWT& gbwt, std::vector& seqs) for(edge_type inedge : gbwt.record(next).incoming) { DynamicRecord& predecessor = gbwt.record(inedge.first); - predecessor.offset(predecessor.edgeTo(next)) = offset; + predecessor.offset(predecessor.edgeToLinear(next)) = offset; offset += inedge.second; } } @@ -453,7 +453,7 @@ rebuildOffsets(DynamicGBWT& gbwt, std::vector& seqs) for(Sequence& seq : seqs) { const DynamicRecord& current = gbwt.record(seq.curr); - seq.offset += current.offset(current.edgeTo(seq.next)); + seq.offset += current.offset(current.edgeToLinear(seq.next)); } } diff --git a/include/gbwt/support.h b/include/gbwt/support.h index e2d2d0d..5f00c05 100644 --- a/include/gbwt/support.h +++ b/include/gbwt/support.h @@ -131,6 +131,9 @@ struct DynamicRecord // Maps successor nodes to outranks. rank_type edgeTo(node_type to) const; + // This version works when the edges are not sorted. + rank_type edgeToLinear(node_type to) const; + // These assume that 'outrank' is a valid outgoing edge. node_type successor(rank_type outrank) const { return this->outgoing[outrank].first; } #ifdef GBWT_SAVE_MEMORY diff --git a/support.cpp b/support.cpp index 125d70e..c36b0da 100644 --- a/support.cpp +++ b/support.cpp @@ -218,6 +218,20 @@ DynamicRecord::hasEdge(node_type to) const rank_type DynamicRecord::edgeTo(node_type to) const +{ + rank_type low = 0, high = this->outdegree(); + while(low < high) + { + rank_type mid = low + (high - low) / 2; + if(this->successor(mid) == to) { return mid; } + if(this->successor(mid) > to) { high = mid; } + else { low = mid + 1; } + } + return this->outdegree(); +} + +rank_type +DynamicRecord::edgeToLinear(node_type to) const { for(rank_type outrank = 0; outrank < this->outdegree(); outrank++) { @@ -401,9 +415,13 @@ CompressedRecord::hasEdge(node_type to) const rank_type CompressedRecord::edgeTo(node_type to) const { - for(rank_type outrank = 0; outrank < this->outdegree(); outrank++) + rank_type low = 0, high = this->outdegree(); + while(low < high) { - if(this->successor(outrank) == to) { return outrank; } + rank_type mid = low + (high - low) / 2; + if(this->successor(mid) == to) { return mid; } + if(this->successor(mid) > to) { high = mid; } + else { low = mid + 1; } } return this->outdegree(); }