aboutsummaryrefslogtreecommitdiffstats
path: root/native/jni/src
diff options
context:
space:
mode:
Diffstat (limited to 'native/jni/src')
-rw-r--r--native/jni/src/char_utils.h11
-rw-r--r--native/jni/src/proximity_info_state.cpp98
-rw-r--r--native/jni/src/proximity_info_state.h45
-rw-r--r--native/jni/src/proximity_info_state_utils.cpp80
-rw-r--r--native/jni/src/proximity_info_state_utils.h17
5 files changed, 146 insertions, 105 deletions
diff --git a/native/jni/src/char_utils.h b/native/jni/src/char_utils.h
index 60da203b9..7a4384dbb 100644
--- a/native/jni/src/char_utils.h
+++ b/native/jni/src/char_utils.h
@@ -72,5 +72,16 @@ inline static bool isSkippableCodePoint(const int codePoint) {
// TODO: Do not hardcode here
return codePoint == KEYCODE_SINGLE_QUOTE || codePoint == KEYCODE_HYPHEN_MINUS;
}
+
+inline static int getCodePointCount(const int arraySize, const int *const codePoints) {
+ int size = 0;
+ for (; size < arraySize; ++size) {
+ if (codePoints[size] == '\0') {
+ break;
+ }
+ }
+ return size;
+}
+
} // namespace latinime
#endif // LATINIME_CHAR_UTILS_H
diff --git a/native/jni/src/proximity_info_state.cpp b/native/jni/src/proximity_info_state.cpp
index 8c6a525a7..387b03a24 100644
--- a/native/jni/src/proximity_info_state.cpp
+++ b/native/jni/src/proximity_info_state.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include <cstring> // for memset()
+#include <cstring> // for memset() and memcpy()
#include <sstream> // for debug prints
#define LOG_TAG "LatinIME: proximity_info_state.cpp"
@@ -33,8 +33,10 @@ void ProximityInfoState::initInputParams(const int pointerId, const float maxPoi
const ProximityInfo *proximityInfo, const int *const inputCodes, const int inputSize,
const int *const xCoordinates, const int *const yCoordinates, const int *const times,
const int *const pointerIds, const bool isGeometric) {
- mIsContinuationPossible = checkAndReturnIsContinuationPossible(
- inputSize, xCoordinates, yCoordinates, times, isGeometric);
+ ASSERT(isGeometric || (inputSize < MAX_WORD_LENGTH));
+ mIsContinuationPossible = ProximityInfoStateUtils::checkAndReturnIsContinuationPossible(
+ inputSize, xCoordinates, yCoordinates, times, mSampledInputSize, &mSampledInputXs,
+ &mSampledInputYs, &mSampledTimes, &mSampledInputIndice);
mProximityInfo = proximityInfo;
mHasTouchPositionCorrectionData = proximityInfo->hasTouchPositionCorrectionData();
@@ -57,12 +59,15 @@ void ProximityInfoState::initInputParams(const int pointerId, const float maxPoi
int pushTouchPointStartIndex = 0;
int lastSavedInputSize = 0;
mMaxPointToKeyLength = maxPointToKeyLength;
+ mSampledInputSize = 0;
+ mMostProbableStringProbability = 0.0f;
+
if (mIsContinuationPossible && mSampledInputIndice.size() > 1) {
// Just update difference.
- // Two points prior is never skipped. Thus, we pop 2 input point data here.
- pushTouchPointStartIndex = mSampledInputIndice[mSampledInputIndice.size() - 2];
- popInputData();
- popInputData();
+ // Previous two points are never skipped. Thus, we pop 2 input point data here.
+ pushTouchPointStartIndex = ProximityInfoStateUtils::trimLastTwoTouchPoints(
+ &mSampledInputXs, &mSampledInputYs, &mSampledTimes, &mSampledLengthCache,
+ &mSampledInputIndice);
lastSavedInputSize = mSampledInputXs.size();
} else {
// Clear all data.
@@ -79,11 +84,11 @@ void ProximityInfoState::initInputParams(const int pointerId, const float maxPoi
mCharProbabilities.clear();
mDirections.clear();
}
+
if (DEBUG_GEO_FULL) {
AKLOGI("Init ProximityInfoState: reused points = %d, last input size = %d",
pushTouchPointStartIndex, lastSavedInputSize);
}
- mSampledInputSize = 0;
if (xCoordinates && yCoordinates) {
mSampledInputSize = ProximityInfoStateUtils::updateTouchPoints(
@@ -119,6 +124,9 @@ void ProximityInfoState::initInputParams(const int pointerId, const float maxPoi
ProximityInfoStateUtils::updateSampledSearchKeysVector(mProximityInfo,
mSampledInputSize, lastSavedInputSize, &mSampledLengthCache,
&mSampledNearKeysVector, &mSampledSearchKeysVector);
+ mMostProbableStringProbability = ProximityInfoStateUtils::getMostProbableString(
+ mProximityInfo, mSampledInputSize, &mCharProbabilities, mMostProbableString);
+
}
}
@@ -130,8 +138,6 @@ void ProximityInfoState::initInputParams(const int pointerId, const float maxPoi
// end
///////////////////////
- memset(mNormalizedSquaredDistances, NOT_A_DISTANCE, sizeof(mNormalizedSquaredDistances));
- memset(mPrimaryInputWord, 0, sizeof(mPrimaryInputWord));
mTouchPositionCorrectionEnabled = mSampledInputSize > 0 && mHasTouchPositionCorrectionData
&& xCoordinates && yCoordinates;
if (!isGeometric && pointerId == 0) {
@@ -140,8 +146,7 @@ void ProximityInfoState::initInputParams(const int pointerId, const float maxPoi
if (mTouchPositionCorrectionEnabled) {
ProximityInfoStateUtils::initNormalizedSquaredDistances(
mProximityInfo, inputSize, xCoordinates, yCoordinates, mInputProximities,
- hasInputCoordinates(), &mSampledInputXs, &mSampledInputYs,
- mNormalizedSquaredDistances);
+ &mSampledInputXs, &mSampledInputYs, mNormalizedSquaredDistances);
}
}
if (DEBUG_GEO_FULL) {
@@ -149,39 +154,6 @@ void ProximityInfoState::initInputParams(const int pointerId, const float maxPoi
}
}
-bool ProximityInfoState::checkAndReturnIsContinuationPossible(const int inputSize,
- const int *const xCoordinates, const int *const yCoordinates, const int *const times,
- const bool isGeometric) const {
- if (isGeometric) {
- for (int i = 0; i < mSampledInputSize; ++i) {
- const int index = mSampledInputIndice[i];
- if (index > inputSize || xCoordinates[index] != mSampledInputXs[i] ||
- yCoordinates[index] != mSampledInputYs[i] || times[index] != mSampledTimes[i]) {
- return false;
- }
- }
- } else {
- if (inputSize < mSampledInputSize) {
- // Assuming the cache is invalid if the previous input size is larger than the new one.
- return false;
- }
- for (int i = 0; i < mSampledInputSize && i < MAX_WORD_LENGTH; ++i) {
- if (xCoordinates[i] != mSampledInputXs[i]
- || yCoordinates[i] != mSampledInputYs[i]) {
- return false;
- }
- }
- }
- return true;
-}
-
-int ProximityInfoState::getDuration(const int index) const {
- if (index >= 0 && index < mSampledInputSize - 1) {
- return mSampledTimes[index + 1] - mSampledTimes[index];
- }
- return 0;
-}
-
// TODO: Remove the "scale" parameter
// This function basically converts from a length to an edit distance. Accordingly, it's obviously
// wrong to compare with mMaxPointToKeyLength.
@@ -309,16 +281,10 @@ int ProximityInfoState::getAllPossibleChars(
}
bool ProximityInfoState::isKeyInSerchKeysAfterIndex(const int index, const int keyId) const {
- ASSERT(keyId >= 0);
- ASSERT(index >= 0 && index < mSampledInputSize);
+ ASSERT(keyId >= 0 && index >= 0 && index < mSampledInputSize);
return mSampledSearchKeysVector[index].test(keyId);
}
-void ProximityInfoState::popInputData() {
- ProximityInfoStateUtils::popInputData(&mSampledInputXs, &mSampledInputYs, &mSampledTimes,
- &mSampledLengthCache, &mSampledInputIndice);
-}
-
float ProximityInfoState::getDirection(const int index0, const int index1) const {
return ProximityInfoStateUtils::getDirection(
&mSampledInputXs, &mSampledInputYs, index0, index1);
@@ -344,33 +310,9 @@ float ProximityInfoState::getLineToKeyDistance(
keyX, keyY, x0, y0, x1, y1, extend);
}
-// Get a word that is detected by tracing the most probable string into codePointBuf and
-// returns probability of generating the word.
float ProximityInfoState::getMostProbableString(int *const codePointBuf) const {
- static const float DEMOTION_LOG_PROBABILITY = 0.3f;
- int index = 0;
- float sumLogProbability = 0.0f;
- // TODO: Current implementation is greedy algorithm. DP would be efficient for many cases.
- for (int i = 0; i < mSampledInputSize && index < MAX_WORD_LENGTH - 1; ++i) {
- float minLogProbability = static_cast<float>(MAX_POINT_TO_KEY_LENGTH);
- int character = NOT_AN_INDEX;
- for (hash_map_compat<int, float>::const_iterator it = mCharProbabilities[i].begin();
- it != mCharProbabilities[i].end(); ++it) {
- const float logProbability = (it->first != NOT_AN_INDEX)
- ? it->second + DEMOTION_LOG_PROBABILITY : it->second;
- if (logProbability < minLogProbability) {
- minLogProbability = logProbability;
- character = it->first;
- }
- }
- if (character != NOT_AN_INDEX) {
- codePointBuf[index] = mProximityInfo->getCodePointOf(character);
- index++;
- }
- sumLogProbability += minLogProbability;
- }
- codePointBuf[index] = '\0';
- return sumLogProbability;
+ memcpy(codePointBuf, mMostProbableString, sizeof(mMostProbableString));
+ return mMostProbableStringProbability;
}
bool ProximityInfoState::hasSpaceProximity(const int index) const {
diff --git a/native/jni/src/proximity_info_state.h b/native/jni/src/proximity_info_state.h
index 642925c1a..7422cb08f 100644
--- a/native/jni/src/proximity_info_state.h
+++ b/native/jni/src/proximity_info_state.h
@@ -54,10 +54,12 @@ class ProximityInfoState {
mSampledInputIndice(), mSampledLengthCache(), mBeelineSpeedPercentiles(),
mSampledDistanceCache_G(), mSpeedRates(), mDirections(), mCharProbabilities(),
mSampledNearKeysVector(), mSampledSearchKeysVector(),
- mTouchPositionCorrectionEnabled(false), mSampledInputSize(0) {
+ mTouchPositionCorrectionEnabled(false), mSampledInputSize(0),
+ mMostProbableStringProbability(0.0f) {
memset(mInputProximities, 0, sizeof(mInputProximities));
memset(mNormalizedSquaredDistances, 0, sizeof(mNormalizedSquaredDistances));
memset(mPrimaryInputWord, 0, sizeof(mPrimaryInputWord));
+ memset(mMostProbableString, 0, sizeof(mMostProbableString));
}
// Non virtual inline destructor -- never inherit this class
@@ -67,6 +69,21 @@ class ProximityInfoState {
return getProximityCodePointsAt(index)[0];
}
+ inline bool sameAsTyped(const int *word, int length) const {
+ if (length != mSampledInputSize) {
+ return false;
+ }
+ const int *inputProximities = mInputProximities;
+ while (length--) {
+ if (*inputProximities != *word) {
+ return false;
+ }
+ inputProximities += MAX_PROXIMITY_CHARS_SIZE;
+ word++;
+ }
+ return true;
+ }
+
AK_FORCE_INLINE bool existsCodePointInProximityAt(const int index, const int c) const {
const int *codePoints = getProximityCodePointsAt(index);
int i = 0;
@@ -107,23 +124,6 @@ class ProximityInfoState {
return mTouchPositionCorrectionEnabled;
}
- inline bool sameAsTyped(const int *word, int length) const {
- if (length != mSampledInputSize) {
- return false;
- }
- const int *inputProximities = mInputProximities;
- while (length--) {
- if (*inputProximities != *word) {
- return false;
- }
- inputProximities += MAX_PROXIMITY_CHARS_SIZE;
- word++;
- }
- return true;
- }
-
- int getDuration(const int index) const;
-
bool isUsed() const {
return mSampledInputSize > 0;
}
@@ -210,16 +210,9 @@ class ProximityInfoState {
// Defined here //
/////////////////////////////////////////
- bool hasInputCoordinates() const {
- return mSampledInputXs.size() > 0 && mSampledInputYs.size() > 0;
- }
-
inline const int *getProximityCodePointsAt(const int index) const {
return ProximityInfoStateUtils::getProximityCodePointsAt(mInputProximities, index);
}
- bool checkAndReturnIsContinuationPossible(const int inputSize, const int *const xCoordinates,
- const int *const yCoordinates, const int *const times, const bool isGeometric) const;
- void popInputData();
// const
const ProximityInfo *mProximityInfo;
@@ -259,6 +252,8 @@ class ProximityInfoState {
int mNormalizedSquaredDistances[MAX_PROXIMITY_CHARS_SIZE * MAX_WORD_LENGTH];
int mSampledInputSize;
int mPrimaryInputWord[MAX_WORD_LENGTH];
+ float mMostProbableStringProbability;
+ int mMostProbableString[MAX_WORD_LENGTH];
};
} // namespace latinime
#endif // LATINIME_PROXIMITY_INFO_STATE_H
diff --git a/native/jni/src/proximity_info_state_utils.cpp b/native/jni/src/proximity_info_state_utils.cpp
index cbc191ed5..9f85743e5 100644
--- a/native/jni/src/proximity_info_state_utils.cpp
+++ b/native/jni/src/proximity_info_state_utils.cpp
@@ -15,6 +15,7 @@
*/
#include <cmath>
+#include <cstring> // for memset()
#include <sstream> // for debug prints
#include <vector>
@@ -26,6 +27,17 @@
namespace latinime {
+/* static */ int ProximityInfoStateUtils::trimLastTwoTouchPoints(std::vector<int> *sampledInputXs,
+ std::vector<int> *sampledInputYs, std::vector<int> *sampledInputTimes,
+ std::vector<int> *sampledLengthCache, std::vector<int> *sampledInputIndice) {
+ const int nextStartIndex = (*sampledInputIndice)[sampledInputIndice->size() - 2];
+ popInputData(sampledInputXs, sampledInputYs, sampledInputTimes, sampledLengthCache,
+ sampledInputIndice);
+ popInputData(sampledInputXs, sampledInputYs, sampledInputTimes, sampledLengthCache,
+ sampledInputIndice);
+ return nextStartIndex;
+}
+
/* static */ int ProximityInfoStateUtils::updateTouchPoints(const int mostCommonKeyWidth,
const ProximityInfo *const proximityInfo, const int maxPointToKeyLength,
const int *const inputProximities, const int *const inputXCoordinates,
@@ -133,6 +145,7 @@ namespace latinime {
/* static */ void ProximityInfoStateUtils::initPrimaryInputWord(
const int inputSize, const int *const inputProximities, int *primaryInputWord) {
+ memset(primaryInputWord, 0, sizeof(primaryInputWord[0]) * MAX_WORD_LENGTH);
for (int i = 0; i < inputSize; ++i) {
primaryInputWord[i] = getPrimaryCodePointAt(inputProximities, i);
}
@@ -171,10 +184,13 @@ namespace latinime {
/* static */ void ProximityInfoStateUtils::initNormalizedSquaredDistances(
const ProximityInfo *const proximityInfo, const int inputSize,
const int *inputXCoordinates, const int *inputYCoordinates,
- const int *const inputProximities, const bool hasInputCoordinates,
+ const int *const inputProximities,
const std::vector<int> *const sampledInputXs,
const std::vector<int> *const sampledInputYs,
int *normalizedSquaredDistances) {
+ memset(normalizedSquaredDistances, NOT_A_DISTANCE,
+ sizeof(normalizedSquaredDistances[0]) * MAX_PROXIMITY_CHARS_SIZE * MAX_WORD_LENGTH);
+ const bool hasInputCoordinates = sampledInputXs->size() > 0 && sampledInputYs->size() > 0;
for (int i = 0; i < inputSize; ++i) {
const int *proximityCodePoints = getProximityCodePointsAt(inputProximities, i);
const int primaryKey = proximityCodePoints[0];
@@ -983,6 +999,68 @@ namespace latinime {
return true;
}
+/* static */ bool ProximityInfoStateUtils::checkAndReturnIsContinuationPossible(const int inputSize,
+ const int *const xCoordinates, const int *const yCoordinates, const int *const times,
+ const int sampledInputSize, const std::vector<int> *const sampledInputXs,
+ const std::vector<int> *const sampledInputYs,
+ const std::vector<int> *const sampledTimes,
+ const std::vector<int> *const sampledInputIndices) {
+ if (inputSize < sampledInputSize) {
+ return false;
+ }
+ for (int i = 0; i < sampledInputSize; ++i) {
+ const int index = (*sampledInputIndices)[i];
+ if (index >= inputSize) {
+ return false;
+ }
+ if (xCoordinates[index] != (*sampledInputXs)[i]
+ || yCoordinates[index] != (*sampledInputYs)[i]) {
+ return false;
+ }
+ if (!times) {
+ continue;
+ }
+ if (times[index] != (*sampledTimes)[i]) {
+ return false;
+ }
+ }
+ return true;
+}
+
+// Get a word that is detected by tracing the most probable string into codePointBuf and
+// returns probability of generating the word.
+/* static */ float ProximityInfoStateUtils::getMostProbableString(
+ const ProximityInfo *const proximityInfo, const int sampledInputSize,
+ const std::vector<hash_map_compat<int, float> > *const charProbabilities,
+ int *const codePointBuf) {
+ ASSERT(charProbabilities->size() >= 0 && sampledInputSize >= 0);
+ memset(codePointBuf, 0, sizeof(codePointBuf[0]) * MAX_WORD_LENGTH);
+ static const float DEMOTION_LOG_PROBABILITY = 0.3f;
+ int index = 0;
+ float sumLogProbability = 0.0f;
+ // TODO: Current implementation is greedy algorithm. DP would be efficient for many cases.
+ for (int i = 0; i < sampledInputSize && index < MAX_WORD_LENGTH - 1; ++i) {
+ float minLogProbability = static_cast<float>(MAX_POINT_TO_KEY_LENGTH);
+ int character = NOT_AN_INDEX;
+ for (hash_map_compat<int, float>::const_iterator it = (*charProbabilities)[i].begin();
+ it != (*charProbabilities)[i].end(); ++it) {
+ const float logProbability = (it->first != NOT_AN_INDEX)
+ ? it->second + DEMOTION_LOG_PROBABILITY : it->second;
+ if (logProbability < minLogProbability) {
+ minLogProbability = logProbability;
+ character = it->first;
+ }
+ }
+ if (character != NOT_AN_INDEX) {
+ codePointBuf[index] = proximityInfo->getCodePointOf(character);
+ index++;
+ }
+ sumLogProbability += minLogProbability;
+ }
+ codePointBuf[index] = '\0';
+ return sumLogProbability;
+}
+
/* static */ void ProximityInfoStateUtils::dump(const bool isGeometric, const int inputSize,
const int *const inputXCoordinates, const int *const inputYCoordinates,
const int sampledInputSize, const std::vector<int> *const sampledInputXs,
diff --git a/native/jni/src/proximity_info_state_utils.h b/native/jni/src/proximity_info_state_utils.h
index 17ef1c3d7..c8f0aeb75 100644
--- a/native/jni/src/proximity_info_state_utils.h
+++ b/native/jni/src/proximity_info_state_utils.h
@@ -32,6 +32,9 @@ class ProximityInfoStateUtils {
typedef hash_map_compat<int, float> NearKeysDistanceMap;
typedef std::bitset<MAX_KEY_COUNT_IN_A_KEYBOARD> NearKeycodesSet;
+ static int trimLastTwoTouchPoints(std::vector<int> *sampledInputXs,
+ std::vector<int> *sampledInputYs, std::vector<int> *sampledInputTimes,
+ std::vector<int> *sampledLengthCache, std::vector<int> *sampledInputIndice);
static int updateTouchPoints(const int mostCommonKeyWidth,
const ProximityInfo *const proximityInfo, const int maxPointToKeyLength,
const int *const inputProximities,
@@ -96,7 +99,7 @@ class ProximityInfoStateUtils {
static void initNormalizedSquaredDistances(
const ProximityInfo *const proximityInfo, const int inputSize,
const int *inputXCoordinates, const int *inputYCoordinates,
- const int *const inputProximities, const bool hasInputCoordinates,
+ const int *const inputProximities,
const std::vector<int> *const sampledInputXs,
const std::vector<int> *const sampledInputYs,
int *normalizedSquaredDistances);
@@ -107,6 +110,18 @@ class ProximityInfoStateUtils {
const std::vector<int> *const sampledTimes,
const std::vector<float> *const sampledSpeedRates,
const std::vector<int> *const sampledBeelineSpeedPercentiles);
+ static bool checkAndReturnIsContinuationPossible(const int inputSize,
+ const int *const xCoordinates, const int *const yCoordinates, const int *const times,
+ const int sampledInputSize, const std::vector<int> *const sampledInputXs,
+ const std::vector<int> *const sampledInputYs,
+ const std::vector<int> *const sampledTimes,
+ const std::vector<int> *const sampledInputIndices);
+ // TODO: Move to most_probable_string_utils.h
+ static float getMostProbableString(
+ const ProximityInfo *const proximityInfo, const int sampledInputSize,
+ const std::vector<hash_map_compat<int, float> > *const charProbabilities,
+ int *const codePointBuf);
+
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(ProximityInfoStateUtils);