RapidFuzz
Loading...
Searching...
No Matches
Indel_impl.hpp
1/* SPDX-License-Identifier: MIT */
2/* Copyright © 2022-present Max Bachmann */
3
4#include <rapidfuzz/details/PatternMatchVector.hpp>
5#include <rapidfuzz/details/Range.hpp>
6#include <rapidfuzz/details/common.hpp>
7#include <rapidfuzz/details/distance.hpp>
8#include <rapidfuzz/details/intrinsics.hpp>
9#include <rapidfuzz/distance/LCSseq.hpp>
10
11namespace rapidfuzz {
12namespace detail {
13
14template <typename InputIt1, typename InputIt2>
15size_t indel_distance(const BlockPatternMatchVector& block, const Range<InputIt1>& s1,
16 const Range<InputIt2>& s2, size_t score_cutoff)
17{
18 size_t maximum = s1.size() + s2.size();
19 size_t lcs_cutoff = (maximum / 2 >= score_cutoff) ? maximum / 2 - score_cutoff : 0;
20 size_t lcs_sim = lcs_seq_similarity(block, s1, s2, lcs_cutoff);
21 size_t dist = maximum - 2 * lcs_sim;
22 return (dist <= score_cutoff) ? dist : score_cutoff + 1;
23}
24
25template <typename InputIt1, typename InputIt2>
26double indel_normalized_distance(const BlockPatternMatchVector& block, const Range<InputIt1>& s1,
27 const Range<InputIt2>& s2, double score_cutoff)
28{
29 size_t maximum = s1.size() + s2.size();
30 size_t cutoff_distance = static_cast<size_t>(std::ceil(static_cast<double>(maximum) * score_cutoff));
31 size_t dist = indel_distance(block, s1, s2, cutoff_distance);
32 double norm_dist = (maximum) ? static_cast<double>(dist) / static_cast<double>(maximum) : 0.0;
33 return (norm_dist <= score_cutoff) ? norm_dist : 1.0;
34}
35
36template <typename InputIt1, typename InputIt2>
37double indel_normalized_similarity(const BlockPatternMatchVector& block, const Range<InputIt1>& s1,
38 const Range<InputIt2>& s2, double score_cutoff)
39{
40 double cutoff_score = NormSim_to_NormDist(score_cutoff);
41 double norm_dist = indel_normalized_distance(block, s1, s2, cutoff_score);
42 double norm_sim = 1.0 - norm_dist;
43 return (norm_sim >= score_cutoff) ? norm_sim : 0.0;
44}
45
46class Indel : public DistanceBase<Indel, size_t, 0, std::numeric_limits<int64_t>::max()> {
47 friend DistanceBase<Indel, size_t, 0, std::numeric_limits<int64_t>::max()>;
48 friend NormalizedMetricBase<Indel>;
49
50 template <typename InputIt1, typename InputIt2>
51 static size_t maximum(const Range<InputIt1>& s1, const Range<InputIt2>& s2)
52 {
53 return s1.size() + s2.size();
54 }
55
56 template <typename InputIt1, typename InputIt2>
57 static size_t _distance(const Range<InputIt1>& s1, const Range<InputIt2>& s2, size_t score_cutoff,
58 size_t score_hint)
59 {
60 size_t maximum = Indel::maximum(s1, s2);
61 size_t lcs_cutoff = (maximum / 2 >= score_cutoff) ? maximum / 2 - score_cutoff : 0;
62 size_t lcs_hint = (maximum / 2 >= score_hint) ? maximum / 2 - score_hint : 0;
63 size_t lcs_sim = LCSseq::similarity(s1, s2, lcs_cutoff, lcs_hint);
64 size_t dist = maximum - 2 * lcs_sim;
65 return (dist <= score_cutoff) ? dist : score_cutoff + 1;
66 }
67};
68
69} // namespace detail
70} // namespace rapidfuzz