ICU-20916 late computation of roundedThreshold to ensure it is up to date

This commit is contained in:
Markus Scherer 2020-03-17 15:31:31 -07:00
parent b1af32bfa7
commit 1b71013da0
2 changed files with 24 additions and 20 deletions

View File

@ -111,11 +111,6 @@ int32_t LocaleDistance::getBestIndexAndDistance(
const LSR **supportedLSRs, int32_t supportedLSRsLength, const LSR **supportedLSRs, int32_t supportedLSRsLength,
int32_t shiftedThreshold, int32_t shiftedThreshold,
ULocMatchFavorSubtag favorSubtag, ULocMatchDirection direction) const { ULocMatchFavorSubtag favorSubtag, ULocMatchDirection direction) const {
// Round up the shifted threshold (if fraction bits are not 0)
// for comparison with un-shifted distances until we need fraction bits.
// (If we simply shifted non-zero fraction bits away, then we might ignore a language
// when it's really still a micro distance below the threshold.)
int32_t roundedThreshold = (shiftedThreshold + DISTANCE_FRACTION_MASK) >> DISTANCE_SHIFT;
BytesTrie iter(trie); BytesTrie iter(trie);
// Look up the desired language only once for all supported LSRs. // Look up the desired language only once for all supported LSRs.
// Its "distance" is either a match point value of 0, or a non-match negative value. // Its "distance" is either a match point value of 0, or a non-match negative value.
@ -155,6 +150,11 @@ int32_t LocaleDistance::getBestIndexAndDistance(
star = true; star = true;
} }
U_ASSERT(0 <= distance && distance <= 100); U_ASSERT(0 <= distance && distance <= 100);
// Round up the shifted threshold (if fraction bits are not 0)
// for comparison with un-shifted distances until we need fraction bits.
// (If we simply shifted non-zero fraction bits away, then we might ignore a language
// when it's really still a micro distance below the threshold.)
int32_t roundedThreshold = (shiftedThreshold + DISTANCE_FRACTION_MASK) >> DISTANCE_SHIFT;
// We implement "favor subtag" by reducing the language subtag distance // We implement "favor subtag" by reducing the language subtag distance
// (unscientifically reducing it to a quarter of the normal value), // (unscientifically reducing it to a quarter of the normal value),
// so that the script distance is relatively more important. // so that the script distance is relatively more important.
@ -163,7 +163,9 @@ int32_t LocaleDistance::getBestIndexAndDistance(
if (favorSubtag == ULOCMATCH_FAVOR_SCRIPT) { if (favorSubtag == ULOCMATCH_FAVOR_SCRIPT) {
distance >>= 2; distance >>= 2;
} }
if (distance >= roundedThreshold) { // Let distance == roundedThreshold pass until the tie-breaker logic
// at the end of the loop.
if (distance > roundedThreshold) {
continue; continue;
} }
@ -181,7 +183,7 @@ int32_t LocaleDistance::getBestIndexAndDistance(
scriptDistance &= ~DISTANCE_IS_FINAL; scriptDistance &= ~DISTANCE_IS_FINAL;
} }
distance += scriptDistance; distance += scriptDistance;
if (distance >= roundedThreshold) { if (distance > roundedThreshold) {
continue; continue;
} }
@ -191,7 +193,7 @@ int32_t LocaleDistance::getBestIndexAndDistance(
distance += defaultRegionDistance; distance += defaultRegionDistance;
} else { } else {
int32_t remainingThreshold = roundedThreshold - distance; int32_t remainingThreshold = roundedThreshold - distance;
if (minRegionDistance >= remainingThreshold) { if (minRegionDistance > remainingThreshold) {
continue; continue;
} }
@ -319,7 +321,7 @@ int32_t LocaleDistance::getRegionPartitionsDistance(
d = getFallbackRegionDistance(iter, startState); d = getFallbackRegionDistance(iter, startState);
star = true; star = true;
} }
if (d >= threshold) { if (d > threshold) {
return d; return d;
} else if (regionDistance < d) { } else if (regionDistance < d) {
regionDistance = d; regionDistance = d;
@ -332,7 +334,7 @@ int32_t LocaleDistance::getRegionPartitionsDistance(
} }
} else if (!star) { } else if (!star) {
int32_t d = getFallbackRegionDistance(iter, startState); int32_t d = getFallbackRegionDistance(iter, startState);
if (d >= threshold) { if (d > threshold) {
return d; return d;
} else if (regionDistance < d) { } else if (regionDistance < d) {
regionDistance = d; regionDistance = d;

View File

@ -244,11 +244,6 @@ public class LocaleDistance {
*/ */
public int getBestIndexAndDistance(LSR desired, LSR[] supportedLSRs, int supportedLSRsLength, public int getBestIndexAndDistance(LSR desired, LSR[] supportedLSRs, int supportedLSRsLength,
int shiftedThreshold, FavorSubtag favorSubtag, LocaleMatcher.Direction direction) { int shiftedThreshold, FavorSubtag favorSubtag, LocaleMatcher.Direction direction) {
// Round up the shifted threshold (if fraction bits are not 0)
// for comparison with un-shifted distances until we need fraction bits.
// (If we simply shifted non-zero fraction bits away, then we might ignore a language
// when it's really still a micro distance below the threshold.)
int roundedThreshold = (shiftedThreshold + DISTANCE_FRACTION_MASK) >> DISTANCE_SHIFT;
BytesTrie iter = new BytesTrie(trie); BytesTrie iter = new BytesTrie(trie);
// Look up the desired language only once for all supported LSRs. // Look up the desired language only once for all supported LSRs.
// Its "distance" is either a match point value of 0, or a non-match negative value. // Its "distance" is either a match point value of 0, or a non-match negative value.
@ -288,6 +283,11 @@ public class LocaleDistance {
star = true; star = true;
} }
assert 0 <= distance && distance <= 100; assert 0 <= distance && distance <= 100;
// Round up the shifted threshold (if fraction bits are not 0)
// for comparison with un-shifted distances until we need fraction bits.
// (If we simply shifted non-zero fraction bits away, then we might ignore a language
// when it's really still a micro distance below the threshold.)
int roundedThreshold = (shiftedThreshold + DISTANCE_FRACTION_MASK) >> DISTANCE_SHIFT;
// We implement "favor subtag" by reducing the language subtag distance // We implement "favor subtag" by reducing the language subtag distance
// (unscientifically reducing it to a quarter of the normal value), // (unscientifically reducing it to a quarter of the normal value),
// so that the script distance is relatively more important. // so that the script distance is relatively more important.
@ -296,7 +296,9 @@ public class LocaleDistance {
if (favorSubtag == FavorSubtag.SCRIPT) { if (favorSubtag == FavorSubtag.SCRIPT) {
distance >>= 2; distance >>= 2;
} }
if (distance >= roundedThreshold) { // Let distance == roundedThreshold pass until the tie-breaker logic
// at the end of the loop.
if (distance > roundedThreshold) {
continue; continue;
} }
@ -314,7 +316,7 @@ public class LocaleDistance {
scriptDistance &= ~DISTANCE_IS_FINAL; scriptDistance &= ~DISTANCE_IS_FINAL;
} }
distance += scriptDistance; distance += scriptDistance;
if (distance >= roundedThreshold) { if (distance > roundedThreshold) {
continue; continue;
} }
@ -324,7 +326,7 @@ public class LocaleDistance {
distance += defaultRegionDistance; distance += defaultRegionDistance;
} else { } else {
int remainingThreshold = roundedThreshold - distance; int remainingThreshold = roundedThreshold - distance;
if (minRegionDistance >= remainingThreshold) { if (minRegionDistance > remainingThreshold) {
continue; continue;
} }
@ -452,7 +454,7 @@ public class LocaleDistance {
d = getFallbackRegionDistance(iter, startState); d = getFallbackRegionDistance(iter, startState);
star = true; star = true;
} }
if (d >= threshold) { if (d > threshold) {
return d; return d;
} else if (regionDistance < d) { } else if (regionDistance < d) {
regionDistance = d; regionDistance = d;
@ -465,7 +467,7 @@ public class LocaleDistance {
} }
} else if (!star) { } else if (!star) {
int d = getFallbackRegionDistance(iter, startState); int d = getFallbackRegionDistance(iter, startState);
if (d >= threshold) { if (d > threshold) {
return d; return d;
} else if (regionDistance < d) { } else if (regionDistance < d) {
regionDistance = d; regionDistance = d;