Separate state from proximity_info step1

Bug: 6548943

Change-Id: I7b4fbe20615a28151a74875be43b9f4a20e0dce9
diff --git a/java/src/com/android/inputmethod/keyboard/ProximityInfo.java b/java/src/com/android/inputmethod/keyboard/ProximityInfo.java
index 1207c3f..27ff6cd 100644
--- a/java/src/com/android/inputmethod/keyboard/ProximityInfo.java
+++ b/java/src/com/android/inputmethod/keyboard/ProximityInfo.java
@@ -27,6 +27,8 @@
 import java.util.HashMap;
 
 public class ProximityInfo {
+    /** MAX_PROXIMITY_CHARS_SIZE must be the same as MAX_PROXIMITY_CHARS_SIZE_INTERNAL
+     * in defines.h */
     public static final int MAX_PROXIMITY_CHARS_SIZE = 16;
     /** Number of key widths from current touch point to search for nearest keys. */
     private static float SEARCH_DISTANCE = 1.2f;
diff --git a/native/jni/Android.mk b/native/jni/Android.mk
index d53757f..0f7aef2 100644
--- a/native/jni/Android.mk
+++ b/native/jni/Android.mk
@@ -45,6 +45,7 @@
     correction.cpp \
     dictionary.cpp \
     proximity_info.cpp \
+    proximity_info_state.cpp \
     unigram_dictionary.cpp
 
 LOCAL_SRC_FILES := \
diff --git a/native/jni/src/correction.cpp b/native/jni/src/correction.cpp
index 99f5b92..bd326a4 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 {
 
@@ -308,13 +309,12 @@
     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,14 +335,14 @@
         bool incremented = false;
         if (mLastCharExceeded && mInputIndex == mInputLength - 1) {
             // TODO: Do not check the proximity if EditDistance exceeds the threshold
-            const ProximityInfo::ProximityType matchId =
+            const ProximityType matchId =
                     mProximityInfo->getMatchedProximityId(mInputIndex, c, true, &proximityIndex);
             if (isEquivalentChar(matchId)) {
                 mLastCharExceeded = false;
                 --mExcessiveCount;
                 mDistances[mOutputIndex] =
                         mProximityInfo->getNormalizedSquaredDistance(mInputIndex, 0);
-            } else if (matchId == ProximityInfo::NEAR_PROXIMITY_CHAR) {
+            } else if (matchId == NEAR_PROXIMITY_CHAR) {
                 mLastCharExceeded = false;
                 --mExcessiveCount;
                 ++mProximityCount;
@@ -417,13 +417,13 @@
             ? (noCorrectionsHappenedSoFar || mProximityCount == 0)
             : (noCorrectionsHappenedSoFar && mProximityCount == 0);
 
-    ProximityInfo::ProximityType matchedProximityCharId = secondTransposing
-            ? ProximityInfo::EQUIVALENT_CHAR
+    ProximityType matchedProximityCharId = secondTransposing
+            ? EQUIVALENT_CHAR
             : mProximityInfo->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
@@ -451,9 +451,9 @@
         }
     }
 
-    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
@@ -543,7 +543,7 @@
                         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;
@@ -574,7 +574,7 @@
         mMatching = true;
         ++mEquivalentCharCount;
         mDistances[mOutputIndex] = mProximityInfo->getNormalizedSquaredDistance(mInputIndex, 0);
-    } else if (ProximityInfo::NEAR_PROXIMITY_CHAR == matchedProximityCharId) {
+    } else if (NEAR_PROXIMITY_CHAR == matchedProximityCharId) {
         mProximityMatching = true;
         ++mProximityCount;
         mDistances[mOutputIndex] =
@@ -737,8 +737,7 @@
         multiplyIntCapped(matchWeight, &finalFreq);
     }
 
-    if (proximityInfo->getMatchedProximityId(0, word[0], true)
-            == ProximityInfo::UNRELATED_CHAR) {
+    if (proximityInfo->getMatchedProximityId(0, word[0], true) == UNRELATED_CHAR) {
         multiplyRate(FIRST_CHAR_DIFFERENT_DEMOTION_RATE, &finalFreq);
     }
 
@@ -796,7 +795,7 @@
                 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);
diff --git a/native/jni/src/defines.h b/native/jni/src/defines.h
index cd2fc63..e4c6753 100644
--- a/native/jni/src/defines.h
+++ b/native/jni/src/defines.h
@@ -225,6 +225,9 @@
 // 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 @@
 #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 960d401..39b91d7 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 @@
           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]));
@@ -81,6 +73,9 @@
     copyOrFillZero(mSweetSpotRadii, sweetSpotRadii, KEY_COUNT * sizeof(mSweetSpotRadii[0]));
 
     initializeCodeToKeyIndex();
+    mProximityInfoState = new ProximityInfoState(this, MAX_PROXIMITY_CHARS_SIZE,
+            HAS_TOUCH_POSITION_CORRECTION_DATA, MOST_COMMON_KEY_WIDTH_SQUARE, mLocaleStr,
+            KEY_COUNT, CELL_HEIGHT, CELL_WIDTH, GRID_WIDTH, GRID_HEIGHT);
 }
 
 // Build the reversed look up table from the char code to the index in mKeyXCoordinates,
@@ -96,9 +91,8 @@
 }
 
 ProximityInfo::~ProximityInfo() {
-    delete[] mNormalizedSquaredDistances;
     delete[] mProximityCharsArray;
-    delete[] mInputCodes;
+    delete mProximityInfoState;
 }
 
 inline int ProximityInfo::getStartIndexFromCoordinates(const int x, const int y) const {
@@ -119,26 +113,18 @@
     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 +140,13 @@
 
 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,113 +203,10 @@
     }
 }
 
-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;
+// TODO: remove
+void ProximityInfo::initInputParams(const int32_t *inputCodes, const int inputLength,
+        const int *xCoordinates, const int *yCoordinates) {
+    mProximityInfoState->initInputParams(inputCodes, inputLength, xCoordinates, yCoordinates);
 }
 
 int ProximityInfo::getKeyIndex(const int c) const {
@@ -337,131 +221,46 @@
     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);
-}
-
+// TODO: remove
 inline const int* ProximityInfo::getProximityCharsAt(const int index) const {
-    return mInputCodes + (index * MAX_PROXIMITY_CHARS_SIZE);
+    return mProximityInfoState->getProximityCharsAt(index);
 }
 
+// TODO: remove
 unsigned short ProximityInfo::getPrimaryCharAt(const int index) const {
-    return getProximityCharsAt(index)[0];
+    return mProximityInfoState->getPrimaryCharAt(index);
 }
 
-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;
+// TODO: remove
+bool ProximityInfo::existsCharInProximityAt(const int index, const int c) const {
+    return mProximityInfoState->existsCharInProximityAt(index, c);
 }
 
+// TODO: remove
 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;
+    return mProximityInfoState->existsAdjacentProximityChars(index);
 }
 
-// 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,
+// TODO: remove
+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;
+    return mProximityInfoState->getMatchedProximityId(
+            index, c, checkProximityChars, proximityIndex);
 }
 
-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;
+// TODO: remove
+int ProximityInfo::getNormalizedSquaredDistance(
+        const int inputIndex, const int proximityIndex) const {
+    return mProximityInfoState->getNormalizedSquaredDistance(inputIndex, proximityIndex);
 }
 
-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;
+// TODO: remove
+const unsigned short* ProximityInfo::getPrimaryInputWord() const {
+    return mProximityInfoState->getPrimaryInputWord();
+}
 
+// TODO: remove
+bool ProximityInfo::touchPositionCorrectionEnabled() const {
+    return mProximityInfoState->touchPositionCorrectionEnabled();
+}
 } // namespace latinime
diff --git a/native/jni/src/proximity_info.h b/native/jni/src/proximity_info.h
index feb0c94..a5ed57d 100644
--- a/native/jni/src/proximity_info.h
+++ b/native/jni/src/proximity_info.h
@@ -25,24 +25,10 @@
 namespace latinime {
 
 class Correction;
+class ProximityInfoState;
 
 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,
@@ -53,7 +39,40 @@
             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,
+    int getNormalizedSquaredDistance(const int inputIndex, const int proximityIndex) const;
+    bool sameAsTyped(const unsigned short *word, int length) const;
+    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;
+
+    ////////////////////////////////////
+    // Access to proximity info state //
+    // TODO: remove                   //
+    ////////////////////////////////////
+    void initInputParams(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;
@@ -61,16 +80,9 @@
     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];
-    }
-    bool sameAsTyped(const unsigned short *word, int length) const;
-    const unsigned short* getPrimaryInputWord() const {
-        return mPrimaryInputWord;
-    }
-    bool touchPositionCorrectionEnabled() const {
-        return mTouchPositionCorrectionEnabled;
-    }
+    const unsigned short* getPrimaryInputWord() const;
+    bool touchPositionCorrectionEnabled() const;
+    ////////////////////////////////////
 
  private:
     // The max number of the keys in one keyboard layout
@@ -86,16 +98,6 @@
     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 +110,7 @@
     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 +119,9 @@
     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
+    ProximityInfoState *mProximityInfoState;
 };
 
 } // 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 0000000..4161afb
--- /dev/null
+++ b/native/jni/src/proximity_info_state.cpp
@@ -0,0 +1,97 @@
+/*
+ * 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 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];
+        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; ++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);
+            }
+        }
+    }
+    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("--- 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 && 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 + 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);
+            }
+        }
+    }
+}
+} // 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 0000000..8113171
--- /dev/null
+++ b/native/jni/src/proximity_info_state.h
@@ -0,0 +1,259 @@
+/*
+ * 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 "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 max number of the keys in one keyboard layout
+    static const int MAX_KEY_COUNT_IN_A_KEYBOARD = 64;
+    // 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 int32_t* inputCodes, const int inputLength,
+           const int* xCoordinates, const int* yCoordinates);
+
+    /////////////////////////////////////////
+    // Defined here                        //
+    /////////////////////////////////////////
+    // TODO: Move the constructor to initInputParams
+    ProximityInfoState(ProximityInfo* proximityInfo, const int maxProximityCharsSize,
+            const bool hasTouchPositionCorrectionData, const int mostCommonKeyWidthSquare,
+            const std::string localeStr, const int keyCount, const int cellHeight,
+            const int cellWidth, const int gridHeight, const int gridWidth)
+            : mProximityInfo(proximityInfo),
+              MAX_PROXIMITY_CHARS_SIZE(maxProximityCharsSize),
+              HAS_TOUCH_POSITION_CORRECTION_DATA(hasTouchPositionCorrectionData),
+              MOST_COMMON_KEY_WIDTH_SQUARE(mostCommonKeyWidthSquare),
+              LOCALE_STR(localeStr),
+              KEY_COUNT(keyCount),
+              CELL_HEIGHT(cellHeight),
+              CELL_WIDTH(cellWidth),
+              GRID_HEIGHT(gridHeight),
+              GRID_WIDTH(gridWidth),
+              mInputXCoordinates(0),
+              mInputYCoordinates(0),
+              mTouchPositionCorrectionEnabled(false) {
+        const int normalizedSquaredDistancesLength =
+                MAX_PROXIMITY_CHARS_SIZE_INTERNAL * MAX_WORD_LENGTH_INTERNAL;
+        for (int i = 0; i < normalizedSquaredDistancesLength; ++i) {
+            mNormalizedSquaredDistances[i] = NOT_A_DISTANCE;
+        }
+    }
+
+    inline const int* getProximityCharsAt(const int index) const {
+        return mInputCodes + (index * MAX_PROXIMITY_CHARS_SIZE);
+    }
+
+    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) {
+            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) 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;
+    }
+
+    inline int getNormalizedSquaredDistance(
+            const int inputIndex, const int proximityIndex) const {
+        return mNormalizedSquaredDistances[inputIndex * MAX_PROXIMITY_CHARS_SIZE + proximityIndex];
+    }
+
+    inline const unsigned short* getPrimaryInputWord() const {
+        return mPrimaryInputWord;
+    }
+
+    inline bool touchPositionCorrectionEnabled() const {
+        return mTouchPositionCorrectionEnabled;
+    }
+
+ private:
+    inline float square(const float x) const { return x * x; }
+
+    float 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;
+    }
+
+    bool hasInputCoordinates() const {
+        return mInputXCoordinates && mInputYCoordinates;
+    }
+
+    float 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);
+    }
+
+    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;
+            word++;
+        }
+        return true;
+    }
+
+    // TODO: const
+    ProximityInfo *mProximityInfo;
+    const int MAX_PROXIMITY_CHARS_SIZE;
+    const bool HAS_TOUCH_POSITION_CORRECTION_DATA;
+    const int MOST_COMMON_KEY_WIDTH_SQUARE;
+    const std::string LOCALE_STR;
+    const int KEY_COUNT;
+    const int CELL_HEIGHT;
+    const int CELL_WIDTH;
+    const int GRID_HEIGHT;
+    const int GRID_WIDTH;
+
+    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 ea9f11b..157e47d 100644
--- a/native/jni/src/unigram_dictionary.cpp
+++ b/native/jni/src/unigram_dictionary.cpp
@@ -305,7 +305,7 @@
         AKLOGI("initSuggest");
         DUMP_WORD_INT(codes, inputLength);
     }
-    proximityInfo->setInputParams(codes, inputLength, xCoordinates, yCoordinates);
+    proximityInfo->initInputParams(codes, inputLength, xCoordinates, yCoordinates);
     const int maxDepth = min(inputLength * MAX_DEPTH_MULTIPLIER, MAX_WORD_LENGTH);
     correction->initCorrection(proximityInfo, inputLength, maxDepth);
 }