RapidFuzz
Loading...
Searching...
No Matches
Indel.hpp
1/* SPDX-License-Identifier: MIT */
2/* Copyright © 2022-present Max Bachmann */
3
4#pragma once
5
6#include <limits>
7#include <rapidfuzz/distance/Indel_impl.hpp>
8#include <rapidfuzz/distance/LCSseq.hpp>
9
10namespace rapidfuzz {
11
17template <typename InputIt1, typename InputIt2>
18size_t indel_distance(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2,
19 size_t score_cutoff = std::numeric_limits<size_t>::max())
20{
21 return detail::Indel::distance(first1, last1, first2, last2, score_cutoff, score_cutoff);
22}
23
24template <typename Sentence1, typename Sentence2>
25size_t indel_distance(const Sentence1& s1, const Sentence2& s2,
26 size_t score_cutoff = std::numeric_limits<size_t>::max())
27{
28 return detail::Indel::distance(s1, s2, score_cutoff, score_cutoff);
29}
30
31template <typename InputIt1, typename InputIt2>
32size_t indel_similarity(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2,
33 size_t score_cutoff = 0.0)
34{
35 return detail::Indel::similarity(first1, last1, first2, last2, score_cutoff, score_cutoff);
36}
37
38template <typename Sentence1, typename Sentence2>
39size_t indel_similarity(const Sentence1& s1, const Sentence2& s2, size_t score_cutoff = 0.0)
40{
41 return detail::Indel::similarity(s1, s2, score_cutoff, score_cutoff);
42}
43
44template <typename InputIt1, typename InputIt2>
45double indel_normalized_distance(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2,
46 double score_cutoff = 1.0)
47{
48 return detail::Indel::normalized_distance(first1, last1, first2, last2, score_cutoff, score_cutoff);
49}
50
51template <typename Sentence1, typename Sentence2>
52double indel_normalized_distance(const Sentence1& s1, const Sentence2& s2, double score_cutoff = 1.0)
53{
54 return detail::Indel::normalized_distance(s1, s2, score_cutoff, score_cutoff);
55}
56
57template <typename InputIt1, typename InputIt2>
58double indel_normalized_similarity(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2,
59 double score_cutoff = 0.0)
60{
61 return detail::Indel::normalized_similarity(first1, last1, first2, last2, score_cutoff, score_cutoff);
62}
63
64template <typename Sentence1, typename Sentence2>
65double indel_normalized_similarity(const Sentence1& s1, const Sentence2& s2, double score_cutoff = 0.0)
66{
67 return detail::Indel::normalized_similarity(s1, s2, score_cutoff, score_cutoff);
68}
69
70template <typename InputIt1, typename InputIt2>
71Editops indel_editops(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2)
72{
73 return lcs_seq_editops(first1, last1, first2, last2);
74}
75
76template <typename Sentence1, typename Sentence2>
77Editops indel_editops(const Sentence1& s1, const Sentence2& s2)
78{
79 return lcs_seq_editops(s1, s2);
80}
81
82#ifdef RAPIDFUZZ_SIMD
83namespace experimental {
84template <int MaxLen>
85struct MultiIndel
86 : public detail::MultiDistanceBase<MultiIndel<MaxLen>, size_t, 0, std::numeric_limits<int64_t>::max()> {
87private:
88 friend detail::MultiDistanceBase<MultiIndel<MaxLen>, size_t, 0, std::numeric_limits<int64_t>::max()>;
89 friend detail::MultiNormalizedMetricBase<MultiIndel<MaxLen>, size_t>;
90
91public:
92 MultiIndel(size_t count) : scorer(count)
93 {}
94
104 size_t result_count() const
105 {
106 return scorer.result_count();
107 }
108
109 template <typename Sentence1>
110 void insert(const Sentence1& s1_)
111 {
112 insert(detail::to_begin(s1_), detail::to_end(s1_));
113 }
114
115 template <typename InputIt1>
116 void insert(InputIt1 first1, InputIt1 last1)
117 {
118 scorer.insert(first1, last1);
119 str_lens.push_back(static_cast<size_t>(std::distance(first1, last1)));
120 }
121
122private:
123 template <typename InputIt2>
124 void _distance(size_t* scores, size_t score_count, const detail::Range<InputIt2>& s2,
125 size_t score_cutoff = std::numeric_limits<size_t>::max()) const
126 {
127 scorer.similarity(scores, score_count, s2);
128
129 for (size_t i = 0; i < get_input_count(); ++i) {
130 size_t maximum_ = maximum(i, s2);
131 size_t dist = maximum_ - 2 * scores[i];
132 scores[i] = (dist <= score_cutoff) ? dist : score_cutoff + 1;
133 }
134 }
135
136 template <typename InputIt2>
137 size_t maximum(size_t s1_idx, const detail::Range<InputIt2>& s2) const
138 {
139 return str_lens[s1_idx] + s2.size();
140 }
141
142 size_t get_input_count() const noexcept
143 {
144 return str_lens.size();
145 }
146
147 std::vector<size_t> str_lens;
148 MultiLCSseq<MaxLen> scorer;
149};
150} /* namespace experimental */
151#endif
152
153template <typename CharT1>
154struct CachedIndel
155 : public detail::CachedDistanceBase<CachedIndel<CharT1>, size_t, 0, std::numeric_limits<int64_t>::max()> {
156 template <typename Sentence1>
157 explicit CachedIndel(const Sentence1& s1_) : CachedIndel(detail::to_begin(s1_), detail::to_end(s1_))
158 {}
159
160 template <typename InputIt1>
161 CachedIndel(InputIt1 first1, InputIt1 last1)
162 : s1_len(static_cast<size_t>(std::distance(first1, last1))), scorer(first1, last1)
163 {}
164
165private:
166 friend detail::CachedDistanceBase<CachedIndel<CharT1>, size_t, 0, std::numeric_limits<int64_t>::max()>;
167 friend detail::CachedNormalizedMetricBase<CachedIndel<CharT1>>;
168
169 template <typename InputIt2>
170 size_t maximum(const detail::Range<InputIt2>& s2) const
171 {
172 return s1_len + s2.size();
173 }
174
175 template <typename InputIt2>
176 size_t _distance(const detail::Range<InputIt2>& s2, size_t score_cutoff, size_t score_hint) const
177 {
178 size_t maximum_ = maximum(s2);
179 size_t lcs_cutoff = (maximum_ / 2 >= score_cutoff) ? maximum_ / 2 - score_cutoff : 0;
180 size_t lcs_cutoff_hint = (maximum_ / 2 >= score_hint) ? maximum_ / 2 - score_hint : 0;
181 size_t lcs_sim = scorer.similarity(s2, lcs_cutoff, lcs_cutoff_hint);
182 size_t dist = maximum_ - 2 * lcs_sim;
183 return (dist <= score_cutoff) ? dist : score_cutoff + 1;
184 }
185
186 size_t s1_len;
187 CachedLCSseq<CharT1> scorer;
188};
189
190#ifdef RAPIDFUZZ_DEDUCTION_GUIDES
191template <typename Sentence1>
192explicit CachedIndel(const Sentence1& s1_) -> CachedIndel<char_type<Sentence1>>;
193
194template <typename InputIt1>
195CachedIndel(InputIt1 first1, InputIt1 last1) -> CachedIndel<iter_value_t<InputIt1>>;
196#endif
197
200} // namespace rapidfuzz