7#include <rapidfuzz/details/common.hpp>
8#include <rapidfuzz/distance/OSA_impl.hpp>
41template <
typename InputIt1,
typename InputIt2>
42size_t osa_distance(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2,
43 size_t score_cutoff = std::numeric_limits<size_t>::max())
45 return detail::OSA::distance(first1, last1, first2, last2, score_cutoff, score_cutoff);
48template <
typename Sentence1,
typename Sentence2>
49size_t osa_distance(
const Sentence1& s1,
const Sentence2& s2,
50 size_t score_cutoff = std::numeric_limits<size_t>::max())
52 return detail::OSA::distance(s1, s2, score_cutoff, score_cutoff);
55template <
typename InputIt1,
typename InputIt2>
56size_t osa_similarity(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2,
57 size_t score_cutoff = 0)
59 return detail::OSA::similarity(first1, last1, first2, last2, score_cutoff, score_cutoff);
62template <
typename Sentence1,
typename Sentence2>
63size_t osa_similarity(
const Sentence1& s1,
const Sentence2& s2,
size_t score_cutoff = 0)
65 return detail::OSA::similarity(s1, s2, score_cutoff, score_cutoff);
68template <
typename InputIt1,
typename InputIt2>
69double osa_normalized_distance(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2,
70 double score_cutoff = 1.0)
72 return detail::OSA::normalized_distance(first1, last1, first2, last2, score_cutoff, score_cutoff);
75template <
typename Sentence1,
typename Sentence2>
76double osa_normalized_distance(
const Sentence1& s1,
const Sentence2& s2,
double score_cutoff = 1.0)
78 return detail::OSA::normalized_distance(s1, s2, score_cutoff, score_cutoff);
105template <
typename InputIt1,
typename InputIt2>
107 double score_cutoff = 0.0)
109 return detail::OSA::normalized_similarity(first1, last1, first2, last2, score_cutoff, score_cutoff);
112template <
typename Sentence1,
typename Sentence2>
115 return detail::OSA::normalized_similarity(s1, s2, score_cutoff, score_cutoff);
119namespace experimental {
122 :
public detail::MultiDistanceBase<MultiOSA<MaxLen>, size_t, 0, std::numeric_limits<int64_t>::max()> {
124 friend detail::MultiDistanceBase<MultiOSA<MaxLen>, size_t, 0, std::numeric_limits<int64_t>::max()>;
125 friend detail::MultiNormalizedMetricBase<MultiOSA<MaxLen>,
size_t>;
127 RAPIDFUZZ_CONSTEXPR_CXX14
static size_t get_vec_size()
129# ifdef RAPIDFUZZ_AVX2
130 using namespace detail::simd_avx2;
132 using namespace detail::simd_sse2;
134 RAPIDFUZZ_IF_CONSTEXPR (MaxLen <= 8)
135 return native_simd<uint8_t>::size;
136 else RAPIDFUZZ_IF_CONSTEXPR (MaxLen <= 16)
137 return native_simd<uint16_t>::size;
138 else RAPIDFUZZ_IF_CONSTEXPR (MaxLen <= 32)
139 return native_simd<uint32_t>::size;
140 else RAPIDFUZZ_IF_CONSTEXPR (MaxLen <= 64)
141 return native_simd<uint64_t>::size;
143 static_assert(MaxLen <= 64, "expected MaxLen <= 64");
146 static
size_t find_block_count(
size_t count)
148 size_t vec_size = get_vec_size();
149 size_t simd_vec_count = detail::ceil_div(count, vec_size);
150 return detail::ceil_div(simd_vec_count * vec_size * MaxLen, 64);
154 MultiOSA(
size_t count) : input_count(count), PM(find_block_count(count) * 64)
156 str_lens.resize(result_count());
168 size_t result_count()
const
170 size_t vec_size = get_vec_size();
171 size_t simd_vec_count = detail::ceil_div(input_count, vec_size);
172 return simd_vec_count * vec_size;
175 template <
typename Sentence1>
176 void insert(
const Sentence1& s1_)
178 insert(detail::to_begin(s1_), detail::to_end(s1_));
181 template <
typename InputIt1>
182 void insert(InputIt1 first1, InputIt1 last1)
184 auto len = std::distance(first1, last1);
185 int block_pos =
static_cast<int>((pos * MaxLen) % 64);
186 auto block = (pos * MaxLen) / 64;
187 assert(len <= MaxLen);
189 if (pos >= input_count)
throw std::invalid_argument(
"out of bounds insert");
191 str_lens[pos] =
static_cast<size_t>(len);
192 for (; first1 != last1; ++first1) {
193 PM.insert(block, *first1, block_pos);
200 template <
typename InputIt2>
201 void _distance(
size_t* scores,
size_t score_count,
const detail::Range<InputIt2>& s2,
202 size_t score_cutoff = std::numeric_limits<size_t>::max())
const
204 if (score_count < result_count())
205 throw std::invalid_argument(
"scores has to have >= result_count() elements");
207 auto scores_ = detail::make_range(scores, scores + score_count);
208 RAPIDFUZZ_IF_CONSTEXPR (MaxLen == 8)
209 detail::osa_hyrroe2003_simd<uint8_t>(scores_, PM, str_lens, s2, score_cutoff);
210 else RAPIDFUZZ_IF_CONSTEXPR (MaxLen == 16)
211 detail::osa_hyrroe2003_simd<uint16_t>(scores_, PM, str_lens, s2, score_cutoff);
212 else RAPIDFUZZ_IF_CONSTEXPR (MaxLen == 32)
213 detail::osa_hyrroe2003_simd<uint32_t>(scores_, PM, str_lens, s2, score_cutoff);
214 else RAPIDFUZZ_IF_CONSTEXPR (MaxLen == 64)
215 detail::osa_hyrroe2003_simd<uint64_t>(scores_, PM, str_lens, s2, score_cutoff);
218 template <typename InputIt2>
219 size_t maximum(
size_t s1_idx, const detail::Range<InputIt2>& s2)
const
221 return std::max(str_lens[s1_idx], s2.size());
224 size_t get_input_count() const noexcept
231 detail::BlockPatternMatchVector PM;
232 std::vector<size_t> str_lens;
237template <
typename CharT1>
239 :
public detail::CachedDistanceBase<CachedOSA<CharT1>, size_t, 0, std::numeric_limits<int64_t>::max()> {
240 template <
typename Sentence1>
241 explicit CachedOSA(
const Sentence1& s1_) : CachedOSA(detail::to_begin(s1_), detail::to_end(s1_))
244 template <
typename InputIt1>
245 CachedOSA(InputIt1 first1, InputIt1 last1) : s1(first1, last1), PM(detail::make_range(first1, last1))
249 friend detail::CachedDistanceBase<CachedOSA<CharT1>, size_t, 0, std::numeric_limits<int64_t>::max()>;
250 friend detail::CachedNormalizedMetricBase<CachedOSA<CharT1>>;
252 template <
typename InputIt2>
253 size_t maximum(
const detail::Range<InputIt2>& s2)
const
255 return std::max(s1.size(), s2.size());
258 template <
typename InputIt2>
259 size_t _distance(
const detail::Range<InputIt2>& s2,
size_t score_cutoff,
size_t)
const
266 else if (s1.size() < 64)
267 res = detail::osa_hyrroe2003(PM, detail::make_range(s1), s2, score_cutoff);
269 res = detail::osa_hyrroe2003_block(PM, detail::make_range(s1), s2, score_cutoff);
271 return (res <= score_cutoff) ? res : score_cutoff + 1;
274 std::vector<CharT1> s1;
275 detail::BlockPatternMatchVector PM;
278#ifdef RAPIDFUZZ_DEDUCTION_GUIDES
279template <
typename Sentence1>
280CachedOSA(
const Sentence1& s1_) -> CachedOSA<char_type<Sentence1>>;
282template <
typename InputIt1>
283CachedOSA(InputIt1 first1, InputIt1 last1) -> CachedOSA<iter_value_t<InputIt1>>;
size_t osa_distance(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2, size_t score_cutoff=std::numeric_limits< size_t >::max())
Calculates the optimal string alignment (OSA) distance between two strings.
Definition OSA.hpp:42
double osa_normalized_similarity(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2, double score_cutoff=0.0)
Calculates a normalized hamming similarity.
Definition OSA.hpp:106