Move code related to ranking algorithm to the correction state
Change-Id: I2d9e2db81cf6597ca4e88d7bc6737ab3b52b34b2
This commit is contained in:
parent
afa5e9af8f
commit
612c6e49c0
4 changed files with 298 additions and 194 deletions
|
@ -21,18 +21,26 @@
|
||||||
#define LOG_TAG "LatinIME: correction_state.cpp"
|
#define LOG_TAG "LatinIME: correction_state.cpp"
|
||||||
|
|
||||||
#include "correction_state.h"
|
#include "correction_state.h"
|
||||||
|
#include "proximity_info.h"
|
||||||
|
|
||||||
namespace latinime {
|
namespace latinime {
|
||||||
|
|
||||||
CorrectionState::CorrectionState() {
|
CorrectionState::CorrectionState(const int typedLetterMultiplier, const int fullWordMultiplier)
|
||||||
|
: TYPED_LETTER_MULTIPLIER(typedLetterMultiplier), FULL_WORD_MULTIPLIER(fullWordMultiplier) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void CorrectionState::setCorrectionParams(const ProximityInfo *pi, const int inputLength,
|
void CorrectionState::initCorrectionState(const ProximityInfo *pi, const int inputLength) {
|
||||||
const int skipPos, const int excessivePos, const int transposedPos) {
|
|
||||||
mProximityInfo = pi;
|
mProximityInfo = pi;
|
||||||
|
mInputLength = inputLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CorrectionState::setCorrectionParams(const int skipPos, const int excessivePos,
|
||||||
|
const int transposedPos, const int spaceProximityPos, const int missingSpacePos) {
|
||||||
mSkipPos = skipPos;
|
mSkipPos = skipPos;
|
||||||
mExcessivePos = excessivePos;
|
mExcessivePos = excessivePos;
|
||||||
mTransposedPos = transposedPos;
|
mTransposedPos = transposedPos;
|
||||||
|
mSpaceProximityPos = spaceProximityPos;
|
||||||
|
mMissingSpacePos = missingSpacePos;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CorrectionState::checkState() {
|
void CorrectionState::checkState() {
|
||||||
|
@ -46,7 +54,203 @@ void CorrectionState::checkState() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int CorrectionState::getFreqForSplitTwoWords(const int firstFreq, const int secondFreq) {
|
||||||
|
return CorrectionState::RankingAlgorithm::calcFreqForSplitTwoWords(firstFreq, secondFreq, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
int CorrectionState::getFinalFreq(const int inputIndex, const int depth, const int matchWeight,
|
||||||
|
const int freq, const bool sameLength) {
|
||||||
|
return CorrectionState::RankingAlgorithm::calculateFinalFreq(inputIndex, depth, matchWeight,
|
||||||
|
freq, sameLength, this);
|
||||||
|
}
|
||||||
|
|
||||||
CorrectionState::~CorrectionState() {
|
CorrectionState::~CorrectionState() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/////////////////////////
|
||||||
|
// static inline utils //
|
||||||
|
/////////////////////////
|
||||||
|
|
||||||
|
static const int TWO_31ST_DIV_255 = S_INT_MAX / 255;
|
||||||
|
static inline int capped255MultForFullMatchAccentsOrCapitalizationDifference(const int num) {
|
||||||
|
return (num < TWO_31ST_DIV_255 ? 255 * num : S_INT_MAX);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const int TWO_31ST_DIV_2 = S_INT_MAX / 2;
|
||||||
|
inline static void multiplyIntCapped(const int multiplier, int *base) {
|
||||||
|
const int temp = *base;
|
||||||
|
if (temp != S_INT_MAX) {
|
||||||
|
// Branch if multiplier == 2 for the optimization
|
||||||
|
if (multiplier == 2) {
|
||||||
|
*base = TWO_31ST_DIV_2 >= temp ? temp << 1 : S_INT_MAX;
|
||||||
|
} else {
|
||||||
|
const int tempRetval = temp * multiplier;
|
||||||
|
*base = tempRetval >= temp ? tempRetval : S_INT_MAX;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline static int powerIntCapped(const int base, const int n) {
|
||||||
|
if (n == 0) return 1;
|
||||||
|
if (base == 2) {
|
||||||
|
return n < 31 ? 1 << n : S_INT_MAX;
|
||||||
|
} else {
|
||||||
|
int ret = base;
|
||||||
|
for (int i = 1; i < n; ++i) multiplyIntCapped(base, &ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline static void multiplyRate(const int rate, int *freq) {
|
||||||
|
if (*freq != S_INT_MAX) {
|
||||||
|
if (*freq > 1000000) {
|
||||||
|
*freq /= 100;
|
||||||
|
multiplyIntCapped(rate, freq);
|
||||||
|
} else {
|
||||||
|
multiplyIntCapped(rate, freq);
|
||||||
|
*freq /= 100;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////
|
||||||
|
// RankingAlgorithm //
|
||||||
|
//////////////////////
|
||||||
|
|
||||||
|
int CorrectionState::RankingAlgorithm::calculateFinalFreq(const int inputIndex, const int depth,
|
||||||
|
const int matchCount, const int freq, const bool sameLength,
|
||||||
|
const CorrectionState* correctionState) {
|
||||||
|
const int skipPos = correctionState->getSkipPos();
|
||||||
|
const int excessivePos = correctionState->getExcessivePos();
|
||||||
|
const int transposedPos = correctionState->getTransposedPos();
|
||||||
|
const int inputLength = correctionState->mInputLength;
|
||||||
|
const int typedLetterMultiplier = correctionState->TYPED_LETTER_MULTIPLIER;
|
||||||
|
const int fullWordMultiplier = correctionState->FULL_WORD_MULTIPLIER;
|
||||||
|
const ProximityInfo *proximityInfo = correctionState->mProximityInfo;
|
||||||
|
const int matchWeight = powerIntCapped(typedLetterMultiplier, matchCount);
|
||||||
|
|
||||||
|
// TODO: Demote by edit distance
|
||||||
|
int finalFreq = freq * matchWeight;
|
||||||
|
if (skipPos >= 0) {
|
||||||
|
if (inputLength >= 2) {
|
||||||
|
const int demotionRate = WORDS_WITH_MISSING_CHARACTER_DEMOTION_RATE
|
||||||
|
* (10 * inputLength - WORDS_WITH_MISSING_CHARACTER_DEMOTION_START_POS_10X)
|
||||||
|
/ (10 * inputLength
|
||||||
|
- WORDS_WITH_MISSING_CHARACTER_DEMOTION_START_POS_10X + 10);
|
||||||
|
if (DEBUG_DICT_FULL) {
|
||||||
|
LOGI("Demotion rate for missing character is %d.", demotionRate);
|
||||||
|
}
|
||||||
|
multiplyRate(demotionRate, &finalFreq);
|
||||||
|
} else {
|
||||||
|
finalFreq = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (transposedPos >= 0) multiplyRate(
|
||||||
|
WORDS_WITH_TRANSPOSED_CHARACTERS_DEMOTION_RATE, &finalFreq);
|
||||||
|
if (excessivePos >= 0) {
|
||||||
|
multiplyRate(WORDS_WITH_EXCESSIVE_CHARACTER_DEMOTION_RATE, &finalFreq);
|
||||||
|
if (!proximityInfo->existsAdjacentProximityChars(inputIndex)) {
|
||||||
|
// If an excessive character is not adjacent to the left char or the right char,
|
||||||
|
// we will demote this word.
|
||||||
|
multiplyRate(WORDS_WITH_EXCESSIVE_CHARACTER_OUT_OF_PROXIMITY_DEMOTION_RATE, &finalFreq);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int lengthFreq = typedLetterMultiplier;
|
||||||
|
multiplyIntCapped(powerIntCapped(typedLetterMultiplier, depth), &lengthFreq);
|
||||||
|
if (lengthFreq == matchWeight) {
|
||||||
|
// Full exact match
|
||||||
|
if (depth > 1) {
|
||||||
|
if (DEBUG_DICT) {
|
||||||
|
LOGI("Found full matched word.");
|
||||||
|
}
|
||||||
|
multiplyRate(FULL_MATCHED_WORDS_PROMOTION_RATE, &finalFreq);
|
||||||
|
}
|
||||||
|
if (sameLength && transposedPos < 0 && skipPos < 0 && excessivePos < 0) {
|
||||||
|
finalFreq = capped255MultForFullMatchAccentsOrCapitalizationDifference(finalFreq);
|
||||||
|
}
|
||||||
|
} else if (sameLength && transposedPos < 0 && skipPos < 0 && excessivePos < 0 && depth > 0) {
|
||||||
|
// A word with proximity corrections
|
||||||
|
if (DEBUG_DICT) {
|
||||||
|
LOGI("Found one proximity correction.");
|
||||||
|
}
|
||||||
|
multiplyIntCapped(typedLetterMultiplier, &finalFreq);
|
||||||
|
multiplyRate(WORDS_WITH_PROXIMITY_CHARACTER_DEMOTION_RATE, &finalFreq);
|
||||||
|
}
|
||||||
|
if (DEBUG_DICT) {
|
||||||
|
LOGI("calc: %d, %d", depth, sameLength);
|
||||||
|
}
|
||||||
|
if (sameLength) multiplyIntCapped(fullWordMultiplier, &finalFreq);
|
||||||
|
return finalFreq;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CorrectionState::RankingAlgorithm::calcFreqForSplitTwoWords(
|
||||||
|
const int firstFreq, const int secondFreq, const CorrectionState* correctionState) {
|
||||||
|
const int spaceProximityPos = correctionState->mSpaceProximityPos;
|
||||||
|
const int missingSpacePos = correctionState->mMissingSpacePos;
|
||||||
|
if (DEBUG_DICT) {
|
||||||
|
int inputCount = 0;
|
||||||
|
if (spaceProximityPos >= 0) ++inputCount;
|
||||||
|
if (missingSpacePos >= 0) ++inputCount;
|
||||||
|
assert(inputCount <= 1);
|
||||||
|
}
|
||||||
|
const bool isSpaceProximity = spaceProximityPos >= 0;
|
||||||
|
const int inputLength = correctionState->mInputLength;
|
||||||
|
const int firstWordLength = isSpaceProximity ? spaceProximityPos : missingSpacePos;
|
||||||
|
const int secondWordLength = isSpaceProximity
|
||||||
|
? (inputLength - spaceProximityPos - 1)
|
||||||
|
: (inputLength - missingSpacePos);
|
||||||
|
const int typedLetterMultiplier = correctionState->TYPED_LETTER_MULTIPLIER;
|
||||||
|
|
||||||
|
if (firstWordLength == 0 || secondWordLength == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
const int firstDemotionRate = 100 - 100 / (firstWordLength + 1);
|
||||||
|
int tempFirstFreq = firstFreq;
|
||||||
|
multiplyRate(firstDemotionRate, &tempFirstFreq);
|
||||||
|
|
||||||
|
const int secondDemotionRate = 100 - 100 / (secondWordLength + 1);
|
||||||
|
int tempSecondFreq = secondFreq;
|
||||||
|
multiplyRate(secondDemotionRate, &tempSecondFreq);
|
||||||
|
|
||||||
|
const int totalLength = firstWordLength + secondWordLength;
|
||||||
|
|
||||||
|
// Promote pairFreq with multiplying by 2, because the word length is the same as the typed
|
||||||
|
// length.
|
||||||
|
int totalFreq = tempFirstFreq + tempSecondFreq;
|
||||||
|
|
||||||
|
// This is a workaround to try offsetting the not-enough-demotion which will be done in
|
||||||
|
// calcNormalizedScore in Utils.java.
|
||||||
|
// In calcNormalizedScore the score will be demoted by (1 - 1 / length)
|
||||||
|
// but we demoted only (1 - 1 / (length + 1)) so we will additionally adjust freq by
|
||||||
|
// (1 - 1 / length) / (1 - 1 / (length + 1)) = (1 - 1 / (length * length))
|
||||||
|
const int normalizedScoreNotEnoughDemotionAdjustment = 100 - 100 / (totalLength * totalLength);
|
||||||
|
multiplyRate(normalizedScoreNotEnoughDemotionAdjustment, &totalFreq);
|
||||||
|
|
||||||
|
// At this moment, totalFreq is calculated by the following formula:
|
||||||
|
// (firstFreq * (1 - 1 / (firstWordLength + 1)) + secondFreq * (1 - 1 / (secondWordLength + 1)))
|
||||||
|
// * (1 - 1 / totalLength) / (1 - 1 / (totalLength + 1))
|
||||||
|
|
||||||
|
multiplyIntCapped(powerIntCapped(typedLetterMultiplier, totalLength), &totalFreq);
|
||||||
|
|
||||||
|
// This is another workaround to offset the demotion which will be done in
|
||||||
|
// calcNormalizedScore in Utils.java.
|
||||||
|
// In calcNormalizedScore the score will be demoted by (1 - 1 / length) so we have to promote
|
||||||
|
// the same amount because we already have adjusted the synthetic freq of this "missing or
|
||||||
|
// mistyped space" suggestion candidate above in this method.
|
||||||
|
const int normalizedScoreDemotionRateOffset = (100 + 100 / totalLength);
|
||||||
|
multiplyRate(normalizedScoreDemotionRateOffset, &totalFreq);
|
||||||
|
|
||||||
|
if (isSpaceProximity) {
|
||||||
|
// A word pair with one space proximity correction
|
||||||
|
if (DEBUG_DICT) {
|
||||||
|
LOGI("Found a word pair with space proximity correction.");
|
||||||
|
}
|
||||||
|
multiplyIntCapped(typedLetterMultiplier, &totalFreq);
|
||||||
|
multiplyRate(WORDS_WITH_PROXIMITY_CHARACTER_DEMOTION_RATE, &totalFreq);
|
||||||
|
}
|
||||||
|
|
||||||
|
multiplyRate(WORDS_WITH_MISSING_SPACE_CHARACTER_DEMOTION_RATE, &totalFreq);
|
||||||
|
return totalFreq;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace latinime
|
} // namespace latinime
|
||||||
|
|
|
@ -26,10 +26,12 @@ namespace latinime {
|
||||||
class ProximityInfo;
|
class ProximityInfo;
|
||||||
|
|
||||||
class CorrectionState {
|
class CorrectionState {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CorrectionState();
|
CorrectionState(const int typedLetterMultiplier, const int fullWordMultiplier);
|
||||||
void setCorrectionParams(const ProximityInfo *pi, const int inputLength, const int skipPos,
|
void initCorrectionState(const ProximityInfo *pi, const int inputLength);
|
||||||
const int excessivePos, const int transposedPos);
|
void setCorrectionParams(const int skipPos, const int excessivePos, const int transposedPos,
|
||||||
|
const int spaceProximityPos, const int missingSpacePos);
|
||||||
void checkState();
|
void checkState();
|
||||||
virtual ~CorrectionState();
|
virtual ~CorrectionState();
|
||||||
int getSkipPos() const {
|
int getSkipPos() const {
|
||||||
|
@ -41,12 +43,36 @@ public:
|
||||||
int getTransposedPos() const {
|
int getTransposedPos() const {
|
||||||
return mTransposedPos;
|
return mTransposedPos;
|
||||||
}
|
}
|
||||||
|
int getSpaceProximityPos() const {
|
||||||
|
return mSpaceProximityPos;
|
||||||
|
}
|
||||||
|
int getMissingSpacePos() const {
|
||||||
|
return mMissingSpacePos;
|
||||||
|
}
|
||||||
|
int getFreqForSplitTwoWords(const int firstFreq, const int secondFreq);
|
||||||
|
int getFinalFreq(const int inputIndex, const int depth, const int matchWeight, const int freq,
|
||||||
|
const bool sameLength);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
const int TYPED_LETTER_MULTIPLIER;
|
||||||
|
const int FULL_WORD_MULTIPLIER;
|
||||||
const ProximityInfo *mProximityInfo;
|
const ProximityInfo *mProximityInfo;
|
||||||
int mInputLength;
|
int mInputLength;
|
||||||
int mSkipPos;
|
int mSkipPos;
|
||||||
int mExcessivePos;
|
int mExcessivePos;
|
||||||
int mTransposedPos;
|
int mTransposedPos;
|
||||||
|
int mSpaceProximityPos;
|
||||||
|
int mMissingSpacePos;
|
||||||
|
|
||||||
|
class RankingAlgorithm {
|
||||||
|
public:
|
||||||
|
static int calculateFinalFreq(const int inputIndex, const int depth,
|
||||||
|
const int matchCount, const int freq, const bool sameLength,
|
||||||
|
const CorrectionState* correctionState);
|
||||||
|
static int calcFreqForSplitTwoWords(const int firstFreq, const int secondFreq,
|
||||||
|
const CorrectionState* correctionState);
|
||||||
|
};
|
||||||
};
|
};
|
||||||
} // namespace latinime
|
} // namespace latinime
|
||||||
#endif // LATINIME_CORRECTION_INFO_H
|
#endif // LATINIME_CORRECTION_INFO_H
|
||||||
|
|
|
@ -48,7 +48,7 @@ UnigramDictionary::UnigramDictionary(const uint8_t* const streamStart, int typed
|
||||||
if (DEBUG_DICT) {
|
if (DEBUG_DICT) {
|
||||||
LOGI("UnigramDictionary - constructor");
|
LOGI("UnigramDictionary - constructor");
|
||||||
}
|
}
|
||||||
mCorrectionState = new CorrectionState();
|
mCorrectionState = new CorrectionState(typedLetterMultiplier, fullWordMultiplier);
|
||||||
}
|
}
|
||||||
|
|
||||||
UnigramDictionary::~UnigramDictionary() {
|
UnigramDictionary::~UnigramDictionary() {
|
||||||
|
@ -187,6 +187,7 @@ void UnigramDictionary::getWordSuggestions(ProximityInfo *proximityInfo,
|
||||||
PROF_START(0);
|
PROF_START(0);
|
||||||
initSuggestions(
|
initSuggestions(
|
||||||
proximityInfo, xcoordinates, ycoordinates, codes, codesSize, outWords, frequencies);
|
proximityInfo, xcoordinates, ycoordinates, codes, codesSize, outWords, frequencies);
|
||||||
|
mCorrectionState->initCorrectionState(mProximityInfo, mInputLength);
|
||||||
if (DEBUG_DICT) assert(codesSize == mInputLength);
|
if (DEBUG_DICT) assert(codesSize == mInputLength);
|
||||||
|
|
||||||
const int MAX_DEPTH = min(mInputLength * MAX_DEPTH_MULTIPLIER, MAX_WORD_LENGTH);
|
const int MAX_DEPTH = min(mInputLength * MAX_DEPTH_MULTIPLIER, MAX_WORD_LENGTH);
|
||||||
|
@ -242,7 +243,7 @@ void UnigramDictionary::getWordSuggestions(ProximityInfo *proximityInfo,
|
||||||
if (DEBUG_DICT) {
|
if (DEBUG_DICT) {
|
||||||
LOGI("--- Suggest missing space characters %d", i);
|
LOGI("--- Suggest missing space characters %d", i);
|
||||||
}
|
}
|
||||||
getMissingSpaceWords(mInputLength, i);
|
getMissingSpaceWords(mInputLength, i, mCorrectionState);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PROF_END(5);
|
PROF_END(5);
|
||||||
|
@ -261,7 +262,7 @@ void UnigramDictionary::getWordSuggestions(ProximityInfo *proximityInfo,
|
||||||
i, x, y, proximityInfo->hasSpaceProximity(x, y));
|
i, x, y, proximityInfo->hasSpaceProximity(x, y));
|
||||||
}
|
}
|
||||||
if (proximityInfo->hasSpaceProximity(x, y)) {
|
if (proximityInfo->hasSpaceProximity(x, y)) {
|
||||||
getMistypedSpaceWords(mInputLength, i);
|
getMistypedSpaceWords(mInputLength, i, mCorrectionState);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -355,8 +356,8 @@ void UnigramDictionary::getSuggestionCandidates(const int skipPos,
|
||||||
assert(excessivePos < mInputLength);
|
assert(excessivePos < mInputLength);
|
||||||
assert(missingPos < mInputLength);
|
assert(missingPos < mInputLength);
|
||||||
}
|
}
|
||||||
mCorrectionState->setCorrectionParams(mProximityInfo, mInputLength, skipPos, excessivePos,
|
mCorrectionState->setCorrectionParams(skipPos, excessivePos, transposedPos,
|
||||||
transposedPos);
|
-1 /* spaceProximityPos */, -1 /* missingSpacePos */);
|
||||||
int rootPosition = ROOT_POS;
|
int rootPosition = ROOT_POS;
|
||||||
// Get the number of children of root, then increment the position
|
// Get the number of children of root, then increment the position
|
||||||
int childCount = Dictionary::getCount(DICT_ROOT, &rootPosition);
|
int childCount = Dictionary::getCount(DICT_ROOT, &rootPosition);
|
||||||
|
@ -364,7 +365,7 @@ void UnigramDictionary::getSuggestionCandidates(const int skipPos,
|
||||||
|
|
||||||
mStackChildCount[0] = childCount;
|
mStackChildCount[0] = childCount;
|
||||||
mStackTraverseAll[0] = (mInputLength <= 0);
|
mStackTraverseAll[0] = (mInputLength <= 0);
|
||||||
mStackNodeFreq[0] = 1;
|
mStackMatchCount[0] = 0;
|
||||||
mStackInputIndex[0] = 0;
|
mStackInputIndex[0] = 0;
|
||||||
mStackDiffs[0] = 0;
|
mStackDiffs[0] = 0;
|
||||||
mStackSiblingPos[0] = rootPosition;
|
mStackSiblingPos[0] = rootPosition;
|
||||||
|
@ -375,7 +376,7 @@ void UnigramDictionary::getSuggestionCandidates(const int skipPos,
|
||||||
if (mStackChildCount[depth] > 0) {
|
if (mStackChildCount[depth] > 0) {
|
||||||
--mStackChildCount[depth];
|
--mStackChildCount[depth];
|
||||||
bool traverseAllNodes = mStackTraverseAll[depth];
|
bool traverseAllNodes = mStackTraverseAll[depth];
|
||||||
int matchWeight = mStackNodeFreq[depth];
|
int matchCount = mStackMatchCount[depth];
|
||||||
int inputIndex = mStackInputIndex[depth];
|
int inputIndex = mStackInputIndex[depth];
|
||||||
int diffs = mStackDiffs[depth];
|
int diffs = mStackDiffs[depth];
|
||||||
int siblingPos = mStackSiblingPos[depth];
|
int siblingPos = mStackSiblingPos[depth];
|
||||||
|
@ -384,9 +385,9 @@ void UnigramDictionary::getSuggestionCandidates(const int skipPos,
|
||||||
// depth will never be greater than maxDepth because in that case,
|
// depth will never be greater than maxDepth because in that case,
|
||||||
// needsToTraverseChildrenNodes should be false
|
// needsToTraverseChildrenNodes should be false
|
||||||
const bool needsToTraverseChildrenNodes = processCurrentNode(siblingPos, outputIndex,
|
const bool needsToTraverseChildrenNodes = processCurrentNode(siblingPos, outputIndex,
|
||||||
maxDepth, traverseAllNodes, matchWeight, inputIndex, diffs,
|
maxDepth, traverseAllNodes, matchCount, inputIndex, diffs,
|
||||||
nextLetters, nextLettersSize, mCorrectionState, &childCount,
|
nextLetters, nextLettersSize, mCorrectionState, &childCount,
|
||||||
&firstChildPos, &traverseAllNodes, &matchWeight, &inputIndex, &diffs,
|
&firstChildPos, &traverseAllNodes, &matchCount, &inputIndex, &diffs,
|
||||||
&siblingPos, &outputIndex);
|
&siblingPos, &outputIndex);
|
||||||
// Update next sibling pos
|
// Update next sibling pos
|
||||||
mStackSiblingPos[depth] = siblingPos;
|
mStackSiblingPos[depth] = siblingPos;
|
||||||
|
@ -395,7 +396,7 @@ void UnigramDictionary::getSuggestionCandidates(const int skipPos,
|
||||||
++depth;
|
++depth;
|
||||||
mStackChildCount[depth] = childCount;
|
mStackChildCount[depth] = childCount;
|
||||||
mStackTraverseAll[depth] = traverseAllNodes;
|
mStackTraverseAll[depth] = traverseAllNodes;
|
||||||
mStackNodeFreq[depth] = matchWeight;
|
mStackMatchCount[depth] = matchCount;
|
||||||
mStackInputIndex[depth] = inputIndex;
|
mStackInputIndex[depth] = inputIndex;
|
||||||
mStackDiffs[depth] = diffs;
|
mStackDiffs[depth] = diffs;
|
||||||
mStackSiblingPos[depth] = firstChildPos;
|
mStackSiblingPos[depth] = firstChildPos;
|
||||||
|
@ -408,11 +409,6 @@ void UnigramDictionary::getSuggestionCandidates(const int skipPos,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const int TWO_31ST_DIV_255 = S_INT_MAX / 255;
|
|
||||||
static inline int capped255MultForFullMatchAccentsOrCapitalizationDifference(const int num) {
|
|
||||||
return (num < TWO_31ST_DIV_255 ? 255 * num : S_INT_MAX);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const int TWO_31ST_DIV_2 = S_INT_MAX / 2;
|
static const int TWO_31ST_DIV_2 = S_INT_MAX / 2;
|
||||||
inline static void multiplyIntCapped(const int multiplier, int *base) {
|
inline static void multiplyIntCapped(const int multiplier, int *base) {
|
||||||
const int temp = *base;
|
const int temp = *base;
|
||||||
|
@ -427,153 +423,18 @@ inline static void multiplyIntCapped(const int multiplier, int *base) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static int powerIntCapped(const int base, const int n) {
|
void UnigramDictionary::getMissingSpaceWords(
|
||||||
if (base == 2) {
|
const int inputLength, const int missingSpacePos, CorrectionState *correctionState) {
|
||||||
return n < 31 ? 1 << n : S_INT_MAX;
|
correctionState->setCorrectionParams(-1 /* skipPos */, -1 /* excessivePos */,
|
||||||
} else {
|
-1 /* transposedPos */, -1 /* spaceProximityPos */, missingSpacePos);
|
||||||
int ret = base;
|
getSplitTwoWordsSuggestion(inputLength, correctionState);
|
||||||
for (int i = 1; i < n; ++i) multiplyIntCapped(base, &ret);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static void multiplyRate(const int rate, int *freq) {
|
void UnigramDictionary::getMistypedSpaceWords(
|
||||||
if (*freq != S_INT_MAX) {
|
const int inputLength, const int spaceProximityPos, CorrectionState *correctionState) {
|
||||||
if (*freq > 1000000) {
|
correctionState->setCorrectionParams(-1 /* skipPos */, -1 /* excessivePos */,
|
||||||
*freq /= 100;
|
-1 /* transposedPos */, spaceProximityPos, -1 /* missingSpacePos */);
|
||||||
multiplyIntCapped(rate, freq);
|
getSplitTwoWordsSuggestion(inputLength, correctionState);
|
||||||
} else {
|
|
||||||
multiplyIntCapped(rate, freq);
|
|
||||||
*freq /= 100;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline static int calcFreqForSplitTwoWords(
|
|
||||||
const int typedLetterMultiplier, const int firstWordLength, const int secondWordLength,
|
|
||||||
const int firstFreq, const int secondFreq, const bool isSpaceProximity) {
|
|
||||||
if (firstWordLength == 0 || secondWordLength == 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
const int firstDemotionRate = 100 - 100 / (firstWordLength + 1);
|
|
||||||
int tempFirstFreq = firstFreq;
|
|
||||||
multiplyRate(firstDemotionRate, &tempFirstFreq);
|
|
||||||
|
|
||||||
const int secondDemotionRate = 100 - 100 / (secondWordLength + 1);
|
|
||||||
int tempSecondFreq = secondFreq;
|
|
||||||
multiplyRate(secondDemotionRate, &tempSecondFreq);
|
|
||||||
|
|
||||||
const int totalLength = firstWordLength + secondWordLength;
|
|
||||||
|
|
||||||
// Promote pairFreq with multiplying by 2, because the word length is the same as the typed
|
|
||||||
// length.
|
|
||||||
int totalFreq = tempFirstFreq + tempSecondFreq;
|
|
||||||
|
|
||||||
// This is a workaround to try offsetting the not-enough-demotion which will be done in
|
|
||||||
// calcNormalizedScore in Utils.java.
|
|
||||||
// In calcNormalizedScore the score will be demoted by (1 - 1 / length)
|
|
||||||
// but we demoted only (1 - 1 / (length + 1)) so we will additionally adjust freq by
|
|
||||||
// (1 - 1 / length) / (1 - 1 / (length + 1)) = (1 - 1 / (length * length))
|
|
||||||
const int normalizedScoreNotEnoughDemotionAdjustment = 100 - 100 / (totalLength * totalLength);
|
|
||||||
multiplyRate(normalizedScoreNotEnoughDemotionAdjustment, &totalFreq);
|
|
||||||
|
|
||||||
// At this moment, totalFreq is calculated by the following formula:
|
|
||||||
// (firstFreq * (1 - 1 / (firstWordLength + 1)) + secondFreq * (1 - 1 / (secondWordLength + 1)))
|
|
||||||
// * (1 - 1 / totalLength) / (1 - 1 / (totalLength + 1))
|
|
||||||
|
|
||||||
multiplyIntCapped(powerIntCapped(typedLetterMultiplier, totalLength), &totalFreq);
|
|
||||||
|
|
||||||
// This is another workaround to offset the demotion which will be done in
|
|
||||||
// calcNormalizedScore in Utils.java.
|
|
||||||
// In calcNormalizedScore the score will be demoted by (1 - 1 / length) so we have to promote
|
|
||||||
// the same amount because we already have adjusted the synthetic freq of this "missing or
|
|
||||||
// mistyped space" suggestion candidate above in this method.
|
|
||||||
const int normalizedScoreDemotionRateOffset = (100 + 100 / totalLength);
|
|
||||||
multiplyRate(normalizedScoreDemotionRateOffset, &totalFreq);
|
|
||||||
|
|
||||||
if (isSpaceProximity) {
|
|
||||||
// A word pair with one space proximity correction
|
|
||||||
if (DEBUG_DICT) {
|
|
||||||
LOGI("Found a word pair with space proximity correction.");
|
|
||||||
}
|
|
||||||
multiplyIntCapped(typedLetterMultiplier, &totalFreq);
|
|
||||||
multiplyRate(WORDS_WITH_PROXIMITY_CHARACTER_DEMOTION_RATE, &totalFreq);
|
|
||||||
}
|
|
||||||
|
|
||||||
multiplyRate(WORDS_WITH_MISSING_SPACE_CHARACTER_DEMOTION_RATE, &totalFreq);
|
|
||||||
return totalFreq;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool UnigramDictionary::getMissingSpaceWords(const int inputLength, const int missingSpacePos) {
|
|
||||||
return getSplitTwoWordsSuggestion(
|
|
||||||
inputLength, 0, missingSpacePos, missingSpacePos, inputLength - missingSpacePos, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool UnigramDictionary::getMistypedSpaceWords(const int inputLength, const int spaceProximityPos) {
|
|
||||||
return getSplitTwoWordsSuggestion(
|
|
||||||
inputLength, 0, spaceProximityPos, spaceProximityPos + 1,
|
|
||||||
inputLength - spaceProximityPos - 1, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline int UnigramDictionary::calculateFinalFreq(const int inputIndex, const int depth,
|
|
||||||
const int matchWeight, const int freq, const bool sameLength,
|
|
||||||
CorrectionState *correctionState) const {
|
|
||||||
const int skipPos = correctionState->getSkipPos();
|
|
||||||
const int excessivePos = correctionState->getExcessivePos();
|
|
||||||
const int transposedPos = correctionState->getTransposedPos();
|
|
||||||
|
|
||||||
// TODO: Demote by edit distance
|
|
||||||
int finalFreq = freq * matchWeight;
|
|
||||||
if (skipPos >= 0) {
|
|
||||||
if (mInputLength >= 2) {
|
|
||||||
const int demotionRate = WORDS_WITH_MISSING_CHARACTER_DEMOTION_RATE
|
|
||||||
* (10 * mInputLength - WORDS_WITH_MISSING_CHARACTER_DEMOTION_START_POS_10X)
|
|
||||||
/ (10 * mInputLength
|
|
||||||
- WORDS_WITH_MISSING_CHARACTER_DEMOTION_START_POS_10X + 10);
|
|
||||||
if (DEBUG_DICT_FULL) {
|
|
||||||
LOGI("Demotion rate for missing character is %d.", demotionRate);
|
|
||||||
}
|
|
||||||
multiplyRate(demotionRate, &finalFreq);
|
|
||||||
} else {
|
|
||||||
finalFreq = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (transposedPos >= 0) multiplyRate(
|
|
||||||
WORDS_WITH_TRANSPOSED_CHARACTERS_DEMOTION_RATE, &finalFreq);
|
|
||||||
if (excessivePos >= 0) {
|
|
||||||
multiplyRate(WORDS_WITH_EXCESSIVE_CHARACTER_DEMOTION_RATE, &finalFreq);
|
|
||||||
if (!mProximityInfo->existsAdjacentProximityChars(inputIndex)) {
|
|
||||||
// If an excessive character is not adjacent to the left char or the right char,
|
|
||||||
// we will demote this word.
|
|
||||||
multiplyRate(WORDS_WITH_EXCESSIVE_CHARACTER_OUT_OF_PROXIMITY_DEMOTION_RATE, &finalFreq);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
int lengthFreq = TYPED_LETTER_MULTIPLIER;
|
|
||||||
multiplyIntCapped(powerIntCapped(TYPED_LETTER_MULTIPLIER, depth), &lengthFreq);
|
|
||||||
if (lengthFreq == matchWeight) {
|
|
||||||
// Full exact match
|
|
||||||
if (depth > 1) {
|
|
||||||
if (DEBUG_DICT) {
|
|
||||||
LOGI("Found full matched word.");
|
|
||||||
}
|
|
||||||
multiplyRate(FULL_MATCHED_WORDS_PROMOTION_RATE, &finalFreq);
|
|
||||||
}
|
|
||||||
if (sameLength && transposedPos < 0 && skipPos < 0 && excessivePos < 0) {
|
|
||||||
finalFreq = capped255MultForFullMatchAccentsOrCapitalizationDifference(finalFreq);
|
|
||||||
}
|
|
||||||
} else if (sameLength && transposedPos < 0 && skipPos < 0 && excessivePos < 0 && depth > 0) {
|
|
||||||
// A word with proximity corrections
|
|
||||||
if (DEBUG_DICT) {
|
|
||||||
LOGI("Found one proximity correction.");
|
|
||||||
}
|
|
||||||
multiplyIntCapped(TYPED_LETTER_MULTIPLIER, &finalFreq);
|
|
||||||
multiplyRate(WORDS_WITH_PROXIMITY_CHARACTER_DEMOTION_RATE, &finalFreq);
|
|
||||||
}
|
|
||||||
if (DEBUG_DICT) {
|
|
||||||
LOGI("calc: %d, %d", depth, sameLength);
|
|
||||||
}
|
|
||||||
if (sameLength) multiplyIntCapped(FULL_WORD_MULTIPLIER, &finalFreq);
|
|
||||||
return finalFreq;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool UnigramDictionary::needsToSkipCurrentNode(const unsigned short c,
|
inline bool UnigramDictionary::needsToSkipCurrentNode(const unsigned short c,
|
||||||
|
@ -586,7 +447,7 @@ inline bool UnigramDictionary::needsToSkipCurrentNode(const unsigned short c,
|
||||||
|
|
||||||
inline void UnigramDictionary::onTerminal(unsigned short int* word, const int depth,
|
inline void UnigramDictionary::onTerminal(unsigned short int* word, const int depth,
|
||||||
const uint8_t* const root, const uint8_t flags, const int pos,
|
const uint8_t* const root, const uint8_t flags, const int pos,
|
||||||
const int inputIndex, const int matchWeight, const int freq, const bool sameLength,
|
const int inputIndex, const int matchCount, const int freq, const bool sameLength,
|
||||||
int* nextLetters, const int nextLettersSize, CorrectionState *correctionState) {
|
int* nextLetters, const int nextLettersSize, CorrectionState *correctionState) {
|
||||||
const int skipPos = correctionState->getSkipPos();
|
const int skipPos = correctionState->getSkipPos();
|
||||||
|
|
||||||
|
@ -594,8 +455,8 @@ inline void UnigramDictionary::onTerminal(unsigned short int* word, const int de
|
||||||
if (isSameAsTyped) return;
|
if (isSameAsTyped) return;
|
||||||
|
|
||||||
if (depth >= MIN_SUGGEST_DEPTH) {
|
if (depth >= MIN_SUGGEST_DEPTH) {
|
||||||
const int finalFreq = calculateFinalFreq(inputIndex, depth, matchWeight,
|
const int finalFreq = correctionState->getFinalFreq(inputIndex, depth, matchCount,
|
||||||
freq, sameLength, correctionState);
|
freq, sameLength);
|
||||||
if (!isSameAsTyped)
|
if (!isSameAsTyped)
|
||||||
addWord(word, depth + 1, finalFreq);
|
addWord(word, depth + 1, finalFreq);
|
||||||
}
|
}
|
||||||
|
@ -605,13 +466,29 @@ inline void UnigramDictionary::onTerminal(unsigned short int* word, const int de
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UnigramDictionary::getSplitTwoWordsSuggestion(const int inputLength,
|
void UnigramDictionary::getSplitTwoWordsSuggestion(
|
||||||
const int firstWordStartPos, const int firstWordLength, const int secondWordStartPos,
|
const int inputLength, CorrectionState* correctionState) {
|
||||||
const int secondWordLength, const bool isSpaceProximity) {
|
const int spaceProximityPos = correctionState->getSpaceProximityPos();
|
||||||
if (inputLength >= MAX_WORD_LENGTH) return false;
|
const int missingSpacePos = correctionState->getMissingSpacePos();
|
||||||
|
if (DEBUG_DICT) {
|
||||||
|
int inputCount = 0;
|
||||||
|
if (spaceProximityPos >= 0) ++inputCount;
|
||||||
|
if (missingSpacePos >= 0) ++inputCount;
|
||||||
|
assert(inputCount <= 1);
|
||||||
|
}
|
||||||
|
const bool isSpaceProximity = spaceProximityPos >= 0;
|
||||||
|
const int firstWordStartPos = 0;
|
||||||
|
const int secondWordStartPos = isSpaceProximity ? (spaceProximityPos + 1) : missingSpacePos;
|
||||||
|
const int firstWordLength = isSpaceProximity ? spaceProximityPos : missingSpacePos;
|
||||||
|
const int secondWordLength = isSpaceProximity
|
||||||
|
? (inputLength - spaceProximityPos - 1)
|
||||||
|
: (inputLength - missingSpacePos);
|
||||||
|
|
||||||
|
if (inputLength >= MAX_WORD_LENGTH) return;
|
||||||
if (0 >= firstWordLength || 0 >= secondWordLength || firstWordStartPos >= secondWordStartPos
|
if (0 >= firstWordLength || 0 >= secondWordLength || firstWordStartPos >= secondWordStartPos
|
||||||
|| firstWordStartPos < 0 || secondWordStartPos + secondWordLength > inputLength)
|
|| firstWordStartPos < 0 || secondWordStartPos + secondWordLength > inputLength)
|
||||||
return false;
|
return;
|
||||||
|
|
||||||
const int newWordLength = firstWordLength + secondWordLength + 1;
|
const int newWordLength = firstWordLength + secondWordLength + 1;
|
||||||
// Allocating variable length array on stack
|
// Allocating variable length array on stack
|
||||||
unsigned short word[newWordLength];
|
unsigned short word[newWordLength];
|
||||||
|
@ -619,7 +496,7 @@ bool UnigramDictionary::getSplitTwoWordsSuggestion(const int inputLength,
|
||||||
if (DEBUG_DICT) {
|
if (DEBUG_DICT) {
|
||||||
LOGI("First freq: %d", firstFreq);
|
LOGI("First freq: %d", firstFreq);
|
||||||
}
|
}
|
||||||
if (firstFreq <= 0) return false;
|
if (firstFreq <= 0) return;
|
||||||
|
|
||||||
for (int i = 0; i < firstWordLength; ++i) {
|
for (int i = 0; i < firstWordLength; ++i) {
|
||||||
word[i] = mWord[i];
|
word[i] = mWord[i];
|
||||||
|
@ -629,21 +506,19 @@ bool UnigramDictionary::getSplitTwoWordsSuggestion(const int inputLength,
|
||||||
if (DEBUG_DICT) {
|
if (DEBUG_DICT) {
|
||||||
LOGI("Second freq: %d", secondFreq);
|
LOGI("Second freq: %d", secondFreq);
|
||||||
}
|
}
|
||||||
if (secondFreq <= 0) return false;
|
if (secondFreq <= 0) return;
|
||||||
|
|
||||||
word[firstWordLength] = SPACE;
|
word[firstWordLength] = SPACE;
|
||||||
for (int i = (firstWordLength + 1); i < newWordLength; ++i) {
|
for (int i = (firstWordLength + 1); i < newWordLength; ++i) {
|
||||||
word[i] = mWord[i - firstWordLength - 1];
|
word[i] = mWord[i - firstWordLength - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
int pairFreq = calcFreqForSplitTwoWords(TYPED_LETTER_MULTIPLIER, firstWordLength,
|
const int pairFreq = mCorrectionState->getFreqForSplitTwoWords(firstFreq, secondFreq);
|
||||||
secondWordLength, firstFreq, secondFreq, isSpaceProximity);
|
|
||||||
if (DEBUG_DICT) {
|
if (DEBUG_DICT) {
|
||||||
LOGI("Split two words: %d, %d, %d, %d, %d", firstFreq, secondFreq, pairFreq, inputLength,
|
LOGI("Split two words: %d, %d, %d, %d", firstFreq, secondFreq, pairFreq, inputLength);
|
||||||
TYPED_LETTER_MULTIPLIER);
|
|
||||||
}
|
}
|
||||||
addWord(word, newWordLength, pairFreq);
|
addWord(word, newWordLength, pairFreq);
|
||||||
return true;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wrapper for getMostFrequentWordLikeInner, which matches it to the previous
|
// Wrapper for getMostFrequentWordLikeInner, which matches it to the previous
|
||||||
|
@ -803,7 +678,7 @@ int UnigramDictionary::getBigramPosition(int pos, unsigned short *word, int offs
|
||||||
// the current node in nextSiblingPosition. Thus, the caller must keep count of the nodes at any
|
// the current node in nextSiblingPosition. Thus, the caller must keep count of the nodes at any
|
||||||
// given level, as output into newCount when traversing this level's parent.
|
// given level, as output into newCount when traversing this level's parent.
|
||||||
inline bool UnigramDictionary::processCurrentNode(const int initialPos, const int initialDepth,
|
inline bool UnigramDictionary::processCurrentNode(const int initialPos, const int initialDepth,
|
||||||
const int maxDepth, const bool initialTraverseAllNodes, int matchWeight, int inputIndex,
|
const int maxDepth, const bool initialTraverseAllNodes, int matchCount, int inputIndex,
|
||||||
const int initialDiffs, int *nextLetters, const int nextLettersSize,
|
const int initialDiffs, int *nextLetters, const int nextLettersSize,
|
||||||
CorrectionState *correctionState, int *newCount, int *newChildrenPosition,
|
CorrectionState *correctionState, int *newCount, int *newChildrenPosition,
|
||||||
bool *newTraverseAllNodes, int *newMatchRate, int *newInputIndex, int *newDiffs,
|
bool *newTraverseAllNodes, int *newMatchRate, int *newInputIndex, int *newDiffs,
|
||||||
|
@ -868,7 +743,7 @@ inline bool UnigramDictionary::processCurrentNode(const int initialPos, const in
|
||||||
// The frequency should be here, because we come here only if this is actually
|
// The frequency should be here, because we come here only if this is actually
|
||||||
// a terminal node, and we are on its last char.
|
// a terminal node, and we are on its last char.
|
||||||
const int freq = BinaryFormat::readFrequencyWithoutMovingPointer(DICT_ROOT, pos);
|
const int freq = BinaryFormat::readFrequencyWithoutMovingPointer(DICT_ROOT, pos);
|
||||||
onTerminal(mWord, depth, DICT_ROOT, flags, pos, inputIndex, matchWeight,
|
onTerminal(mWord, depth, DICT_ROOT, flags, pos, inputIndex, matchCount,
|
||||||
freq, false, nextLetters, nextLettersSize, mCorrectionState);
|
freq, false, nextLetters, nextLettersSize, mCorrectionState);
|
||||||
}
|
}
|
||||||
if (!hasChildren) {
|
if (!hasChildren) {
|
||||||
|
@ -913,13 +788,13 @@ inline bool UnigramDictionary::processCurrentNode(const int initialPos, const in
|
||||||
// If inputIndex is greater than mInputLength, that means there is no
|
// If inputIndex is greater than mInputLength, that means there is no
|
||||||
// proximity chars. So, we don't need to check proximity.
|
// proximity chars. So, we don't need to check proximity.
|
||||||
if (ProximityInfo::SAME_OR_ACCENTED_OR_CAPITALIZED_CHAR == matchedProximityCharId) {
|
if (ProximityInfo::SAME_OR_ACCENTED_OR_CAPITALIZED_CHAR == matchedProximityCharId) {
|
||||||
multiplyIntCapped(TYPED_LETTER_MULTIPLIER, &matchWeight);
|
++matchCount;
|
||||||
}
|
}
|
||||||
const bool isSameAsUserTypedLength = mInputLength == inputIndex + 1
|
const bool isSameAsUserTypedLength = mInputLength == inputIndex + 1
|
||||||
|| (excessivePos == mInputLength - 1 && inputIndex == mInputLength - 2);
|
|| (excessivePos == mInputLength - 1 && inputIndex == mInputLength - 2);
|
||||||
if (isSameAsUserTypedLength && isTerminal) {
|
if (isSameAsUserTypedLength && isTerminal) {
|
||||||
const int freq = BinaryFormat::readFrequencyWithoutMovingPointer(DICT_ROOT, pos);
|
const int freq = BinaryFormat::readFrequencyWithoutMovingPointer(DICT_ROOT, pos);
|
||||||
onTerminal(mWord, depth, DICT_ROOT, flags, pos, inputIndex, matchWeight,
|
onTerminal(mWord, depth, DICT_ROOT, flags, pos, inputIndex, matchCount,
|
||||||
freq, true, nextLetters, nextLettersSize, mCorrectionState);
|
freq, true, nextLetters, nextLettersSize, mCorrectionState);
|
||||||
}
|
}
|
||||||
// This character matched the typed character (enough to traverse the node at least)
|
// This character matched the typed character (enough to traverse the node at least)
|
||||||
|
@ -975,7 +850,7 @@ inline bool UnigramDictionary::processCurrentNode(const int initialPos, const in
|
||||||
// All the output values that are purely computation by this function are held in local
|
// All the output values that are purely computation by this function are held in local
|
||||||
// variables. Output them to the caller.
|
// variables. Output them to the caller.
|
||||||
*newTraverseAllNodes = traverseAllNodes;
|
*newTraverseAllNodes = traverseAllNodes;
|
||||||
*newMatchRate = matchWeight;
|
*newMatchRate = matchCount;
|
||||||
*newDiffs = diffs;
|
*newDiffs = diffs;
|
||||||
*newInputIndex = inputIndex;
|
*newInputIndex = inputIndex;
|
||||||
*newOutputIndex = depth;
|
*newOutputIndex = depth;
|
||||||
|
|
|
@ -74,6 +74,7 @@ public:
|
||||||
virtual ~UnigramDictionary();
|
virtual ~UnigramDictionary();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void getWordSuggestions(ProximityInfo *proximityInfo, const int *xcoordinates,
|
void getWordSuggestions(ProximityInfo *proximityInfo, const int *xcoordinates,
|
||||||
const int *ycoordinates, const int *codes, const int codesSize,
|
const int *ycoordinates, const int *codes, const int codesSize,
|
||||||
unsigned short *outWords, int *frequencies);
|
unsigned short *outWords, int *frequencies);
|
||||||
|
@ -89,13 +90,11 @@ private:
|
||||||
const int transposedPos, int *nextLetters, const int nextLettersSize,
|
const int transposedPos, int *nextLetters, const int nextLettersSize,
|
||||||
const int maxDepth);
|
const int maxDepth);
|
||||||
bool addWord(unsigned short *word, int length, int frequency);
|
bool addWord(unsigned short *word, int length, int frequency);
|
||||||
bool getSplitTwoWordsSuggestion(const int inputLength,
|
void getSplitTwoWordsSuggestion(const int inputLength, CorrectionState *correctionState);
|
||||||
const int firstWordStartPos, const int firstWordLength,
|
void getMissingSpaceWords(
|
||||||
const int secondWordStartPos, const int secondWordLength, const bool isSpaceProximity);
|
const int inputLength, const int missingSpacePos, CorrectionState *correctionState);
|
||||||
bool getMissingSpaceWords(const int inputLength, const int missingSpacePos);
|
void getMistypedSpaceWords(
|
||||||
bool getMistypedSpaceWords(const int inputLength, const int spaceProximityPos);
|
const int inputLength, const int spaceProximityPos, CorrectionState *correctionState);
|
||||||
int calculateFinalFreq(const int inputIndex, const int depth, const int snr,
|
|
||||||
const int freq, const bool sameLength, CorrectionState *correctionState) const;
|
|
||||||
void onTerminal(unsigned short int* word, const int depth,
|
void onTerminal(unsigned short int* word, const int depth,
|
||||||
const uint8_t* const root, const uint8_t flags, const int pos,
|
const uint8_t* const root, const uint8_t flags, const int pos,
|
||||||
const int inputIndex, const int matchWeight, const int freq, const bool sameLength,
|
const int inputIndex, const int matchWeight, const int freq, const bool sameLength,
|
||||||
|
@ -145,7 +144,7 @@ private:
|
||||||
|
|
||||||
int mStackChildCount[MAX_WORD_LENGTH_INTERNAL];
|
int mStackChildCount[MAX_WORD_LENGTH_INTERNAL];
|
||||||
bool mStackTraverseAll[MAX_WORD_LENGTH_INTERNAL];
|
bool mStackTraverseAll[MAX_WORD_LENGTH_INTERNAL];
|
||||||
int mStackNodeFreq[MAX_WORD_LENGTH_INTERNAL];
|
int mStackMatchCount[MAX_WORD_LENGTH_INTERNAL];
|
||||||
int mStackInputIndex[MAX_WORD_LENGTH_INTERNAL];
|
int mStackInputIndex[MAX_WORD_LENGTH_INTERNAL];
|
||||||
int mStackDiffs[MAX_WORD_LENGTH_INTERNAL];
|
int mStackDiffs[MAX_WORD_LENGTH_INTERNAL];
|
||||||
int mStackSiblingPos[MAX_WORD_LENGTH_INTERNAL];
|
int mStackSiblingPos[MAX_WORD_LENGTH_INTERNAL];
|
||||||
|
|
Loading…
Reference in a new issue