17 #include <type_traits>
27 namespace seqan3::detail
31 enum class error_type : uint8_t
48 class unidirectional_search_algorithm :
protected policies_t...
52 using traits_t = search_traits<configuration_t>;
54 using search_result_type =
typename traits_t::search_result_type;
56 static_assert(!std::same_as<search_result_type, empty_type>,
"The search result type was not configured.");
62 unidirectional_search_algorithm() =
default;
63 unidirectional_search_algorithm(unidirectional_search_algorithm
const &) =
default;
64 unidirectional_search_algorithm(unidirectional_search_algorithm &&) =
default;
65 unidirectional_search_algorithm & operator=(unidirectional_search_algorithm
const &) =
default;
66 unidirectional_search_algorithm & operator=(unidirectional_search_algorithm &&) =
default;
67 ~unidirectional_search_algorithm() =
default;
79 unidirectional_search_algorithm(configuration_t
const & cfg, index_t
const & index) : policies_t{cfg}...
81 stratum = cfg.get_or(search_cfg::hit_strata{0}).stratum;
106 template <
typename indexed_query_t,
typename callback_t>
108 requires (std::tuple_size_v<indexed_query_t> == 2) &&
109 std::ranges::forward_range<std::tuple_element_t<1, indexed_query_t>> &&
110 std::invocable<callback_t, search_result_type>
112 void operator()(indexed_query_t && indexed_query, callback_t && callback)
114 auto && [query_idx, query] = indexed_query;
115 auto error_state = this->max_error_counts(query);
119 delegate = [&internal_hits] (
auto const & it)
124 perform_search_by_hit_strategy(internal_hits, query, error_state);
126 this->make_results(
std::move(internal_hits), query_idx, callback);
131 index_t
const * index_ptr{
nullptr};
134 std::function<void(
typename index_t::cursor_type
const &)> delegate;
140 template <
bool abort_on_hit,
typename query_t>
141 bool search_trivial(
typename index_t::cursor_type cur,
143 typename index_t::cursor_type::size_type
const query_pos,
144 search_param
const error_left,
145 error_type
const prev_error);
153 template <
typename query_t>
156 search_param error_state)
158 if constexpr (!traits_t::search_all_hits)
160 auto max_total = error_state.total;
161 error_state.total = 0;
163 while (internal_hits.
empty() && error_state.total <= max_total)
171 constexpr
bool abort_on_hit = !traits_t::search_all_best_hits;
172 search_trivial<abort_on_hit>(index_ptr->cursor(), query, 0, error_state, error_type::none);
176 if constexpr (traits_t::search_strata_hits)
178 if (!internal_hits.
empty())
180 internal_hits.
clear();
181 error_state.total += stratum - 1;
182 search_trivial<false>(index_ptr->cursor(), query, 0, error_state, error_type::none);
190 search_trivial<false>(index_ptr->cursor(), query, 0, error_state, error_type::none);
213 template <
typename configuration_t,
typename index_t,
typename ...policies_t>
214 template <
bool abort_on_hit,
typename query_t>
215 inline bool unidirectional_search_algorithm<configuration_t, index_t, policies_t...>::search_trivial(
216 typename index_t::cursor_type cur,
218 typename index_t::cursor_type::size_type
const query_pos,
219 search_param
const error_left,
220 error_type
const prev_error)
237 bool const allow_insertion = (cur.query_length() > 0) ? cur.last_rank() !=
seqan3::to_rank(query[query_pos]) : true;
239 if (allow_insertion && (prev_error != error_type::deletion || error_left.substitution == 0) &&
240 error_left.insertion > 0)
242 search_param error_left2{error_left};
243 error_left2.insertion--;
248 if (search_trivial<abort_on_hit>(cur,
249 query, query_pos + 1,
251 error_type::insertion) &&
259 if (((query_pos > 0 && error_left.deletion > 0) || error_left.substitution > 0) && cur.extend_right())
264 if (error_left.substitution > 0)
267 search_param error_left2{error_left};
268 error_left2.total -= delta;
269 error_left2.substitution -= delta;
271 if (search_trivial<abort_on_hit>(cur,
275 error_type::matchmm) &&
286 if (error_left.substitution == 0 && cur.last_rank() ==
seqan3::to_rank(query[query_pos]))
288 if (search_trivial<abort_on_hit>(cur,
292 error_type::matchmm) &&
303 if ((prev_error != error_type::insertion || error_left.substitution == 0) &&
304 error_left.deletion > 0)
306 search_param error_left2{error_left};
308 error_left2.deletion--;
313 if (search_trivial<abort_on_hit>(cur,
317 error_type::deletion) &&
325 }
while (cur.cycle_back());
330 if (cur.extend_right(query[query_pos]))
332 if (search_trivial<abort_on_hit>(cur,
336 error_type::matchmm) &&