89 Position_ query_start,
93 std::vector<Index_>& matches)
96 if (subject.root_children == 0) {
100 enum class OverlapsAnyMode :
char { BASIC, MIN_OVERLAP, MAX_GAP };
101 OverlapsAnyMode mode = OverlapsAnyMode::BASIC;
103 mode = OverlapsAnyMode::MIN_OVERLAP;
104 }
else if (params.
max_gap.has_value()) {
105 mode = OverlapsAnyMode::MAX_GAP;
158 if (mode == OverlapsAnyMode::MIN_OVERLAP) {
159 if (query_end - query_start < params.
min_overlap) {
164 Position_ effective_query_start = std::numeric_limits<Position_>::max();
165 if (mode == OverlapsAnyMode::MAX_GAP) {
166 effective_query_start = safe_subtract_gap(query_start, *(params.
max_gap));
167 }
else if (mode == OverlapsAnyMode::MIN_OVERLAP) {
168 constexpr Position_ maxed = std::numeric_limits<Position_>::max();
173 effective_query_start = query_start + params.
min_overlap;
177 auto find_first_child = [&](Index_ children_start, Index_ children_end) -> Index_ {
178 auto ebegin = subject.ends.begin();
179 auto estart = ebegin + children_start;
180 auto eend = ebegin + children_end;
181 if (mode == OverlapsAnyMode::BASIC) {
182 return std::upper_bound(estart, eend, query_start) - ebegin;
184 return std::lower_bound(estart, eend, effective_query_start) - ebegin;
188 auto can_skip_search = [&](Position_ subject_start) ->
bool {
189 if (mode == OverlapsAnyMode::BASIC) {
190 return subject_start > query_start;
192 return subject_start >= effective_query_start;
196 auto is_finished = [&](Position_ subject_start) ->
bool {
197 if (mode == OverlapsAnyMode::BASIC) {
198 return subject_start >= query_end;
199 }
else if (mode == OverlapsAnyMode::MAX_GAP) {
200 if (subject_start < query_end) {
203 return subject_start - query_end > *(params.
max_gap);
205 if (subject_start >= query_end) {
208 return query_end - subject_start < params.
min_overlap;
212 Index_ root_child_at = 0;
213 bool root_skip_search = can_skip_search(subject.starts[0]);
214 if (!root_skip_search) {
215 root_child_at = find_first_child(0, subject.root_children);
218 workspace.history.clear();
220 Index_ current_subject;
222 if (workspace.history.empty()) {
223 if (root_child_at == subject.root_children || is_finished(subject.starts[root_child_at])) {
226 current_subject = root_child_at;
227 skip_search = root_skip_search;
230 auto& current_state = workspace.history.back();
231 if (current_state.child_at == current_state.child_end || is_finished(subject.starts[current_state.child_at])) {
232 workspace.history.pop_back();
235 current_subject = current_state.child_at;
236 skip_search = current_state.skip_search;
237 ++(current_state.child_at);
240 const auto& current_node = subject.nodes[current_subject];
241 if (mode == OverlapsAnyMode::MIN_OVERLAP) {
242 if (std::min(query_end, subject.ends[current_subject]) - std::max(query_start, subject.starts[current_subject]) < params.
min_overlap) {
248 matches.push_back(current_node.id);
252 if (current_node.duplicates_start != current_node.duplicates_end) {
253 matches.insert(matches.end(), subject.duplicates.begin() + current_node.duplicates_start, subject.duplicates.begin() + current_node.duplicates_end);
256 if (current_node.children_start != current_node.children_end) {
258 workspace.history.emplace_back(current_node.children_start, current_node.children_end,
true);
260 Index_ start_pos = find_first_child(current_node.children_start, current_node.children_end);
261 if (start_pos != current_node.children_end) {
262 workspace.history.emplace_back(start_pos, current_node.children_end, can_skip_search(subject.starts[start_pos]));