Skip to content

Commit 97cb884

Browse files
committed
ensure partial_ratio is symmetric
1 parent 76dc007 commit 97cb884

3 files changed

Lines changed: 69 additions & 25 deletions

File tree

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
## Changelog
22

3+
### [1.10.2] - 2022-11-
4+
#### Fixed
5+
- `fuzz::partial_ratio` was not always symmetric when `len(s1) == len(s2)`
6+
37
### [1.10.1] - 2022-11-02
48
#### Fixed
59
- fix broken sse2 support

extras/rapidfuzz_amalgamated.hpp

Lines changed: 33 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// Licensed under the MIT License <http://opensource.org/licenses/MIT>.
22
// SPDX-License-Identifier: MIT
33
// RapidFuzz v1.0.2
4-
// Generated: 2022-11-02 21:25:29.646502
4+
// Generated: 2022-11-04 11:50:47.498267
55
// ----------------------------------------------------------
66
// This file is an amalgamation of multiple different files.
77
// You probably shouldn't edit it directly.
@@ -9014,14 +9014,13 @@ namespace fuzz_detail {
90149014

90159015
template <typename InputIt1, typename InputIt2, typename CachedCharT1>
90169016
ScoreAlignment<double>
9017-
partial_ratio_short_needle(rapidfuzz::detail::Range<InputIt1> s1, rapidfuzz::detail::Range<InputIt2> s2,
9018-
const CachedRatio<CachedCharT1>& cached_ratio,
9019-
const detail::CharSet<iter_value_t<InputIt1>>& s1_char_set, double score_cutoff)
9017+
partial_ratio_impl(rapidfuzz::detail::Range<InputIt1> s1, rapidfuzz::detail::Range<InputIt2> s2,
9018+
const CachedRatio<CachedCharT1>& cached_ratio,
9019+
const detail::CharSet<iter_value_t<InputIt1>>& s1_char_set, double score_cutoff)
90209020
{
90219021
ScoreAlignment<double> res;
90229022
auto len1 = static_cast<size_t>(s1.size());
90239023
auto len2 = static_cast<size_t>(s2.size());
9024-
assert(len2 >= len1);
90259024
res.src_start = 0;
90269025
res.src_end = len1;
90279026
res.dest_start = 0;
@@ -9119,16 +9118,16 @@ partial_ratio_short_needle(rapidfuzz::detail::Range<InputIt1> s1, rapidfuzz::det
91199118
}
91209119

91219120
template <typename InputIt1, typename InputIt2, typename CharT1 = iter_value_t<InputIt1>>
9122-
ScoreAlignment<double> partial_ratio_short_needle(rapidfuzz::detail::Range<InputIt1> s1,
9123-
rapidfuzz::detail::Range<InputIt2> s2, double score_cutoff)
9121+
ScoreAlignment<double> partial_ratio_impl(rapidfuzz::detail::Range<InputIt1> s1,
9122+
rapidfuzz::detail::Range<InputIt2> s2, double score_cutoff)
91249123
{
91259124
CachedRatio<CharT1> cached_ratio(s1);
91269125

91279126
detail::CharSet<CharT1> s1_char_set;
91289127
for (auto ch : s1)
91299128
s1_char_set.insert(ch);
91309129

9131-
return partial_ratio_short_needle(s1, s2, cached_ratio, s1_char_set, score_cutoff);
9130+
return partial_ratio_impl(s1, s2, cached_ratio, s1_char_set, score_cutoff);
91329131
}
91339132

91349133
} // namespace fuzz_detail
@@ -9152,8 +9151,21 @@ ScoreAlignment<double> partial_ratio_alignment(InputIt1 first1, InputIt1 last1,
91529151
if (!len1 || !len2)
91539152
return ScoreAlignment<double>(static_cast<double>(len1 == len2) * 100.0, 0, len1, 0, len1);
91549153

9155-
return fuzz_detail::partial_ratio_short_needle(detail::Range(first1, last1), detail::Range(first2, last2),
9156-
score_cutoff);
9154+
auto s1 = detail::Range(first1, last1);
9155+
auto s2 = detail::Range(first2, last2);
9156+
9157+
auto alignment = fuzz_detail::partial_ratio_impl(s1, s2, score_cutoff);
9158+
if (alignment.score != 100 && s1.size() == s2.size()) {
9159+
score_cutoff = std::max(score_cutoff, alignment.score);
9160+
auto alignment2 = fuzz_detail::partial_ratio_impl(s2, s1, score_cutoff);
9161+
if (alignment2.score > alignment.score) {
9162+
std::swap(alignment2.src_start, alignment2.dest_start);
9163+
std::swap(alignment2.src_end, alignment2.dest_end);
9164+
return alignment2;
9165+
}
9166+
}
9167+
9168+
return alignment;
91579169
}
91589170

91599171
template <typename Sentence1, typename Sentence2>
@@ -9199,9 +9211,17 @@ double CachedPartialRatio<CharT1>::similarity(InputIt2 first2, InputIt2 last2, d
91999211

92009212
if (!len1 || !len2) return static_cast<double>(len1 == len2) * 100.0;
92019213

9202-
return fuzz_detail::partial_ratio_short_needle(detail::Range(s1), detail::Range(first2, last2),
9203-
cached_ratio, s1_char_set, score_cutoff)
9204-
.score;
9214+
auto s1_ = detail::Range(s1);
9215+
auto s2 = detail::Range(first2, last2);
9216+
9217+
double score = fuzz_detail::partial_ratio_impl(s1_, s2, cached_ratio, s1_char_set, score_cutoff).score;
9218+
if (score != 100 && s1_.size() == s2.size()) {
9219+
score_cutoff = std::max(score_cutoff, score);
9220+
double score2 = fuzz_detail::partial_ratio_impl(s2, s1_, score_cutoff).score;
9221+
if (score2 > score) return score2;
9222+
}
9223+
9224+
return score;
92059225
}
92069226

92079227
template <typename CharT1>

rapidfuzz/fuzz.impl

Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -52,14 +52,13 @@ namespace fuzz_detail {
5252

5353
template <typename InputIt1, typename InputIt2, typename CachedCharT1>
5454
ScoreAlignment<double>
55-
partial_ratio_short_needle(rapidfuzz::detail::Range<InputIt1> s1, rapidfuzz::detail::Range<InputIt2> s2,
56-
const CachedRatio<CachedCharT1>& cached_ratio,
57-
const detail::CharSet<iter_value_t<InputIt1>>& s1_char_set, double score_cutoff)
55+
partial_ratio_impl(rapidfuzz::detail::Range<InputIt1> s1, rapidfuzz::detail::Range<InputIt2> s2,
56+
const CachedRatio<CachedCharT1>& cached_ratio,
57+
const detail::CharSet<iter_value_t<InputIt1>>& s1_char_set, double score_cutoff)
5858
{
5959
ScoreAlignment<double> res;
6060
auto len1 = static_cast<size_t>(s1.size());
6161
auto len2 = static_cast<size_t>(s2.size());
62-
assert(len2 >= len1);
6362
res.src_start = 0;
6463
res.src_end = len1;
6564
res.dest_start = 0;
@@ -157,16 +156,16 @@ partial_ratio_short_needle(rapidfuzz::detail::Range<InputIt1> s1, rapidfuzz::det
157156
}
158157

159158
template <typename InputIt1, typename InputIt2, typename CharT1 = iter_value_t<InputIt1>>
160-
ScoreAlignment<double> partial_ratio_short_needle(rapidfuzz::detail::Range<InputIt1> s1,
161-
rapidfuzz::detail::Range<InputIt2> s2, double score_cutoff)
159+
ScoreAlignment<double> partial_ratio_impl(rapidfuzz::detail::Range<InputIt1> s1,
160+
rapidfuzz::detail::Range<InputIt2> s2, double score_cutoff)
162161
{
163162
CachedRatio<CharT1> cached_ratio(s1);
164163

165164
detail::CharSet<CharT1> s1_char_set;
166165
for (auto ch : s1)
167166
s1_char_set.insert(ch);
168167

169-
return partial_ratio_short_needle(s1, s2, cached_ratio, s1_char_set, score_cutoff);
168+
return partial_ratio_impl(s1, s2, cached_ratio, s1_char_set, score_cutoff);
170169
}
171170

172171
} // namespace fuzz_detail
@@ -190,8 +189,21 @@ ScoreAlignment<double> partial_ratio_alignment(InputIt1 first1, InputIt1 last1,
190189
if (!len1 || !len2)
191190
return ScoreAlignment<double>(static_cast<double>(len1 == len2) * 100.0, 0, len1, 0, len1);
192191

193-
return fuzz_detail::partial_ratio_short_needle(detail::Range(first1, last1), detail::Range(first2, last2),
194-
score_cutoff);
192+
auto s1 = detail::Range(first1, last1);
193+
auto s2 = detail::Range(first2, last2);
194+
195+
auto alignment = fuzz_detail::partial_ratio_impl(s1, s2, score_cutoff);
196+
if (alignment.score != 100 && s1.size() == s2.size()) {
197+
score_cutoff = std::max(score_cutoff, alignment.score);
198+
auto alignment2 = fuzz_detail::partial_ratio_impl(s2, s1, score_cutoff);
199+
if (alignment2.score > alignment.score) {
200+
std::swap(alignment2.src_start, alignment2.dest_start);
201+
std::swap(alignment2.src_end, alignment2.dest_end);
202+
return alignment2;
203+
}
204+
}
205+
206+
return alignment;
195207
}
196208

197209
template <typename Sentence1, typename Sentence2>
@@ -237,9 +249,17 @@ double CachedPartialRatio<CharT1>::similarity(InputIt2 first2, InputIt2 last2, d
237249

238250
if (!len1 || !len2) return static_cast<double>(len1 == len2) * 100.0;
239251

240-
return fuzz_detail::partial_ratio_short_needle(detail::Range(s1), detail::Range(first2, last2),
241-
cached_ratio, s1_char_set, score_cutoff)
242-
.score;
252+
auto s1_ = detail::Range(s1);
253+
auto s2 = detail::Range(first2, last2);
254+
255+
double score = fuzz_detail::partial_ratio_impl(s1_, s2, cached_ratio, s1_char_set, score_cutoff).score;
256+
if (score != 100 && s1_.size() == s2.size()) {
257+
score_cutoff = std::max(score_cutoff, score);
258+
double score2 = fuzz_detail::partial_ratio_impl(s2, s1_, score_cutoff).score;
259+
if (score2 > score) return score2;
260+
}
261+
262+
return score;
243263
}
244264

245265
template <typename CharT1>

0 commit comments

Comments
 (0)