aboutsummaryrefslogtreecommitdiffstats
path: root/native/src/correction.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'native/src/correction.cpp')
-rw-r--r--native/src/correction.cpp113
1 files changed, 57 insertions, 56 deletions
diff --git a/native/src/correction.cpp b/native/src/correction.cpp
index a08a21bd2..31493ee7d 100644
--- a/native/src/correction.cpp
+++ b/native/src/correction.cpp
@@ -118,7 +118,6 @@ bool Correction::initProcessState(const int outputIndex) {
mInputIndex = mCorrectionStates[outputIndex].mInputIndex;
mNeedsToTraverseAllNodes = mCorrectionStates[outputIndex].mNeedsToTraverseAllNodes;
- mSumOfDistance = mCorrectionStates[outputIndex].mSumOfDistance;
mEquivalentCharCount = mCorrectionStates[outputIndex].mEquivalentCharCount;
mProximityCount = mCorrectionStates[outputIndex].mProximityCount;
mTransposedCount = mCorrectionStates[outputIndex].mTransposedCount;
@@ -174,7 +173,6 @@ void Correction::incrementOutputIndex() {
mCorrectionStates[mOutputIndex].mInputIndex = mInputIndex;
mCorrectionStates[mOutputIndex].mNeedsToTraverseAllNodes = mNeedsToTraverseAllNodes;
- mCorrectionStates[mOutputIndex].mSumOfDistance = mSumOfDistance;
mCorrectionStates[mOutputIndex].mEquivalentCharCount = mEquivalentCharCount;
mCorrectionStates[mOutputIndex].mProximityCount = mProximityCount;
mCorrectionStates[mOutputIndex].mTransposedCount = mTransposedCount;
@@ -227,20 +225,26 @@ Correction::CorrectionType Correction::processCharAndCalcState(
// TODO: Change the limit if we'll allow two or more corrections
const bool noCorrectionsHappenedSoFar = correctionCount == 0;
const bool canTryCorrection = noCorrectionsHappenedSoFar;
+ int proximityIndex = 0;
+ mDistances[mOutputIndex] = NOT_A_DISTANCE;
if (mNeedsToTraverseAllNodes || isQuote(c)) {
bool incremented = false;
if (mLastCharExceeded && mInputIndex == mInputLength - 1) {
// TODO: Do not check the proximity if EditDistance exceeds the threshold
const ProximityInfo::ProximityType matchId =
- mProximityInfo->getMatchedProximityId(mInputIndex, c, true);
+ mProximityInfo->getMatchedProximityId(mInputIndex, c, true, &proximityIndex);
if (isEquivalentChar(matchId)) {
mLastCharExceeded = false;
--mExcessiveCount;
+ mDistances[mOutputIndex] =
+ mProximityInfo->getNormalizedSquaredDistance(mInputIndex, 0);
} else if (matchId == ProximityInfo::NEAR_PROXIMITY_CHAR) {
mLastCharExceeded = false;
--mExcessiveCount;
++mProximityCount;
+ mDistances[mOutputIndex] =
+ mProximityInfo->getNormalizedSquaredDistance(mInputIndex, proximityIndex);
}
incrementInputIndex();
incremented = true;
@@ -301,7 +305,8 @@ Correction::CorrectionType Correction::processCharAndCalcState(
const bool checkProximityChars = noCorrectionsHappenedSoFar || mProximityCount == 0;
ProximityInfo::ProximityType matchedProximityCharId = secondTransposing
? ProximityInfo::EQUIVALENT_CHAR
- : mProximityInfo->getMatchedProximityId(mInputIndex, c, checkProximityChars);
+ : mProximityInfo->getMatchedProximityId(
+ mInputIndex, c, checkProximityChars, &proximityIndex);
if (ProximityInfo::UNRELATED_CHAR == matchedProximityCharId) {
if (canTryCorrection && mOutputIndex > 0
@@ -323,8 +328,8 @@ Correction::CorrectionType Correction::processCharAndCalcState(
// Here, we are doing something equivalent to matchedProximityCharId,
// but we already know that "excessive char correction" just happened
// so that we just need to check "mProximityCount == 0".
- matchedProximityCharId =
- mProximityInfo->getMatchedProximityId(mInputIndex, c, mProximityCount == 0);
+ matchedProximityCharId = mProximityInfo->getMatchedProximityId(
+ mInputIndex, c, mProximityCount == 0, &proximityIndex);
}
}
@@ -399,17 +404,12 @@ Correction::CorrectionType Correction::processCharAndCalcState(
} else if (isEquivalentChar(matchedProximityCharId)) {
mMatching = true;
++mEquivalentCharCount;
- if (mSumOfDistance != NOT_A_DISTANCE) {
- const int distance = mProximityInfo->getNormalizedSquaredDistance(mInputIndex);
- if (distance != NOT_A_DISTANCE) {
- mSumOfDistance += distance;
- } else {
- mSumOfDistance = NOT_A_DISTANCE;
- }
- }
+ mDistances[mOutputIndex] = mProximityInfo->getNormalizedSquaredDistance(mInputIndex, 0);
} else if (ProximityInfo::NEAR_PROXIMITY_CHAR == matchedProximityCharId) {
mProximityMatching = true;
++mProximityCount;
+ mDistances[mOutputIndex] =
+ mProximityInfo->getNormalizedSquaredDistance(mInputIndex, proximityIndex);
}
mWord[mOutputIndex] = c;
@@ -583,8 +583,6 @@ int Correction::RankingAlgorithm::calculateFinalFreq(const int inputIndex, const
const int transposedCount = correction->mTransposedCount / 2;
const int excessiveCount = correction->mExcessiveCount + correction->mTransposedCount % 2;
const int proximityMatchedCount = correction->mProximityCount;
- const int mSumOfDistance = correction->mSumOfDistance;
- const int mEquivalentCharCount = correction->mEquivalentCharCount;
const bool lastCharExceeded = correction->mLastCharExceeded;
const bool useFullEditDistance = correction->mUseFullEditDistance;
const int outputLength = outputIndex + 1;
@@ -684,47 +682,50 @@ int Correction::RankingAlgorithm::calculateFinalFreq(const int inputIndex, const
}
}
- // Promotion for a word with proximity characters
- for (int i = 0; i < adjustedProximityMatchedCount; ++i) {
- // A word with proximity corrections
- if (DEBUG_DICT_FULL) {
- LOGI("Found a proximity correction.");
+ // Score calibration by touch coordinates is being done only for pure-fat finger typing error
+ // cases.
+ // TODO: Remove this constraint.
+ if (CALIBRATE_SCORE_BY_TOUCH_COORDINATES && proximityInfo->touchPositionCorrectionEnabled()
+ && skippedCount == 0 && excessiveCount == 0 && transposedCount == 0) {
+ for (int i = 0; i < outputLength; ++i) {
+ const int squaredDistance = correction->mDistances[i];
+ if (i < adjustedProximityMatchedCount) {
+ multiplyIntCapped(typedLetterMultiplier, &finalFreq);
+ }
+ if (squaredDistance >= 0) {
+ // Promote or demote the score according to the distance from the sweet spot
+ static const float A = ZERO_DISTANCE_PROMOTION_RATE / 100.0f;
+ static const float B = 1.0f;
+ static const float C = 0.5f;
+ static const float R1 = NEUTRAL_SCORE_SQUARED_RADIUS;
+ static const float R2 = HALF_SCORE_SQUARED_RADIUS;
+ const float x = (float)squaredDistance
+ / ProximityInfo::NORMALIZED_SQUARED_DISTANCE_SCALING_FACTOR;
+ const float factor = (x < R1)
+ ? (A * (R1 - x) + B * x) / R1
+ : (B * (R2 - x) + C * (x - R1)) / (R2 - R1);
+ // factor is piecewise linear function like:
+ // A -_ .
+ // ^-_ .
+ // B \ .
+ // \ .
+ // C \ .
+ // 0 R1 R2
+ multiplyRate((int)(factor * 100), &finalFreq);
+ } else if (squaredDistance == PROXIMITY_CHAR_WITHOUT_DISTANCE_INFO) {
+ multiplyRate(WORDS_WITH_PROXIMITY_CHARACTER_DEMOTION_RATE, &finalFreq);
+ }
+ }
+ } else {
+ // Promotion for a word with proximity characters
+ for (int i = 0; i < adjustedProximityMatchedCount; ++i) {
+ // A word with proximity corrections
+ if (DEBUG_DICT_FULL) {
+ LOGI("Found a proximity correction.");
+ }
+ multiplyIntCapped(typedLetterMultiplier, &finalFreq);
+ multiplyRate(WORDS_WITH_PROXIMITY_CHARACTER_DEMOTION_RATE, &finalFreq);
}
- multiplyIntCapped(typedLetterMultiplier, &finalFreq);
- multiplyRate(WORDS_WITH_PROXIMITY_CHARACTER_DEMOTION_RATE, &finalFreq);
- }
-
- if (CALIBRATE_SCORE_BY_TOUCH_COORDINATES
- && mEquivalentCharCount > 0 && mSumOfDistance != NOT_A_DISTANCE) {
- // Let (x, y) be the coordinate of a user's touch, and let c be a key.
- // Assuming users' touch distribution is gauss distribution, the conditional probability of
- // the user touching (x, y) given he or she intends to hit c is:
- // p(x, y | c) = exp(-(x - m_x) / (2 * s^2)) / (sqrt(2 * pi) * s)
- // * exp(-(y - m_y) / (2 * s^2)) / (sqrt(2 * pi) * s)
- // where (m_x, m_y) is a mean of touches of c, and s is a variance of touches of c.
- // If user touches c1, c2, .., cn, the joint distribution is
- // p(x1, y1 | c1) * p(x2, y2 | c2) * ... * p(xn, yn | cn)
- // We consider the logarithm of this value, that is
- // sum_i log p(x_i, y_i | c_i) + const
- // = sum_i ((x_i - m_x)^2 + (y_i - m_y)^2) / (2 * s^2) + const
- // Thus, we use the sum of squared distance as a score of the word.
- static const int UPPER = WORDS_WITH_EQUIVALENT_CHAR_STRONGEST_PROMOTION_RATE;
- static const int LOWER = WORDS_WITH_EQUIVALENT_CHAR_WEAKEST_DEMOTION_RATE;
- static const int MIDDLE = 100;
- static const int SHIFT = ProximityInfo::NORMALIZED_SQUARED_DISTANCE_SCALING_FACTOR_LOG_2;
- const int expected = mEquivalentCharCount << SHIFT;
- // factor is a function as described below:
- // U\ .
- // \ .
- // M \ .
- // \ .
- // L \------- .
- // 0 e
- // (x-axis is mSumOfDistance, y-axis is rate,
- // and e, U, M, L are expected, UPPER, MIDDLE, LOWER respectively.
- const int factor =
- max((UPPER * expected - (UPPER - MIDDLE) * mSumOfDistance) / expected, LOWER);
- multiplyRate(factor, &finalFreq);
}
const int errorCount = adjustedProximityMatchedCount > 0