aboutsummaryrefslogtreecommitdiffstats
path: root/native
diff options
context:
space:
mode:
Diffstat (limited to 'native')
-rw-r--r--native/jni/Android.mk2
-rw-r--r--native/jni/com_android_inputmethod_latin_NativeUtils.cpp40
-rw-r--r--native/jni/com_android_inputmethod_latin_NativeUtils.h29
-rw-r--r--native/jni/jni_common.cpp6
-rw-r--r--native/jni/src/correction.cpp86
-rw-r--r--native/jni/src/correction.h20
-rw-r--r--native/jni/src/defines.h15
-rw-r--r--native/jni/src/proximity_info.cpp270
-rw-r--r--native/jni/src/proximity_info.h108
-rw-r--r--native/jni/src/proximity_info_state.cpp139
-rw-r--r--native/jni/src/proximity_info_state.h219
-rw-r--r--native/jni/src/unigram_dictionary.cpp76
-rw-r--r--native/jni/src/unigram_dictionary.h35
13 files changed, 632 insertions, 413 deletions
diff --git a/native/jni/Android.mk b/native/jni/Android.mk
index d53757fd4..edcc0677d 100644
--- a/native/jni/Android.mk
+++ b/native/jni/Android.mk
@@ -35,6 +35,7 @@ LOCAL_CFLAGS += -Wno-unused-parameter -Wno-unused-function
LATIN_IME_JNI_SRC_FILES := \
com_android_inputmethod_keyboard_ProximityInfo.cpp \
com_android_inputmethod_latin_BinaryDictionary.cpp \
+ com_android_inputmethod_latin_NativeUtils.cpp \
jni_common.cpp
LATIN_IME_CORE_SRC_FILES := \
@@ -45,6 +46,7 @@ LATIN_IME_CORE_SRC_FILES := \
correction.cpp \
dictionary.cpp \
proximity_info.cpp \
+ proximity_info_state.cpp \
unigram_dictionary.cpp
LOCAL_SRC_FILES := \
diff --git a/native/jni/com_android_inputmethod_latin_NativeUtils.cpp b/native/jni/com_android_inputmethod_latin_NativeUtils.cpp
new file mode 100644
index 000000000..c1e586a4b
--- /dev/null
+++ b/native/jni/com_android_inputmethod_latin_NativeUtils.cpp
@@ -0,0 +1,40 @@
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#include "com_android_inputmethod_latin_NativeUtils.h"
+#include "jni.h"
+#include "jni_common.h"
+
+#include <math.h>
+
+namespace latinime {
+
+static float latinime_NativeUtils_powf(float x, float y) {
+ return powf(x, y);
+}
+
+static JNINativeMethod sMethods[] = {
+ {"powf", "(FF)F", (void*)latinime_NativeUtils_powf}
+};
+
+int register_NativeUtils(JNIEnv *env) {
+ const char* const kClassPathName = "com/android/inputmethod/latin/NativeUtils";
+ return registerNativeMethods(env, kClassPathName, sMethods,
+ sizeof(sMethods) / sizeof(sMethods[0]));
+}
+
+} // namespace latinime
diff --git a/native/jni/com_android_inputmethod_latin_NativeUtils.h b/native/jni/com_android_inputmethod_latin_NativeUtils.h
new file mode 100644
index 000000000..13a348a5c
--- /dev/null
+++ b/native/jni/com_android_inputmethod_latin_NativeUtils.h
@@ -0,0 +1,29 @@
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#ifndef _COM_ANDROID_INPUTMETHOD_LATIN_NATIVEUTILS_H
+#define _COM_ANDROID_INPUTMETHOD_LATIN_NATIVEUTILS_H
+
+#include "jni.h"
+
+namespace latinime {
+
+int register_NativeUtils(JNIEnv *env);
+
+}
+
+#endif // _COM_ANDROID_INPUTMETHOD_LATIN_NATIVEUTILS_H
diff --git a/native/jni/jni_common.cpp b/native/jni/jni_common.cpp
index b9e2c3255..1314bab27 100644
--- a/native/jni/jni_common.cpp
+++ b/native/jni/jni_common.cpp
@@ -19,6 +19,7 @@
#include "com_android_inputmethod_keyboard_ProximityInfo.h"
#include "com_android_inputmethod_latin_BinaryDictionary.h"
+#include "com_android_inputmethod_latin_NativeUtils.h"
#include "defines.h"
#include "jni.h"
#include "proximity_info.h"
@@ -52,6 +53,11 @@ jint JNI_OnLoad(JavaVM* vm, void* reserved) {
goto bail;
}
+ if (!register_NativeUtils(env)) {
+ AKLOGE("ERROR: NativeUtils native registration failed");
+ goto bail;
+ }
+
/* success -- return valid version number */
result = JNI_VERSION_1_4;
diff --git a/native/jni/src/correction.cpp b/native/jni/src/correction.cpp
index 99f5b92c1..3957b013a 100644
--- a/native/jni/src/correction.cpp
+++ b/native/jni/src/correction.cpp
@@ -27,6 +27,7 @@
#include "defines.h"
#include "dictionary.h"
#include "proximity_info.h"
+#include "proximity_info_state.h"
namespace latinime {
@@ -97,7 +98,7 @@ inline static int getCurrentEditDistance(int *editDistanceTable, const int editD
static const char QUOTE = '\'';
inline bool Correction::isQuote(const unsigned short c) {
- const unsigned short userTypedChar = mProximityInfo->getPrimaryCharAt(mInputIndex);
+ const unsigned short userTypedChar = mProximityInfoState.getPrimaryCharAt(mInputIndex);
return (c == QUOTE && userTypedChar != QUOTE);
}
@@ -282,7 +283,7 @@ bool Correction::needsToPrune() const {
void Correction::addCharToCurrentWord(const int32_t c) {
mWord[mOutputIndex] = c;
- const unsigned short *primaryInputWord = mProximityInfo->getPrimaryInputWord();
+ const unsigned short *primaryInputWord = mProximityInfoState.getPrimaryInputWord();
calcEditDistanceOneStep(mEditDistanceTable, primaryInputWord, mInputLength,
mWord, mOutputIndex + 1);
}
@@ -308,13 +309,12 @@ Correction::CorrectionType Correction::processUnrelatedCorrectionType() {
return UNRELATED;
}
-inline bool isEquivalentChar(ProximityInfo::ProximityType type) {
- return type == ProximityInfo::EQUIVALENT_CHAR;
+inline bool isEquivalentChar(ProximityType type) {
+ return type == EQUIVALENT_CHAR;
}
-inline bool isProximityCharOrEquivalentChar(ProximityInfo::ProximityType type) {
- return type == ProximityInfo::EQUIVALENT_CHAR
- || type == ProximityInfo::NEAR_PROXIMITY_CHAR;
+inline bool isProximityCharOrEquivalentChar(ProximityType type) {
+ return type == EQUIVALENT_CHAR || type == NEAR_PROXIMITY_CHAR;
}
Correction::CorrectionType Correction::processCharAndCalcState(
@@ -335,19 +335,19 @@ Correction::CorrectionType Correction::processCharAndCalcState(
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, &proximityIndex);
+ const ProximityType matchId = mProximityInfoState.getMatchedProximityId(
+ mInputIndex, c, true, &proximityIndex);
if (isEquivalentChar(matchId)) {
mLastCharExceeded = false;
--mExcessiveCount;
mDistances[mOutputIndex] =
- mProximityInfo->getNormalizedSquaredDistance(mInputIndex, 0);
- } else if (matchId == ProximityInfo::NEAR_PROXIMITY_CHAR) {
+ mProximityInfoState.getNormalizedSquaredDistance(mInputIndex, 0);
+ } else if (matchId == NEAR_PROXIMITY_CHAR) {
mLastCharExceeded = false;
--mExcessiveCount;
++mProximityCount;
- mDistances[mOutputIndex] =
- mProximityInfo->getNormalizedSquaredDistance(mInputIndex, proximityIndex);
+ mDistances[mOutputIndex] = mProximityInfoState.getNormalizedSquaredDistance(
+ mInputIndex, proximityIndex);
}
if (!isQuote(c)) {
incrementInputIndex();
@@ -388,7 +388,8 @@ Correction::CorrectionType Correction::processCharAndCalcState(
bool secondTransposing = false;
if (mTransposedCount % 2 == 1) {
- if (isEquivalentChar(mProximityInfo->getMatchedProximityId(mInputIndex - 1, c, false))) {
+ if (isEquivalentChar(mProximityInfoState.getMatchedProximityId(
+ mInputIndex - 1, c, false))) {
++mTransposedCount;
secondTransposing = true;
} else if (mCorrectionStates[mOutputIndex].mExceeding) {
@@ -417,17 +418,17 @@ Correction::CorrectionType Correction::processCharAndCalcState(
? (noCorrectionsHappenedSoFar || mProximityCount == 0)
: (noCorrectionsHappenedSoFar && mProximityCount == 0);
- ProximityInfo::ProximityType matchedProximityCharId = secondTransposing
- ? ProximityInfo::EQUIVALENT_CHAR
- : mProximityInfo->getMatchedProximityId(
+ ProximityType matchedProximityCharId = secondTransposing
+ ? EQUIVALENT_CHAR
+ : mProximityInfoState.getMatchedProximityId(
mInputIndex, c, checkProximityChars, &proximityIndex);
- if (ProximityInfo::UNRELATED_CHAR == matchedProximityCharId
- || ProximityInfo::ADDITIONAL_PROXIMITY_CHAR == matchedProximityCharId) {
+ if (UNRELATED_CHAR == matchedProximityCharId
+ || ADDITIONAL_PROXIMITY_CHAR == matchedProximityCharId) {
if (canTryCorrection && mOutputIndex > 0
&& mCorrectionStates[mOutputIndex].mProximityMatching
&& mCorrectionStates[mOutputIndex].mExceeding
- && isEquivalentChar(mProximityInfo->getMatchedProximityId(
+ && isEquivalentChar(mProximityInfoState.getMatchedProximityId(
mInputIndex, mWord[mOutputIndex - 1], false))) {
if (DEBUG_CORRECTION
&& (INPUTLENGTH_FOR_DEBUG <= 0 || INPUTLENGTH_FOR_DEBUG == mInputLength)
@@ -446,14 +447,14 @@ 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(
+ matchedProximityCharId = mProximityInfoState.getMatchedProximityId(
mInputIndex, c, mProximityCount == 0, &proximityIndex);
}
}
- if (ProximityInfo::UNRELATED_CHAR == matchedProximityCharId
- || ProximityInfo::ADDITIONAL_PROXIMITY_CHAR == matchedProximityCharId) {
- if (ProximityInfo::ADDITIONAL_PROXIMITY_CHAR == matchedProximityCharId) {
+ if (UNRELATED_CHAR == matchedProximityCharId
+ || ADDITIONAL_PROXIMITY_CHAR == matchedProximityCharId) {
+ if (ADDITIONAL_PROXIMITY_CHAR == matchedProximityCharId) {
mAdditionalProximityMatching = true;
}
// TODO: Optimize
@@ -463,10 +464,10 @@ Correction::CorrectionType Correction::processCharAndCalcState(
if (mInputIndex < mInputLength - 1 && mOutputIndex > 0 && mTransposedCount > 0
&& !mCorrectionStates[mOutputIndex].mTransposing
&& mCorrectionStates[mOutputIndex - 1].mTransposing
- && isEquivalentChar(mProximityInfo->getMatchedProximityId(
+ && isEquivalentChar(mProximityInfoState.getMatchedProximityId(
mInputIndex, mWord[mOutputIndex - 1], false))
&& isEquivalentChar(
- mProximityInfo->getMatchedProximityId(mInputIndex + 1, c, false))) {
+ mProximityInfoState.getMatchedProximityId(mInputIndex + 1, c, false))) {
// Conversion t->e
// Example:
// occaisional -> occa sional
@@ -478,7 +479,7 @@ Correction::CorrectionType Correction::processCharAndCalcState(
&& !mCorrectionStates[mOutputIndex].mTransposing
&& mCorrectionStates[mOutputIndex - 1].mTransposing
&& isEquivalentChar(
- mProximityInfo->getMatchedProximityId(mInputIndex - 1, c, false))) {
+ mProximityInfoState.getMatchedProximityId(mInputIndex - 1, c, false))) {
// Conversion t->s
// Example:
// chcolate -> chocolate
@@ -490,7 +491,7 @@ Correction::CorrectionType Correction::processCharAndCalcState(
&& mCorrectionStates[mOutputIndex].mProximityMatching
&& mCorrectionStates[mOutputIndex].mSkipping
&& isEquivalentChar(
- mProximityInfo->getMatchedProximityId(mInputIndex - 1, c, false))) {
+ mProximityInfoState.getMatchedProximityId(mInputIndex - 1, c, false))) {
// Conversion p->s
// Note: This logic tries saving cases like contrst --> contrast -- "a" is one of
// proximity chars of "s", but it should rather be handled as a skipped char.
@@ -502,7 +503,7 @@ Correction::CorrectionType Correction::processCharAndCalcState(
&& mCorrectionStates[mOutputIndex].mSkipping
&& mCorrectionStates[mOutputIndex].mAdditionalProximityMatching
&& isProximityCharOrEquivalentChar(
- mProximityInfo->getMatchedProximityId(mInputIndex + 1, c, false))) {
+ mProximityInfoState.getMatchedProximityId(mInputIndex + 1, c, false))) {
// Conversion s->a
incrementInputIndex();
--mSkippedCount;
@@ -511,7 +512,7 @@ Correction::CorrectionType Correction::processCharAndCalcState(
mDistances[mOutputIndex] = ADDITIONAL_PROXIMITY_CHAR_DISTANCE_INFO;
} else if ((mExceeding || mTransposing) && mInputIndex - 1 < mInputLength
&& isEquivalentChar(
- mProximityInfo->getMatchedProximityId(mInputIndex + 1, c, false))) {
+ mProximityInfoState.getMatchedProximityId(mInputIndex + 1, c, false))) {
// 1.2. Excessive or transpose correction
if (mTransposing) {
++mTransposedCount;
@@ -543,7 +544,7 @@ Correction::CorrectionType Correction::processCharAndCalcState(
mTransposedCount, mExcessiveCount, c);
}
return processSkipChar(c, isTerminal, false);
- } else if (ProximityInfo::ADDITIONAL_PROXIMITY_CHAR == matchedProximityCharId) {
+ } else if (ADDITIONAL_PROXIMITY_CHAR == matchedProximityCharId) {
// As a last resort, use additional proximity characters
mProximityMatching = true;
++mProximityCount;
@@ -573,12 +574,12 @@ Correction::CorrectionType Correction::processCharAndCalcState(
} else if (isEquivalentChar(matchedProximityCharId)) {
mMatching = true;
++mEquivalentCharCount;
- mDistances[mOutputIndex] = mProximityInfo->getNormalizedSquaredDistance(mInputIndex, 0);
- } else if (ProximityInfo::NEAR_PROXIMITY_CHAR == matchedProximityCharId) {
+ mDistances[mOutputIndex] = mProximityInfoState.getNormalizedSquaredDistance(mInputIndex, 0);
+ } else if (NEAR_PROXIMITY_CHAR == matchedProximityCharId) {
mProximityMatching = true;
++mProximityCount;
mDistances[mOutputIndex] =
- mProximityInfo->getNormalizedSquaredDistance(mInputIndex, proximityIndex);
+ mProximityInfoState.getNormalizedSquaredDistance(mInputIndex, proximityIndex);
if (DEBUG_CORRECTION
&& (INPUTLENGTH_FOR_DEBUG <= 0 || INPUTLENGTH_FOR_DEBUG == mInputLength)
&& (MIN_OUTPUT_INDEX_FOR_DEBUG <= 0
@@ -662,7 +663,7 @@ int Correction::RankingAlgorithm::calculateFinalProbability(const int inputIndex
const int excessivePos = correction->getExcessivePos();
const int typedLetterMultiplier = correction->TYPED_LETTER_MULTIPLIER;
const int fullWordMultiplier = correction->FULL_WORD_MULTIPLIER;
- const ProximityInfo *proximityInfo = correction->mProximityInfo;
+ const ProximityInfoState *proximityInfoState = &correction->mProximityInfoState;
const int skippedCount = correction->mSkippedCount;
const int transposedCount = correction->mTransposedCount / 2;
const int excessiveCount = correction->mExcessiveCount + correction->mTransposedCount % 2;
@@ -685,7 +686,7 @@ int Correction::RankingAlgorithm::calculateFinalProbability(const int inputIndex
const bool skipped = skippedCount > 0;
const int quoteDiffCount = max(0, getQuoteCount(word, outputLength)
- - getQuoteCount(proximityInfo->getPrimaryInputWord(), inputLength));
+ - getQuoteCount(proximityInfoState->getPrimaryInputWord(), inputLength));
// TODO: Calculate edit distance for transposed and excessive
int ed = 0;
@@ -737,8 +738,7 @@ int Correction::RankingAlgorithm::calculateFinalProbability(const int inputIndex
multiplyIntCapped(matchWeight, &finalFreq);
}
- if (proximityInfo->getMatchedProximityId(0, word[0], true)
- == ProximityInfo::UNRELATED_CHAR) {
+ if (proximityInfoState->getMatchedProximityId(0, word[0], true) == UNRELATED_CHAR) {
multiplyRate(FIRST_CHAR_DIFFERENT_DEMOTION_RATE, &finalFreq);
}
@@ -764,7 +764,7 @@ int Correction::RankingAlgorithm::calculateFinalProbability(const int inputIndex
// Demotion for a word with excessive character
if (excessiveCount > 0) {
multiplyRate(WORDS_WITH_EXCESSIVE_CHARACTER_DEMOTION_RATE, &finalFreq);
- if (!lastCharExceeded && !proximityInfo->existsAdjacentProximityChars(excessivePos)) {
+ if (!lastCharExceeded && !proximityInfoState->existsAdjacentProximityChars(excessivePos)) {
if (DEBUG_DICT_FULL) {
AKLOGI("Double excessive demotion");
}
@@ -775,8 +775,9 @@ int Correction::RankingAlgorithm::calculateFinalProbability(const int inputIndex
}
const bool performTouchPositionCorrection =
- CALIBRATE_SCORE_BY_TOUCH_COORDINATES && proximityInfo->touchPositionCorrectionEnabled()
- && skippedCount == 0 && excessiveCount == 0 && transposedCount == 0;
+ CALIBRATE_SCORE_BY_TOUCH_COORDINATES
+ && proximityInfoState->touchPositionCorrectionEnabled()
+ && skippedCount == 0 && excessiveCount == 0 && transposedCount == 0;
// Score calibration by touch coordinates is being done only for pure-fat finger typing error
// cases.
int additionalProximityCount = 0;
@@ -796,7 +797,7 @@ int Correction::RankingAlgorithm::calculateFinalProbability(const int inputIndex
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;
+ / ProximityInfoState::NORMALIZED_SQUARED_DISTANCE_SCALING_FACTOR;
const float factor = max((x < R1)
? (A * (R1 - x) + B * x) / R1
: (B * (R2 - x) + C * (x - R1)) / (R2 - R1), MIN);
@@ -1146,5 +1147,4 @@ float Correction::RankingAlgorithm::calcNormalizedScore(const unsigned short* be
const float weight = 1.0 - (float) distance / afterLength;
return (score / maxScore) * weight;
}
-
} // namespace latinime
diff --git a/native/jni/src/correction.h b/native/jni/src/correction.h
index 3300a8491..60d7dc33f 100644
--- a/native/jni/src/correction.h
+++ b/native/jni/src/correction.h
@@ -19,9 +19,10 @@
#include <assert.h>
#include <stdint.h>
-#include "correction_state.h"
+#include "correction_state.h"
#include "defines.h"
+#include "proximity_info_state.h"
namespace latinime {
@@ -178,6 +179,21 @@ class Correction {
static const int FULL_WORD_MULTIPLIER = 2;
};
+ // proximity info state
+ void initInputParams(const ProximityInfo *proximityInfo, const int32_t *inputCodes,
+ const int inputLength, const int *xCoordinates, const int *yCoordinates) {
+ mProximityInfoState.initInputParams(
+ proximityInfo, inputCodes, inputLength, xCoordinates, yCoordinates);
+ }
+
+ const unsigned short* getPrimaryInputWord() const {
+ return mProximityInfoState.getPrimaryInputWord();
+ }
+
+ unsigned short getPrimaryCharAt(const int index) const {
+ return mProximityInfoState.getPrimaryCharAt(index);
+ }
+
private:
inline void incrementInputIndex();
inline void incrementOutputIndex();
@@ -240,7 +256,7 @@ class Correction {
bool mExceeding;
bool mTransposing;
bool mSkipping;
-
+ ProximityInfoState mProximityInfoState;
};
} // namespace latinime
#endif // LATINIME_CORRECTION_H
diff --git a/native/jni/src/defines.h b/native/jni/src/defines.h
index cd2fc634a..e4c6753f4 100644
--- a/native/jni/src/defines.h
+++ b/native/jni/src/defines.h
@@ -225,6 +225,9 @@ static inline void prof_out(void) {
// This is only used for the size of array. Not to be used in c functions.
#define MAX_WORD_LENGTH_INTERNAL 48
+// This must be the same as ProximityInfo#MAX_PROXIMITY_CHARS_SIZE, currently it's 16.
+#define MAX_PROXIMITY_CHARS_SIZE_INTERNAL 16
+
// This must be equal to ADDITIONAL_PROXIMITY_CHAR_DELIMITER_CODE in KeyDetector.java
#define ADDITIONAL_PROXIMITY_CHAR_DELIMITER_CODE 2
@@ -289,4 +292,16 @@ template<typename T> inline T max(T a, T b) { return a > b ? a : b; }
#define INPUTLENGTH_FOR_DEBUG -1
#define MIN_OUTPUT_INDEX_FOR_DEBUG -1
+// Used as a return value for character comparison
+typedef enum {
+ // Same char, possibly with different case or accent
+ EQUIVALENT_CHAR,
+ // It is a char located nearby on the keyboard
+ NEAR_PROXIMITY_CHAR,
+ // It is an unrelated char
+ UNRELATED_CHAR,
+ // Additional proximity char which can differ by language.
+ ADDITIONAL_PROXIMITY_CHAR
+} ProximityType;
+
#endif // LATINIME_DEFINES_H
diff --git a/native/jni/src/proximity_info.cpp b/native/jni/src/proximity_info.cpp
index 960d40119..d1aa66488 100644
--- a/native/jni/src/proximity_info.cpp
+++ b/native/jni/src/proximity_info.cpp
@@ -24,6 +24,7 @@
#include "defines.h"
#include "dictionary.h"
#include "proximity_info.h"
+#include "proximity_info_state.h"
namespace latinime {
@@ -51,23 +52,14 @@ ProximityInfo::ProximityInfo(const std::string localeStr, const int maxProximity
HAS_TOUCH_POSITION_CORRECTION_DATA(keyCount > 0 && keyXCoordinates && keyYCoordinates
&& keyWidths && keyHeights && keyCharCodes && sweetSpotCenterXs
&& sweetSpotCenterYs && sweetSpotRadii),
- mLocaleStr(localeStr),
- mInputXCoordinates(0), mInputYCoordinates(0),
- mTouchPositionCorrectionEnabled(false) {
- const int proximityGridLength = GRID_WIDTH * GRID_HEIGHT * MAX_PROXIMITY_CHARS_SIZE;
- mProximityCharsArray = new int32_t[proximityGridLength];
- mInputCodes = new int32_t[MAX_PROXIMITY_CHARS_SIZE * MAX_WORD_LENGTH_INTERNAL];
+ mLocaleStr(localeStr) {
if (DEBUG_PROXIMITY_INFO) {
AKLOGI("Create proximity info array %d", proximityGridLength);
}
+ const int proximityGridLength = GRID_WIDTH * GRID_HEIGHT * MAX_PROXIMITY_CHARS_SIZE;
+ mProximityCharsArray = new int32_t[proximityGridLength];
memcpy(mProximityCharsArray, proximityCharsArray,
proximityGridLength * sizeof(mProximityCharsArray[0]));
- const int normalizedSquaredDistancesLength =
- MAX_PROXIMITY_CHARS_SIZE * MAX_WORD_LENGTH_INTERNAL;
- mNormalizedSquaredDistances = new int[normalizedSquaredDistancesLength];
- for (int i = 0; i < normalizedSquaredDistancesLength; ++i) {
- mNormalizedSquaredDistances[i] = NOT_A_DISTANCE;
- }
copyOrFillZero(mKeyXCoordinates, keyXCoordinates, KEY_COUNT * sizeof(mKeyXCoordinates[0]));
copyOrFillZero(mKeyYCoordinates, keyYCoordinates, KEY_COUNT * sizeof(mKeyYCoordinates[0]));
@@ -96,9 +88,7 @@ void ProximityInfo::initializeCodeToKeyIndex() {
}
ProximityInfo::~ProximityInfo() {
- delete[] mNormalizedSquaredDistances;
delete[] mProximityCharsArray;
- delete[] mInputCodes;
}
inline int ProximityInfo::getStartIndexFromCoordinates(const int x, const int y) const {
@@ -119,26 +109,18 @@ bool ProximityInfo::hasSpaceProximity(const int x, const int y) const {
if (DEBUG_PROXIMITY_INFO) {
AKLOGI("hasSpaceProximity: index %d, %d, %d", startIndex, x, y);
}
+ int32_t* proximityCharsArray = mProximityCharsArray;
for (int i = 0; i < MAX_PROXIMITY_CHARS_SIZE; ++i) {
if (DEBUG_PROXIMITY_INFO) {
AKLOGI("Index: %d", mProximityCharsArray[startIndex + i]);
}
- if (mProximityCharsArray[startIndex + i] == KEYCODE_SPACE) {
+ if (proximityCharsArray[startIndex + i] == KEYCODE_SPACE) {
return true;
}
}
return false;
}
-bool ProximityInfo::isOnKey(const int keyId, const int x, const int y) const {
- if (keyId < 0) return true; // NOT_A_ID is -1, but return whenever < 0 just in case
- const int left = mKeyXCoordinates[keyId];
- const int top = mKeyYCoordinates[keyId];
- const int right = left + mKeyWidths[keyId] + 1;
- const int bottom = top + mKeyHeights[keyId];
- return left < right && top < bottom && x >= left && x < right && y >= top && y < bottom;
-}
-
int ProximityInfo::squaredDistanceToEdge(const int keyId, const int x, const int y) const {
if (keyId < 0) return true; // NOT_A_ID is -1, but return whenever < 0 just in case
const int left = mKeyXCoordinates[keyId];
@@ -154,12 +136,13 @@ int ProximityInfo::squaredDistanceToEdge(const int keyId, const int x, const int
void ProximityInfo::calculateNearbyKeyCodes(
const int x, const int y, const int32_t primaryKey, int *inputCodes) const {
+ int32_t *proximityCharsArray = mProximityCharsArray;
int insertPos = 0;
inputCodes[insertPos++] = primaryKey;
const int startIndex = getStartIndexFromCoordinates(x, y);
if (startIndex >= 0) {
for (int i = 0; i < MAX_PROXIMITY_CHARS_SIZE; ++i) {
- const int32_t c = mProximityCharsArray[startIndex + i];
+ const int32_t c = proximityCharsArray[startIndex + i];
if (c < KEYCODE_SPACE || c == primaryKey) {
continue;
}
@@ -216,115 +199,6 @@ void ProximityInfo::calculateNearbyKeyCodes(
}
}
-void ProximityInfo::setInputParams(const int32_t* inputCodes, const int inputLength,
- const int* xCoordinates, const int* yCoordinates) {
- memset(mInputCodes, 0,
- MAX_WORD_LENGTH_INTERNAL * MAX_PROXIMITY_CHARS_SIZE * sizeof(mInputCodes[0]));
-
- for (int i = 0; i < inputLength; ++i) {
- const int32_t primaryKey = inputCodes[i];
- const int x = xCoordinates[i];
- const int y = yCoordinates[i];
- int *proximities = &mInputCodes[i * MAX_PROXIMITY_CHARS_SIZE];
- calculateNearbyKeyCodes(x, y, primaryKey, proximities);
- }
-
- if (DEBUG_PROXIMITY_CHARS) {
- for (int i = 0; i < inputLength; ++i) {
- AKLOGI("---");
- for (int j = 0; j < MAX_PROXIMITY_CHARS_SIZE; ++j) {
- int icc = mInputCodes[i * MAX_PROXIMITY_CHARS_SIZE + j];
- int icfjc = inputCodes[i * MAX_PROXIMITY_CHARS_SIZE + j];
- icc+= 0;
- icfjc += 0;
- AKLOGI("--- (%d)%c,%c", i, icc, icfjc);
- AKLOGI("--- A<%d>,B<%d>", icc, icfjc);
- }
- }
- }
- //Keep for debug, sorry
- //for (int i = 0; i < MAX_WORD_LENGTH_INTERNAL * MAX_PROXIMITY_CHARS_SIZE; ++i) {
- //if (i < inputLength * MAX_PROXIMITY_CHARS_SIZE) {
- //mInputCodes[i] = mInputCodesFromJava[i];
- //} else {
- // mInputCodes[i] = 0;
- // }
- //}
- mInputXCoordinates = xCoordinates;
- mInputYCoordinates = yCoordinates;
- mTouchPositionCorrectionEnabled =
- HAS_TOUCH_POSITION_CORRECTION_DATA && xCoordinates && yCoordinates;
- mInputLength = inputLength;
- for (int i = 0; i < inputLength; ++i) {
- mPrimaryInputWord[i] = getPrimaryCharAt(i);
- }
- mPrimaryInputWord[inputLength] = 0;
- if (DEBUG_PROXIMITY_CHARS) {
- AKLOGI("--- setInputParams");
- }
- for (int i = 0; i < mInputLength; ++i) {
- const int *proximityChars = getProximityCharsAt(i);
- const int primaryKey = proximityChars[0];
- const int x = xCoordinates[i];
- const int y = yCoordinates[i];
- if (DEBUG_PROXIMITY_CHARS) {
- int a = x + y + primaryKey;
- a += 0;
- AKLOGI("--- Primary = %c, x = %d, y = %d", primaryKey, x, y);
- // Keep debug code just in case
- //int proximities[50];
- //for (int m = 0; m < 50; ++m) {
- //proximities[m] = 0;
- //}
- //calculateNearbyKeyCodes(x, y, primaryKey, proximities);
- //for (int l = 0; l < 50 && proximities[l] > 0; ++l) {
- //if (DEBUG_PROXIMITY_CHARS) {
- //AKLOGI("--- native Proximity (%d) = %c", l, proximities[l]);
- //}
- //}
- }
- for (int j = 0; j < MAX_PROXIMITY_CHARS_SIZE && proximityChars[j] > 0; ++j) {
- const int currentChar = proximityChars[j];
- const float squaredDistance = hasInputCoordinates()
- ? calculateNormalizedSquaredDistance(getKeyIndex(currentChar), i)
- : NOT_A_DISTANCE_FLOAT;
- if (squaredDistance >= 0.0f) {
- mNormalizedSquaredDistances[i * MAX_PROXIMITY_CHARS_SIZE + j] =
- (int)(squaredDistance * NORMALIZED_SQUARED_DISTANCE_SCALING_FACTOR);
- } else {
- mNormalizedSquaredDistances[i * MAX_PROXIMITY_CHARS_SIZE + j] = (j == 0)
- ? EQUIVALENT_CHAR_WITHOUT_DISTANCE_INFO
- : PROXIMITY_CHAR_WITHOUT_DISTANCE_INFO;
- }
- if (DEBUG_PROXIMITY_CHARS) {
- AKLOGI("--- Proximity (%d) = %c", j, currentChar);
- }
- }
- }
-}
-
-inline float square(const float x) { return x * x; }
-
-float ProximityInfo::calculateNormalizedSquaredDistance(
- const int keyIndex, const int inputIndex) const {
- if (keyIndex == NOT_AN_INDEX) {
- return NOT_A_DISTANCE_FLOAT;
- }
- if (!hasSweetSpotData(keyIndex)) {
- return NOT_A_DISTANCE_FLOAT;
- }
- if (NOT_A_COORDINATE == mInputXCoordinates[inputIndex]) {
- return NOT_A_DISTANCE_FLOAT;
- }
- const float squaredDistance = calculateSquaredDistanceFromSweetSpotCenter(keyIndex, inputIndex);
- const float squaredRadius = square(mSweetSpotRadii[keyIndex]);
- return squaredDistance / squaredRadius;
-}
-
-bool ProximityInfo::hasInputCoordinates() const {
- return mInputXCoordinates && mInputYCoordinates;
-}
-
int ProximityInfo::getKeyIndex(const int c) const {
if (KEY_COUNT == 0) {
// We do not have the coordinate data
@@ -336,132 +210,4 @@ int ProximityInfo::getKeyIndex(const int c) const {
}
return mCodeToKeyIndex[baseLowerC];
}
-
-float ProximityInfo::calculateSquaredDistanceFromSweetSpotCenter(
- const int keyIndex, const int inputIndex) const {
- const float sweetSpotCenterX = mSweetSpotCenterXs[keyIndex];
- const float sweetSpotCenterY = mSweetSpotCenterYs[keyIndex];
- const float inputX = (float)mInputXCoordinates[inputIndex];
- const float inputY = (float)mInputYCoordinates[inputIndex];
- return square(inputX - sweetSpotCenterX) + square(inputY - sweetSpotCenterY);
-}
-
-inline const int* ProximityInfo::getProximityCharsAt(const int index) const {
- return mInputCodes + (index * MAX_PROXIMITY_CHARS_SIZE);
-}
-
-unsigned short ProximityInfo::getPrimaryCharAt(const int index) const {
- return getProximityCharsAt(index)[0];
-}
-
-inline bool ProximityInfo::existsCharInProximityAt(const int index, const int c) const {
- const int *chars = getProximityCharsAt(index);
- int i = 0;
- while (chars[i] > 0 && i < MAX_PROXIMITY_CHARS_SIZE) {
- if (chars[i++] == c) {
- return true;
- }
- }
- return false;
-}
-
-bool ProximityInfo::existsAdjacentProximityChars(const int index) const {
- if (index < 0 || index >= mInputLength) return false;
- const int currentChar = getPrimaryCharAt(index);
- const int leftIndex = index - 1;
- if (leftIndex >= 0 && existsCharInProximityAt(leftIndex, currentChar)) {
- return true;
- }
- const int rightIndex = index + 1;
- if (rightIndex < mInputLength && existsCharInProximityAt(rightIndex, currentChar)) {
- return true;
- }
- return false;
-}
-
-// In the following function, c is the current character of the dictionary word
-// currently examined.
-// currentChars is an array containing the keys close to the character the
-// user actually typed at the same position. We want to see if c is in it: if so,
-// then the word contains at that position a character close to what the user
-// typed.
-// What the user typed is actually the first character of the array.
-// proximityIndex is a pointer to the variable where getMatchedProximityId returns
-// the index of c in the proximity chars of the input index.
-// Notice : accented characters do not have a proximity list, so they are alone
-// in their list. The non-accented version of the character should be considered
-// "close", but not the other keys close to the non-accented version.
-ProximityInfo::ProximityType ProximityInfo::getMatchedProximityId(const int index,
- const unsigned short c, const bool checkProximityChars, int *proximityIndex) const {
- const int *currentChars = getProximityCharsAt(index);
- const int firstChar = currentChars[0];
- const unsigned short baseLowerC = toBaseLowerCase(c);
-
- // The first char in the array is what user typed. If it matches right away,
- // that means the user typed that same char for this pos.
- if (firstChar == baseLowerC || firstChar == c) {
- return EQUIVALENT_CHAR;
- }
-
- if (!checkProximityChars) return UNRELATED_CHAR;
-
- // If the non-accented, lowercased version of that first character matches c,
- // then we have a non-accented version of the accented character the user
- // typed. Treat it as a close char.
- if (toBaseLowerCase(firstChar) == baseLowerC)
- return NEAR_PROXIMITY_CHAR;
-
- // Not an exact nor an accent-alike match: search the list of close keys
- int j = 1;
- while (j < MAX_PROXIMITY_CHARS_SIZE
- && currentChars[j] > ADDITIONAL_PROXIMITY_CHAR_DELIMITER_CODE) {
- const bool matched = (currentChars[j] == baseLowerC || currentChars[j] == c);
- if (matched) {
- if (proximityIndex) {
- *proximityIndex = j;
- }
- return NEAR_PROXIMITY_CHAR;
- }
- ++j;
- }
- if (j < MAX_PROXIMITY_CHARS_SIZE
- && currentChars[j] == ADDITIONAL_PROXIMITY_CHAR_DELIMITER_CODE) {
- ++j;
- while (j < MAX_PROXIMITY_CHARS_SIZE
- && currentChars[j] > ADDITIONAL_PROXIMITY_CHAR_DELIMITER_CODE) {
- const bool matched = (currentChars[j] == baseLowerC || currentChars[j] == c);
- if (matched) {
- if (proximityIndex) {
- *proximityIndex = j;
- }
- return ADDITIONAL_PROXIMITY_CHAR;
- }
- ++j;
- }
- }
-
- // Was not included, signal this as an unrelated character.
- return UNRELATED_CHAR;
-}
-
-bool ProximityInfo::sameAsTyped(const unsigned short *word, int length) const {
- if (length != mInputLength) {
- return false;
- }
- const int *inputCodes = mInputCodes;
- while (length--) {
- if ((unsigned int) *inputCodes != (unsigned int) *word) {
- return false;
- }
- inputCodes += MAX_PROXIMITY_CHARS_SIZE;
- word++;
- }
- return true;
-}
-
-const int ProximityInfo::NORMALIZED_SQUARED_DISTANCE_SCALING_FACTOR_LOG_2;
-const int ProximityInfo::NORMALIZED_SQUARED_DISTANCE_SCALING_FACTOR;
-const int ProximityInfo::MAX_KEY_COUNT_IN_A_KEYBOARD;
-const int ProximityInfo::MAX_CHAR_CODE;
-
} // namespace latinime
diff --git a/native/jni/src/proximity_info.h b/native/jni/src/proximity_info.h
index feb0c9444..67f2f60fb 100644
--- a/native/jni/src/proximity_info.h
+++ b/native/jni/src/proximity_info.h
@@ -28,22 +28,6 @@ class Correction;
class ProximityInfo {
public:
- static const int NORMALIZED_SQUARED_DISTANCE_SCALING_FACTOR_LOG_2 = 10;
- static const int NORMALIZED_SQUARED_DISTANCE_SCALING_FACTOR =
- 1 << NORMALIZED_SQUARED_DISTANCE_SCALING_FACTOR_LOG_2;
-
- // Used as a return value for character comparison
- typedef enum {
- // Same char, possibly with different case or accent
- EQUIVALENT_CHAR,
- // It is a char located nearby on the keyboard
- NEAR_PROXIMITY_CHAR,
- // It is an unrelated char
- UNRELATED_CHAR,
- // Additional proximity char which can differ by language.
- ADDITIONAL_PROXIMITY_CHAR
- } ProximityType;
-
ProximityInfo(const std::string localeStr, const int maxProximityCharsSize,
const int keyboardWidth, const int keyboardHeight, const int gridWidth,
const int gridHeight, const int mostCommonkeyWidth,
@@ -53,23 +37,65 @@ class ProximityInfo {
const float *sweetSpotCenterYs, const float *sweetSpotRadii);
~ProximityInfo();
bool hasSpaceProximity(const int x, const int y) const;
- void setInputParams(const int32_t *inputCodes, const int inputLength,
- const int *xCoordinates, const int *yCoordinates);
- const int* getProximityCharsAt(const int index) const;
- unsigned short getPrimaryCharAt(const int index) const;
- bool existsCharInProximityAt(const int index, const int c) const;
- bool existsAdjacentProximityChars(const int index) const;
- ProximityType getMatchedProximityId(const int index, const unsigned short c,
- const bool checkProximityChars, int *proximityIndex = 0) const;
- int getNormalizedSquaredDistance(const int inputIndex, const int proximityIndex) const {
- return mNormalizedSquaredDistances[inputIndex * MAX_PROXIMITY_CHARS_SIZE + proximityIndex];
- }
+ int getNormalizedSquaredDistance(const int inputIndex, const int proximityIndex) const;
bool sameAsTyped(const unsigned short *word, int length) const;
- const unsigned short* getPrimaryInputWord() const {
- return mPrimaryInputWord;
+ int squaredDistanceToEdge(const int keyId, const int x, const int y) const;
+ bool isOnKey(const int keyId, const int x, const int y) const {
+ if (keyId < 0) return true; // NOT_A_ID is -1, but return whenever < 0 just in case
+ const int left = mKeyXCoordinates[keyId];
+ const int top = mKeyYCoordinates[keyId];
+ const int right = left + mKeyWidths[keyId] + 1;
+ const int bottom = top + mKeyHeights[keyId];
+ return left < right && top < bottom && x >= left && x < right && y >= top && y < bottom;
+ }
+ int getKeyIndex(const int c) const;
+ bool hasSweetSpotData(const int keyIndex) const {
+ // When there are no calibration data for a key,
+ // the radius of the key is assigned to zero.
+ return mSweetSpotRadii[keyIndex] > 0.0;
+ }
+ float getSweetSpotRadiiAt(int keyIndex) const {
+ return mSweetSpotRadii[keyIndex];
+ }
+ float getSweetSpotCenterXAt(int keyIndex) const {
+ return mSweetSpotCenterXs[keyIndex];
+ }
+ float getSweetSpotCenterYAt(int keyIndex) const {
+ return mSweetSpotCenterYs[keyIndex];
+ }
+ void calculateNearbyKeyCodes(
+ const int x, const int y, const int32_t primaryKey, int *inputCodes) const;
+
+ bool hasTouchPositionCorrectionData() const {
+ return HAS_TOUCH_POSITION_CORRECTION_DATA;
+ }
+
+ int getMostCommonKeyWidthSquare() const {
+ return MOST_COMMON_KEY_WIDTH_SQUARE;
+ }
+
+ std::string getLocaleStr() const {
+ return mLocaleStr;
+ }
+
+ int getKeyCount() const {
+ return KEY_COUNT;
+ }
+
+ int getCellHeight() const {
+ return CELL_HEIGHT;
}
- bool touchPositionCorrectionEnabled() const {
- return mTouchPositionCorrectionEnabled;
+
+ int getCellWidth() const {
+ return CELL_WIDTH;
+ }
+
+ int getGridWidth() const {
+ return GRID_WIDTH;
+ }
+
+ int getGridHeight() const {
+ return GRID_HEIGHT;
}
private:
@@ -86,16 +112,6 @@ class ProximityInfo {
float calculateSquaredDistanceFromSweetSpotCenter(
const int keyIndex, const int inputIndex) const;
bool hasInputCoordinates() const;
- int getKeyIndex(const int c) const;
- bool hasSweetSpotData(const int keyIndex) const {
- // When there are no calibration data for a key,
- // the radius of the key is assigned to zero.
- return mSweetSpotRadii[keyIndex] > 0.0;
- }
- bool isOnKey(const int keyId, const int x, const int y) const;
- int squaredDistanceToEdge(const int keyId, const int x, const int y) const;
- void calculateNearbyKeyCodes(
- const int x, const int y, const int32_t primaryKey, int *inputCodes) const;
const int MAX_PROXIMITY_CHARS_SIZE;
const int KEYBOARD_WIDTH;
@@ -108,14 +124,7 @@ class ProximityInfo {
const int KEY_COUNT;
const bool HAS_TOUCH_POSITION_CORRECTION_DATA;
const std::string mLocaleStr;
- // TODO: remove this
- const int *mInputCodesFromJava;
- int32_t *mInputCodes;
- const int *mInputXCoordinates;
- const int *mInputYCoordinates;
- bool mTouchPositionCorrectionEnabled;
int32_t *mProximityCharsArray;
- int *mNormalizedSquaredDistances;
int32_t mKeyXCoordinates[MAX_KEY_COUNT_IN_A_KEYBOARD];
int32_t mKeyYCoordinates[MAX_KEY_COUNT_IN_A_KEYBOARD];
int32_t mKeyWidths[MAX_KEY_COUNT_IN_A_KEYBOARD];
@@ -124,9 +133,8 @@ class ProximityInfo {
float mSweetSpotCenterXs[MAX_KEY_COUNT_IN_A_KEYBOARD];
float mSweetSpotCenterYs[MAX_KEY_COUNT_IN_A_KEYBOARD];
float mSweetSpotRadii[MAX_KEY_COUNT_IN_A_KEYBOARD];
- int mInputLength;
- unsigned short mPrimaryInputWord[MAX_WORD_LENGTH_INTERNAL];
int mCodeToKeyIndex[MAX_CHAR_CODE + 1];
+ // TODO: move to correction.h
};
} // namespace latinime
diff --git a/native/jni/src/proximity_info_state.cpp b/native/jni/src/proximity_info_state.cpp
new file mode 100644
index 000000000..149299eb6
--- /dev/null
+++ b/native/jni/src/proximity_info_state.cpp
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <assert.h>
+#include <stdint.h>
+#include <string>
+
+#define LOG_TAG "LatinIME: proximity_info_state.cpp"
+
+#include "additional_proximity_chars.h"
+#include "defines.h"
+#include "dictionary.h"
+#include "proximity_info.h"
+#include "proximity_info_state.h"
+
+namespace latinime {
+void ProximityInfoState::initInputParams(
+ const ProximityInfo* proximityInfo, const int32_t* inputCodes, const int inputLength,
+ const int* xCoordinates, const int* yCoordinates) {
+ mProximityInfo = proximityInfo;
+ mHasTouchPositionCorrectionData = proximityInfo->hasTouchPositionCorrectionData();
+ mMostCommonKeyWidthSquare = proximityInfo->getMostCommonKeyWidthSquare();
+ mLocaleStr = proximityInfo->getLocaleStr();
+ mKeyCount = proximityInfo->getKeyCount();
+ mCellHeight = proximityInfo->getCellHeight();
+ mCellWidth = proximityInfo->getCellWidth();
+ mGridHeight = proximityInfo->getGridWidth();
+ mGridWidth = proximityInfo->getGridHeight();
+ const int normalizedSquaredDistancesLength =
+ MAX_PROXIMITY_CHARS_SIZE_INTERNAL * MAX_WORD_LENGTH_INTERNAL;
+ for (int i = 0; i < normalizedSquaredDistancesLength; ++i) {
+ mNormalizedSquaredDistances[i] = NOT_A_DISTANCE;
+ }
+
+ memset(mInputCodes, 0,
+ MAX_WORD_LENGTH_INTERNAL * MAX_PROXIMITY_CHARS_SIZE_INTERNAL * sizeof(mInputCodes[0]));
+
+ for (int i = 0; i < inputLength; ++i) {
+ const int32_t primaryKey = inputCodes[i];
+ const int x = xCoordinates[i];
+ const int y = yCoordinates[i];
+ int *proximities = &mInputCodes[i * MAX_PROXIMITY_CHARS_SIZE_INTERNAL];
+ mProximityInfo->calculateNearbyKeyCodes(x, y, primaryKey, proximities);
+ }
+
+ if (DEBUG_PROXIMITY_CHARS) {
+ for (int i = 0; i < inputLength; ++i) {
+ AKLOGI("---");
+ for (int j = 0; j < MAX_PROXIMITY_CHARS_SIZE_INTERNAL; ++j) {
+ int icc = mInputCodes[i * MAX_PROXIMITY_CHARS_SIZE_INTERNAL + j];
+ int icfjc = inputCodes[i * MAX_PROXIMITY_CHARS_SIZE_INTERNAL + j];
+ icc += 0;
+ icfjc += 0;
+ AKLOGI("--- (%d)%c,%c", i, icc, icfjc); AKLOGI("--- A<%d>,B<%d>", icc, icfjc);
+ }
+ }
+ }
+ mInputXCoordinates = xCoordinates;
+ mInputYCoordinates = yCoordinates;
+ mTouchPositionCorrectionEnabled =
+ mHasTouchPositionCorrectionData && xCoordinates && yCoordinates;
+ mInputLength = inputLength;
+ for (int i = 0; i < inputLength; ++i) {
+ mPrimaryInputWord[i] = getPrimaryCharAt(i);
+ }
+ mPrimaryInputWord[inputLength] = 0;
+ if (DEBUG_PROXIMITY_CHARS) {
+ AKLOGI("--- initInputParams");
+ }
+ for (int i = 0; i < mInputLength; ++i) {
+ const int *proximityChars = getProximityCharsAt(i);
+ const int primaryKey = proximityChars[0];
+ const int x = xCoordinates[i];
+ const int y = yCoordinates[i];
+ if (DEBUG_PROXIMITY_CHARS) {
+ int a = x + y + primaryKey;
+ a += 0;
+ AKLOGI("--- Primary = %c, x = %d, y = %d", primaryKey, x, y);
+ }
+ for (int j = 0; j < MAX_PROXIMITY_CHARS_SIZE_INTERNAL && proximityChars[j] > 0; ++j) {
+ const int currentChar = proximityChars[j];
+ const float squaredDistance =
+ hasInputCoordinates() ? calculateNormalizedSquaredDistance(
+ mProximityInfo->getKeyIndex(currentChar), i) :
+ NOT_A_DISTANCE_FLOAT;
+ if (squaredDistance >= 0.0f) {
+ mNormalizedSquaredDistances[i * MAX_PROXIMITY_CHARS_SIZE_INTERNAL + j] =
+ (int) (squaredDistance * NORMALIZED_SQUARED_DISTANCE_SCALING_FACTOR);
+ } else {
+ mNormalizedSquaredDistances[i * MAX_PROXIMITY_CHARS_SIZE_INTERNAL + j] =
+ (j == 0) ? EQUIVALENT_CHAR_WITHOUT_DISTANCE_INFO :
+ PROXIMITY_CHAR_WITHOUT_DISTANCE_INFO;
+ }
+ if (DEBUG_PROXIMITY_CHARS) {
+ AKLOGI("--- Proximity (%d) = %c", j, currentChar);
+ }
+ }
+ }
+}
+
+float ProximityInfoState::calculateNormalizedSquaredDistance(
+ const int keyIndex, const int inputIndex) const {
+ if (keyIndex == NOT_AN_INDEX) {
+ return NOT_A_DISTANCE_FLOAT;
+ }
+ if (!mProximityInfo->hasSweetSpotData(keyIndex)) {
+ return NOT_A_DISTANCE_FLOAT;
+ }
+ if (NOT_A_COORDINATE == mInputXCoordinates[inputIndex]) {
+ return NOT_A_DISTANCE_FLOAT;
+ }
+ const float squaredDistance = calculateSquaredDistanceFromSweetSpotCenter(
+ keyIndex, inputIndex);
+ const float squaredRadius = square(mProximityInfo->getSweetSpotRadiiAt(keyIndex));
+ return squaredDistance / squaredRadius;
+}
+
+float ProximityInfoState::calculateSquaredDistanceFromSweetSpotCenter(
+ const int keyIndex, const int inputIndex) const {
+ const float sweetSpotCenterX = mProximityInfo->getSweetSpotCenterXAt(keyIndex);
+ const float sweetSpotCenterY = mProximityInfo->getSweetSpotCenterYAt(keyIndex);
+ const float inputX = (float)mInputXCoordinates[inputIndex];
+ const float inputY = (float)mInputYCoordinates[inputIndex];
+ return square(inputX - sweetSpotCenterX) + square(inputY - sweetSpotCenterY);
+}
+} // namespace latinime
diff --git a/native/jni/src/proximity_info_state.h b/native/jni/src/proximity_info_state.h
new file mode 100644
index 000000000..3a98d9b6a
--- /dev/null
+++ b/native/jni/src/proximity_info_state.h
@@ -0,0 +1,219 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LATINIME_PROXIMITY_INFO_STATE_H
+#define LATINIME_PROXIMITY_INFO_STATE_H
+
+#include <assert.h>
+#include <stdint.h>
+#include <string>
+
+#include "additional_proximity_chars.h"
+#include "char_utils.h"
+#include "defines.h"
+
+namespace latinime {
+
+class ProximityInfo;
+
+class ProximityInfoState {
+ public:
+ static const int NORMALIZED_SQUARED_DISTANCE_SCALING_FACTOR_LOG_2 = 10;
+ static const int NORMALIZED_SQUARED_DISTANCE_SCALING_FACTOR =
+ 1 << NORMALIZED_SQUARED_DISTANCE_SCALING_FACTOR_LOG_2;
+ // The upper limit of the char code in mCodeToKeyIndex
+ static const int MAX_CHAR_CODE = 127;
+ static const float NOT_A_DISTANCE_FLOAT = -1.0f;
+ static const int NOT_A_CODE = -1;
+
+ /////////////////////////////////////////
+ // Defined in proximity_info_state.cpp //
+ /////////////////////////////////////////
+ void initInputParams(
+ const ProximityInfo* proximityInfo, const int32_t* inputCodes, const int inputLength,
+ const int* xCoordinates, const int* yCoordinates);
+
+ /////////////////////////////////////////
+ // Defined here //
+ /////////////////////////////////////////
+ inline const int* getProximityCharsAt(const int index) const {
+ return mInputCodes + (index * MAX_PROXIMITY_CHARS_SIZE_INTERNAL);
+ }
+
+ inline unsigned short getPrimaryCharAt(const int index) const {
+ return getProximityCharsAt(index)[0];
+ }
+
+ inline bool existsCharInProximityAt(const int index, const int c) const {
+ const int *chars = getProximityCharsAt(index);
+ int i = 0;
+ while (chars[i] > 0 && i < MAX_PROXIMITY_CHARS_SIZE_INTERNAL) {
+ if (chars[i++] == c) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ inline bool existsAdjacentProximityChars(const int index) const {
+ if (index < 0 || index >= mInputLength) return false;
+ const int currentChar = getPrimaryCharAt(index);
+ const int leftIndex = index - 1;
+ if (leftIndex >= 0 && existsCharInProximityAt(leftIndex, currentChar)) {
+ return true;
+ }
+ const int rightIndex = index + 1;
+ if (rightIndex < mInputLength && existsCharInProximityAt(rightIndex, currentChar)) {
+ return true;
+ }
+ return false;
+ }
+
+ // In the following function, c is the current character of the dictionary word
+ // currently examined.
+ // currentChars is an array containing the keys close to the character the
+ // user actually typed at the same position. We want to see if c is in it: if so,
+ // then the word contains at that position a character close to what the user
+ // typed.
+ // What the user typed is actually the first character of the array.
+ // proximityIndex is a pointer to the variable where getMatchedProximityId returns
+ // the index of c in the proximity chars of the input index.
+ // Notice : accented characters do not have a proximity list, so they are alone
+ // in their list. The non-accented version of the character should be considered
+ // "close", but not the other keys close to the non-accented version.
+ inline ProximityType getMatchedProximityId(const int index,
+ const unsigned short c, const bool checkProximityChars, int *proximityIndex = 0) const {
+ const int *currentChars = getProximityCharsAt(index);
+ const int firstChar = currentChars[0];
+ const unsigned short baseLowerC = toBaseLowerCase(c);
+
+ // The first char in the array is what user typed. If it matches right away,
+ // that means the user typed that same char for this pos.
+ if (firstChar == baseLowerC || firstChar == c) {
+ return EQUIVALENT_CHAR;
+ }
+
+ if (!checkProximityChars) return UNRELATED_CHAR;
+
+ // If the non-accented, lowercased version of that first character matches c,
+ // then we have a non-accented version of the accented character the user
+ // typed. Treat it as a close char.
+ if (toBaseLowerCase(firstChar) == baseLowerC)
+ return NEAR_PROXIMITY_CHAR;
+
+ // Not an exact nor an accent-alike match: search the list of close keys
+ int j = 1;
+ while (j < MAX_PROXIMITY_CHARS_SIZE_INTERNAL
+ && currentChars[j] > ADDITIONAL_PROXIMITY_CHAR_DELIMITER_CODE) {
+ const bool matched = (currentChars[j] == baseLowerC || currentChars[j] == c);
+ if (matched) {
+ if (proximityIndex) {
+ *proximityIndex = j;
+ }
+ return NEAR_PROXIMITY_CHAR;
+ }
+ ++j;
+ }
+ if (j < MAX_PROXIMITY_CHARS_SIZE_INTERNAL
+ && currentChars[j] == ADDITIONAL_PROXIMITY_CHAR_DELIMITER_CODE) {
+ ++j;
+ while (j < MAX_PROXIMITY_CHARS_SIZE_INTERNAL
+ && currentChars[j] > ADDITIONAL_PROXIMITY_CHAR_DELIMITER_CODE) {
+ const bool matched = (currentChars[j] == baseLowerC || currentChars[j] == c);
+ if (matched) {
+ if (proximityIndex) {
+ *proximityIndex = j;
+ }
+ return ADDITIONAL_PROXIMITY_CHAR;
+ }
+ ++j;
+ }
+ }
+
+ // Was not included, signal this as an unrelated character.
+ return UNRELATED_CHAR;
+ }
+
+ inline int getNormalizedSquaredDistance(
+ const int inputIndex, const int proximityIndex) const {
+ return mNormalizedSquaredDistances[
+ inputIndex * MAX_PROXIMITY_CHARS_SIZE_INTERNAL + proximityIndex];
+ }
+
+ inline const unsigned short* getPrimaryInputWord() const {
+ return mPrimaryInputWord;
+ }
+
+ inline bool touchPositionCorrectionEnabled() const {
+ return mTouchPositionCorrectionEnabled;
+ }
+
+ private:
+ /////////////////////////////////////////
+ // Defined in proximity_info_state.cpp //
+ /////////////////////////////////////////
+ float calculateNormalizedSquaredDistance(const int keyIndex, const int inputIndex) const;
+
+ float calculateSquaredDistanceFromSweetSpotCenter(
+ const int keyIndex, const int inputIndex) const;
+
+ /////////////////////////////////////////
+ // Defined here //
+ /////////////////////////////////////////
+ inline float square(const float x) const { return x * x; }
+
+ bool hasInputCoordinates() const {
+ return mInputXCoordinates && mInputYCoordinates;
+ }
+
+ bool sameAsTyped(const unsigned short *word, int length) const {
+ if (length != mInputLength) {
+ return false;
+ }
+ const int *inputCodes = mInputCodes;
+ while (length--) {
+ if ((unsigned int) *inputCodes != (unsigned int) *word) {
+ return false;
+ }
+ inputCodes += MAX_PROXIMITY_CHARS_SIZE_INTERNAL;
+ word++;
+ }
+ return true;
+ }
+
+ // const
+ const ProximityInfo *mProximityInfo;
+ bool mHasTouchPositionCorrectionData;
+ int mMostCommonKeyWidthSquare;
+ std::string mLocaleStr;
+ int mKeyCount;
+ int mCellHeight;
+ int mCellWidth;
+ int mGridHeight;
+ int mGridWidth;
+
+ const int *mInputXCoordinates;
+ const int *mInputYCoordinates;
+ bool mTouchPositionCorrectionEnabled;
+ int32_t mInputCodes[MAX_PROXIMITY_CHARS_SIZE_INTERNAL * MAX_WORD_LENGTH_INTERNAL];
+ int mNormalizedSquaredDistances[MAX_PROXIMITY_CHARS_SIZE_INTERNAL * MAX_WORD_LENGTH_INTERNAL];
+ int mInputLength;
+ unsigned short mPrimaryInputWord[MAX_WORD_LENGTH_INTERNAL];
+};
+
+} // namespace latinime
+
+#endif // LATINIME_PROXIMITY_INFO_STATE_H
diff --git a/native/jni/src/unigram_dictionary.cpp b/native/jni/src/unigram_dictionary.cpp
index ea9f11b2c..27196f493 100644
--- a/native/jni/src/unigram_dictionary.cpp
+++ b/native/jni/src/unigram_dictionary.cpp
@@ -103,7 +103,7 @@ void UnigramDictionary::getWordWithDigraphSuggestionsRec(ProximityInfo *proximit
const bool useFullEditDistance, const int *codesSrc,
const int codesRemain, const int currentDepth, int *codesDest, Correction *correction,
WordsPriorityQueuePool *queuePool,
- const digraph_t* const digraphs, const unsigned int digraphsSize) {
+ const digraph_t* const digraphs, const unsigned int digraphsSize) const {
const int startIndex = codesDest - codesBuffer;
if (currentDepth < MAX_DIGRAPH_SEARCH_DEPTH) {
@@ -173,7 +173,7 @@ int UnigramDictionary::getSuggestions(ProximityInfo *proximityInfo,
WordsPriorityQueuePool *queuePool, Correction *correction, const int *xcoordinates,
const int *ycoordinates, const int *codes, const int codesSize,
const std::map<int, int> *bigramMap, const uint8_t *bigramFilter,
- const bool useFullEditDistance, unsigned short *outWords, int *frequencies) {
+ const bool useFullEditDistance, unsigned short *outWords, int *frequencies) const {
queuePool->clearAll();
Correction* masterCorrection = correction;
@@ -205,17 +205,17 @@ int UnigramDictionary::getSuggestions(ProximityInfo *proximityInfo,
PROF_START(20);
if (DEBUG_DICT) {
float ns = queuePool->getMasterQueue()->getHighestNormalizedScore(
- proximityInfo->getPrimaryInputWord(), codesSize, 0, 0, 0);
+ correction->getPrimaryInputWord(), codesSize, 0, 0, 0);
ns += 0;
AKLOGI("Max normalized score = %f", ns);
}
const int suggestedWordsCount =
queuePool->getMasterQueue()->outputSuggestions(
- proximityInfo->getPrimaryInputWord(), codesSize, frequencies, outWords);
+ correction->getPrimaryInputWord(), codesSize, frequencies, outWords);
if (DEBUG_DICT) {
float ns = queuePool->getMasterQueue()->getHighestNormalizedScore(
- proximityInfo->getPrimaryInputWord(), codesSize, 0, 0, 0);
+ correction->getPrimaryInputWord(), codesSize, 0, 0, 0);
ns += 0;
AKLOGI("Returning %d words", suggestedWordsCount);
/// Print the returned words
@@ -235,7 +235,8 @@ int UnigramDictionary::getSuggestions(ProximityInfo *proximityInfo,
void UnigramDictionary::getWordSuggestions(ProximityInfo *proximityInfo,
const int *xcoordinates, const int *ycoordinates, const int *codes,
const int inputLength, const std::map<int, int> *bigramMap, const uint8_t *bigramFilter,
- const bool useFullEditDistance, Correction *correction, WordsPriorityQueuePool *queuePool) {
+ const bool useFullEditDistance, Correction *correction,
+ WordsPriorityQueuePool *queuePool) const {
PROF_OPEN;
PROF_START(0);
@@ -259,7 +260,7 @@ void UnigramDictionary::getWordSuggestions(ProximityInfo *proximityInfo,
WordsPriorityQueue* masterQueue = queuePool->getMasterQueue();
if (masterQueue->size() > 0) {
float nsForMaster = masterQueue->getHighestNormalizedScore(
- proximityInfo->getPrimaryInputWord(), inputLength, 0, 0, 0);
+ correction->getPrimaryInputWord(), inputLength, 0, 0, 0);
hasAutoCorrectionCandidate = (nsForMaster > START_TWO_WORDS_CORRECTION_THRESHOLD);
}
PROF_END(4);
@@ -288,11 +289,11 @@ void UnigramDictionary::getWordSuggestions(ProximityInfo *proximityInfo,
const unsigned short* word = sw->mWord;
const int wordLength = sw->mWordLength;
float ns = Correction::RankingAlgorithm::calcNormalizedScore(
- proximityInfo->getPrimaryInputWord(), i, word, wordLength, score);
+ correction->getPrimaryInputWord(), i, word, wordLength, score);
ns += 0;
AKLOGI("--- TOP SUB WORDS for %d --- %d %f [%d]", i, score, ns,
(ns > TWO_WORDS_CORRECTION_WITH_OTHER_ERROR_THRESHOLD));
- DUMP_WORD(proximityInfo->getPrimaryInputWord(), i);
+ DUMP_WORD(correction->getPrimaryInputWord(), i);
DUMP_WORD(word, wordLength);
}
}
@@ -300,12 +301,13 @@ void UnigramDictionary::getWordSuggestions(ProximityInfo *proximityInfo,
}
void UnigramDictionary::initSuggestions(ProximityInfo *proximityInfo, const int *xCoordinates,
- const int *yCoordinates, const int *codes, const int inputLength, Correction *correction) {
+ const int *yCoordinates, const int *codes, const int inputLength,
+ Correction *correction) const {
if (DEBUG_DICT) {
AKLOGI("initSuggest");
DUMP_WORD_INT(codes, inputLength);
}
- proximityInfo->setInputParams(codes, inputLength, xCoordinates, yCoordinates);
+ correction->initInputParams(proximityInfo, codes, inputLength, xCoordinates, yCoordinates);
const int maxDepth = min(inputLength * MAX_DEPTH_MULTIPLIER, MAX_WORD_LENGTH);
correction->initCorrection(proximityInfo, inputLength, maxDepth);
}
@@ -317,7 +319,7 @@ void UnigramDictionary::getOneWordSuggestions(ProximityInfo *proximityInfo,
const int *xcoordinates, const int *ycoordinates, const int *codes,
const std::map<int, int> *bigramMap, const uint8_t *bigramFilter,
const bool useFullEditDistance, const int inputLength,
- Correction *correction, WordsPriorityQueuePool *queuePool) {
+ Correction *correction, WordsPriorityQueuePool *queuePool) const {
initSuggestions(proximityInfo, xcoordinates, ycoordinates, codes, inputLength, correction);
getSuggestionCandidates(useFullEditDistance, inputLength, bigramMap, bigramFilter, correction,
queuePool, true /* doAutoCompletion */, DEFAULT_MAX_ERRORS, FIRST_WORD_INDEX);
@@ -326,7 +328,7 @@ void UnigramDictionary::getOneWordSuggestions(ProximityInfo *proximityInfo,
void UnigramDictionary::getSuggestionCandidates(const bool useFullEditDistance,
const int inputLength, const std::map<int, int> *bigramMap, const uint8_t *bigramFilter,
Correction *correction, WordsPriorityQueuePool *queuePool,
- const bool doAutoCompletion, const int maxErrors, const int currentWordIndex) {
+ const bool doAutoCompletion, const int maxErrors, const int currentWordIndex) const {
uint8_t totalTraverseCount = correction->pushAndGetTotalTraverseCount();
if (DEBUG_DICT) {
AKLOGI("Traverse count %d", totalTraverseCount);
@@ -374,7 +376,7 @@ void UnigramDictionary::getSuggestionCandidates(const bool useFullEditDistance,
inline void UnigramDictionary::onTerminal(const int probability,
const TerminalAttributes& terminalAttributes, Correction *correction,
WordsPriorityQueuePool *queuePool, const bool addToMasterQueue,
- const int currentWordIndex) {
+ const int currentWordIndex) const {
const int inputIndex = correction->getInputIndex();
const bool addToSubQueue = inputIndex < SUB_QUEUE_MAX_COUNT;
@@ -430,7 +432,7 @@ int UnigramDictionary::getSubStringSuggestion(
const bool hasAutoCorrectionCandidate, const int currentWordIndex,
const int inputWordStartPos, const int inputWordLength,
const int outputWordStartPos, const bool isSpaceProximity, int *freqArray,
- int*wordLengthArray, unsigned short* outputWord, int *outputWordLength) {
+ int*wordLengthArray, unsigned short* outputWord, int *outputWordLength) const {
if (inputWordLength > MULTIPLE_WORDS_SUGGESTION_MAX_WORD_LENGTH) {
return FLAG_MULTIPLE_SUGGEST_ABORT;
}
@@ -479,11 +481,12 @@ int UnigramDictionary::getSubStringSuggestion(
initSuggestions(proximityInfo, xcoordinates, ycoordinates, codes,
inputLength, correction);
+ unsigned short word[MAX_WORD_LENGTH_INTERNAL];
int freq = getMostFrequentWordLike(
- inputWordStartPos, inputWordLength, proximityInfo, mWord);
+ inputWordStartPos, inputWordLength, correction, word);
if (freq > 0) {
nextWordLength = inputWordLength;
- tempOutputWord = mWord;
+ tempOutputWord = word;
} else if (!hasAutoCorrectionCandidate) {
if (inputWordStartPos > 0) {
const int offset = inputWordStartPos;
@@ -510,7 +513,7 @@ int UnigramDictionary::getSubStringSuggestion(
}
int score = 0;
const float ns = queue->getHighestNormalizedScore(
- proximityInfo->getPrimaryInputWord(), inputWordLength,
+ correction->getPrimaryInputWord(), inputWordLength,
&tempOutputWord, &score, &nextWordLength);
if (DEBUG_DICT) {
AKLOGI("NS(%d) = %f, Score = %d", currentWordIndex, ns, score);
@@ -577,7 +580,7 @@ void UnigramDictionary::getMultiWordsSuggestionRec(ProximityInfo *proximityInfo,
Correction *correction, WordsPriorityQueuePool* queuePool,
const bool hasAutoCorrectionCandidate, const int startInputPos, const int startWordIndex,
const int outputWordLength, int *freqArray, int* wordLengthArray,
- unsigned short* outputWord) {
+ unsigned short* outputWord) const {
if (startWordIndex >= (MULTIPLE_WORDS_SUGGESTION_MAX_WORDS - 1)) {
// Return if the last word index
return;
@@ -656,7 +659,7 @@ void UnigramDictionary::getSplitMultipleWordsSuggestions(ProximityInfo *proximit
const int *xcoordinates, const int *ycoordinates, const int *codes,
const bool useFullEditDistance, const int inputLength,
Correction *correction, WordsPriorityQueuePool* queuePool,
- const bool hasAutoCorrectionCandidate) {
+ const bool hasAutoCorrectionCandidate) const {
if (inputLength >= MAX_WORD_LENGTH) return;
if (DEBUG_DICT) {
AKLOGI("--- Suggest multiple words");
@@ -678,11 +681,11 @@ void UnigramDictionary::getSplitMultipleWordsSuggestions(ProximityInfo *proximit
// Wrapper for getMostFrequentWordLikeInner, which matches it to the previous
// interface.
inline int UnigramDictionary::getMostFrequentWordLike(const int startInputIndex,
- const int inputLength, ProximityInfo *proximityInfo, unsigned short *word) {
+ const int inputLength, Correction *correction, unsigned short *word) const {
uint16_t inWord[inputLength];
for (int i = 0; i < inputLength; ++i) {
- inWord[i] = (uint16_t)proximityInfo->getPrimaryCharAt(startInputIndex + i);
+ inWord[i] = (uint16_t)correction->getPrimaryCharAt(startInputIndex + i);
}
return getMostFrequentWordLikeInner(inWord, inputLength, word);
}
@@ -751,21 +754,24 @@ static inline void onTerminalWordLike(const int freq, int32_t* newWord, const in
// Will find the highest frequency of the words like the one passed as an argument,
// that is, everything that only differs by case/accents.
int UnigramDictionary::getMostFrequentWordLikeInner(const uint16_t * const inWord,
- const int length, short unsigned int* outWord) {
+ const int length, short unsigned int* outWord) const {
int32_t newWord[MAX_WORD_LENGTH_INTERNAL];
int depth = 0;
int maxFreq = -1;
const uint8_t* const root = DICT_ROOT;
+ int stackChildCount[MAX_WORD_LENGTH_INTERNAL];
+ int stackInputIndex[MAX_WORD_LENGTH_INTERNAL];
+ int stackSiblingPos[MAX_WORD_LENGTH_INTERNAL];
int startPos = 0;
- mStackChildCount[0] = BinaryFormat::getGroupCountAndForwardPointer(root, &startPos);
- mStackInputIndex[0] = 0;
- mStackSiblingPos[0] = startPos;
+ stackChildCount[0] = BinaryFormat::getGroupCountAndForwardPointer(root, &startPos);
+ stackInputIndex[0] = 0;
+ stackSiblingPos[0] = startPos;
while (depth >= 0) {
- const int charGroupCount = mStackChildCount[depth];
- int pos = mStackSiblingPos[depth];
+ const int charGroupCount = stackChildCount[depth];
+ int pos = stackSiblingPos[depth];
for (int charGroupIndex = charGroupCount - 1; charGroupIndex >= 0; --charGroupIndex) {
- int inputIndex = mStackInputIndex[depth];
+ int inputIndex = stackInputIndex[depth];
const uint8_t flags = BinaryFormat::getFlagsAndForwardPointer(root, &pos);
// Test whether all chars in this group match with the word we are searching for. If so,
// we want to traverse its children (or if the length match, evaluate its frequency).
@@ -785,15 +791,15 @@ int UnigramDictionary::getMostFrequentWordLikeInner(const uint16_t * const inWor
// anyway, so don't traverse unless inputIndex < length.
if (isAlike && (-1 != childrenNodePos) && (inputIndex < length)) {
// Save position for this depth, to get back to this once children are done
- mStackChildCount[depth] = charGroupIndex;
- mStackSiblingPos[depth] = siblingPos;
+ stackChildCount[depth] = charGroupIndex;
+ stackSiblingPos[depth] = siblingPos;
// Prepare stack values for next depth
++depth;
int childrenPos = childrenNodePos;
- mStackChildCount[depth] =
+ stackChildCount[depth] =
BinaryFormat::getGroupCountAndForwardPointer(root, &childrenPos);
- mStackSiblingPos[depth] = childrenPos;
- mStackInputIndex[depth] = inputIndex;
+ stackSiblingPos[depth] = childrenPos;
+ stackInputIndex[depth] = inputIndex;
pos = childrenPos;
// Go to the next depth level.
++depth;
@@ -848,7 +854,7 @@ int UnigramDictionary::getBigramPosition(int pos, unsigned short *word, int offs
inline bool UnigramDictionary::processCurrentNode(const int initialPos,
const std::map<int, int> *bigramMap, const uint8_t *bigramFilter, Correction *correction,
int *newCount, int *newChildrenPosition, int *nextSiblingPosition,
- WordsPriorityQueuePool *queuePool, const int currentWordIndex) {
+ WordsPriorityQueuePool *queuePool, const int currentWordIndex) const {
if (DEBUG_DICT) {
correction->checkState();
}
diff --git a/native/jni/src/unigram_dictionary.h b/native/jni/src/unigram_dictionary.h
index a1a8299e5..1b26eff10 100644
--- a/native/jni/src/unigram_dictionary.h
+++ b/native/jni/src/unigram_dictionary.h
@@ -81,7 +81,7 @@ class UnigramDictionary {
Correction *correction, const int *xcoordinates, const int *ycoordinates,
const int *codes, const int codesSize, const std::map<int, int> *bigramMap,
const uint8_t *bigramFilter, const bool useFullEditDistance, unsigned short *outWords,
- int *frequencies);
+ int *frequencies) const;
virtual ~UnigramDictionary();
private:
@@ -89,7 +89,7 @@ class UnigramDictionary {
const int *ycoordinates, const int *codes, const int inputLength,
const std::map<int, int> *bigramMap, const uint8_t *bigramFilter,
const bool useFullEditDistance, Correction *correction,
- WordsPriorityQueuePool *queuePool);
+ WordsPriorityQueuePool *queuePool) const;
int getDigraphReplacement(const int *codes, const int i, const int codesSize,
const digraph_t* const digraphs, const unsigned int digraphsSize) const;
void getWordWithDigraphSuggestionsRec(ProximityInfo *proximityInfo,
@@ -99,37 +99,36 @@ class UnigramDictionary {
const bool useFullEditDistance, const int* codesSrc, const int codesRemain,
const int currentDepth, int* codesDest, Correction *correction,
WordsPriorityQueuePool* queuePool, const digraph_t* const digraphs,
- const unsigned int digraphsSize);
+ const unsigned int digraphsSize) const;
void initSuggestions(ProximityInfo *proximityInfo, const int *xcoordinates,
- const int *ycoordinates, const int *codes, const int codesSize, Correction *correction);
+ const int *ycoordinates, const int *codes, const int codesSize,
+ Correction *correction) const;
void getOneWordSuggestions(ProximityInfo *proximityInfo, const int *xcoordinates,
const int *ycoordinates, const int *codes, const std::map<int, int> *bigramMap,
const uint8_t *bigramFilter, const bool useFullEditDistance, const int inputLength,
- Correction *correction, WordsPriorityQueuePool* queuePool);
+ Correction *correction, WordsPriorityQueuePool* queuePool) const;
void getSuggestionCandidates(
const bool useFullEditDistance, const int inputLength,
const std::map<int, int> *bigramMap, const uint8_t *bigramFilter,
Correction *correction, WordsPriorityQueuePool* queuePool, const bool doAutoCompletion,
- const int maxErrors, const int currentWordIndex);
+ const int maxErrors, const int currentWordIndex) const;
void getSplitMultipleWordsSuggestions(ProximityInfo *proximityInfo,
const int *xcoordinates, const int *ycoordinates, const int *codes,
const bool useFullEditDistance, const int inputLength,
Correction *correction, WordsPriorityQueuePool* queuePool,
- const bool hasAutoCorrectionCandidate);
+ const bool hasAutoCorrectionCandidate) const;
void onTerminal(const int freq, const TerminalAttributes& terminalAttributes,
Correction *correction, WordsPriorityQueuePool *queuePool, const bool addToMasterQueue,
- const int currentWordIndex);
- bool needsToSkipCurrentNode(const unsigned short c,
- const int inputIndex, const int skipPos, const int depth);
+ const int currentWordIndex) const;
// Process a node by considering proximity, missing and excessive character
bool processCurrentNode(const int initialPos, const std::map<int, int> *bigramMap,
const uint8_t *bigramFilter, Correction *correction, int *newCount,
int *newChildPosition, int *nextSiblingPosition, WordsPriorityQueuePool *queuePool,
- const int currentWordIndex);
+ const int currentWordIndex) const;
int getMostFrequentWordLike(const int startInputIndex, const int inputLength,
- ProximityInfo *proximityInfo, unsigned short *word);
+ Correction *correction, unsigned short *word) const;
int getMostFrequentWordLikeInner(const uint16_t* const inWord, const int length,
- short unsigned int *outWord);
+ short unsigned int *outWord) const;
int getSubStringSuggestion(
ProximityInfo *proximityInfo, const int *xcoordinates, const int *ycoordinates,
const int *codes, const bool useFullEditDistance, Correction *correction,
@@ -137,14 +136,14 @@ class UnigramDictionary {
const bool hasAutoCorrectionCandidate, const int currentWordIndex,
const int inputWordStartPos, const int inputWordLength,
const int outputWordStartPos, const bool isSpaceProximity, int *freqArray,
- int *wordLengthArray, unsigned short* outputWord, int *outputWordLength);
+ int *wordLengthArray, unsigned short* outputWord, int *outputWordLength) const;
void getMultiWordsSuggestionRec(ProximityInfo *proximityInfo,
const int *xcoordinates, const int *ycoordinates, const int *codes,
const bool useFullEditDistance, const int inputLength,
Correction *correction, WordsPriorityQueuePool* queuePool,
const bool hasAutoCorrectionCandidate, const int startPos, const int startWordIndex,
const int outputWordLength, int *freqArray, int* wordLengthArray,
- unsigned short* outputWord);
+ unsigned short* outputWord) const;
const uint8_t* const DICT_ROOT;
const int MAX_WORD_LENGTH;
@@ -158,12 +157,6 @@ class UnigramDictionary {
static const digraph_t GERMAN_UMLAUT_DIGRAPHS[];
static const digraph_t FRENCH_LIGATURES_DIGRAPHS[];
-
- // Still bundled members
- unsigned short mWord[MAX_WORD_LENGTH_INTERNAL];// TODO: remove
- int mStackChildCount[MAX_WORD_LENGTH_INTERNAL];// TODO: remove
- int mStackInputIndex[MAX_WORD_LENGTH_INTERNAL];// TODO: remove
- int mStackSiblingPos[MAX_WORD_LENGTH_INTERNAL];// TODO: remove
};
} // namespace latinime