From 28661069591fd1d6a8e25981aaade2e5d8b20b9a Mon Sep 17 00:00:00 2001 From: Keisuke Kuroyanagi Date: Mon, 24 Sep 2012 20:02:57 +0900 Subject: Using relative speed instead of duration rate for gesture input distance calculation. bug: 7165929 Change-Id: I94fe18c57bf19fe58b5050f2c7b3085c6cba6fa8 --- native/jni/src/proximity_info_state.cpp | 40 ++++++++++++++++++++++++++------- native/jni/src/proximity_info_state.h | 7 ++++-- 2 files changed, 37 insertions(+), 10 deletions(-) (limited to 'native/jni/src') diff --git a/native/jni/src/proximity_info_state.cpp b/native/jni/src/proximity_info_state.cpp index c5f2884c6..530ac9e7e 100644 --- a/native/jni/src/proximity_info_state.cpp +++ b/native/jni/src/proximity_info_state.cpp @@ -104,6 +104,7 @@ void ProximityInfoState::initInputParams(const int pointerId, const float maxPoi mLengthCache.clear(); mDistanceCache.clear(); mNearKeysVector.clear(); + mRelativeSpeeds.clear(); } if (DEBUG_GEO_FULL) { AKLOGI("Init ProximityInfoState: reused points = %d, last input size = %d", @@ -159,6 +160,36 @@ void ProximityInfoState::initInputParams(const int pointerId, const float maxPoi mInputSize = mInputXs.size(); } + if (mInputSize > 0 && isGeometric) { + int sumDuration = mTimes.back() - mTimes.front(); + int sumLength = mLengthCache.back() - mLengthCache.front(); + float averageSpeed = static_cast(sumLength) / static_cast(sumDuration); + mRelativeSpeeds.resize(mInputSize); + for (int i = lastSavedInputSize; i < mInputSize; ++i) { + const int index = mInputIndice[i]; + int length = 0; + int duration = 0; + if (index == 0 && index < inputSize - 1) { + length = getDistanceInt(xCoordinates[index], yCoordinates[index], + xCoordinates[index + 1], yCoordinates[index + 1]); + duration = times[index + 1] - times[index]; + } else if (index == inputSize - 1 && index > 0) { + length = getDistanceInt(xCoordinates[index - 1], yCoordinates[index - 1], + xCoordinates[index], yCoordinates[index]); + duration = times[index] - times[index - 1]; + } else if (0 < index && index < inputSize - 1) { + length = getDistanceInt(xCoordinates[index - 1], yCoordinates[index - 1], + xCoordinates[index + 1], yCoordinates[index + 1]); + duration = times[index + 1] - times[index - 1]; + } else { + length = 0; + duration = 1; + } + const float speed = static_cast(length) / static_cast(duration); + mRelativeSpeeds[i] = speed / averageSpeed; + } + } + if (mInputSize > 0) { const int keyCount = mProximityInfo->getKeyCount(); mNearKeysVector.resize(mInputSize); @@ -464,7 +495,7 @@ float ProximityInfoState::calculateNormalizedSquaredDistance( } int ProximityInfoState::getDuration(const int index) const { - if (mInputSize > 0 && index >= 0 && index < mInputSize - 1) { + if (index >= 0 && index < mInputSize - 1) { return mTimes[index + 1] - mTimes[index]; } return 0; @@ -524,13 +555,6 @@ int32_t ProximityInfoState::getAllPossibleChars( return newFilterSize; } -float ProximityInfoState::getAveragePointDuration() const { - if (mInputSize == 0) { - return 0.0f; - } - return static_cast(mTimes[mInputSize - 1] - mTimes[0]) / static_cast(mInputSize); -} - void ProximityInfoState::popInputData() { mInputXs.pop_back(); mInputYs.pop_back(); diff --git a/native/jni/src/proximity_info_state.h b/native/jni/src/proximity_info_state.h index 48862a7c7..c1ec76c38 100644 --- a/native/jni/src/proximity_info_state.h +++ b/native/jni/src/proximity_info_state.h @@ -55,7 +55,7 @@ class ProximityInfoState { mHasTouchPositionCorrectionData(false), mMostCommonKeyWidthSquare(0), mLocaleStr(), mKeyCount(0), mCellHeight(0), mCellWidth(0), mGridHeight(0), mGridWidth(0), mIsContinuationPossible(false), mInputXs(), mInputYs(), mTimes(), mInputIndice(), - mDistanceCache(), mLengthCache(), mNearKeysVector(), + mDistanceCache(), mLengthCache(), mRelativeSpeeds(), mNearKeysVector(), mTouchPositionCorrectionEnabled(false), mInputSize(0) { memset(mInputCodes, 0, sizeof(mInputCodes)); memset(mNormalizedSquaredDistances, 0, sizeof(mNormalizedSquaredDistances)); @@ -220,7 +220,9 @@ class ProximityInfoState { int32_t getAllPossibleChars( const size_t startIndex, int32_t *const filter, const int32_t filterSize) const; - float getAveragePointDuration() const; + float getRelativeSpeed(const int index) const { + return mRelativeSpeeds[index]; + } private: DISALLOW_COPY_AND_ASSIGN(ProximityInfoState); typedef hash_map_compat NearKeysDistanceMap; @@ -283,6 +285,7 @@ class ProximityInfoState { std::vector mInputIndice; std::vector mDistanceCache; std::vector mLengthCache; + std::vector mRelativeSpeeds; std::vector mNearKeysVector; bool mTouchPositionCorrectionEnabled; int32_t mInputCodes[MAX_PROXIMITY_CHARS_SIZE_INTERNAL * MAX_WORD_LENGTH_INTERNAL]; -- cgit v1.2.3-83-g751a From 0edab9d2fcc30667c79aa9221dbb27f042d8b455 Mon Sep 17 00:00:00 2001 From: Satoshi Kataoka Date: Mon, 24 Sep 2012 18:29:31 +0900 Subject: Use touch position correction in the geometric input bug: 7108161 Change-Id: I72d51bcfa26f241bec8fa907d64384e7eebe5c5e --- native/jni/src/proximity_info.cpp | 18 +++++++++++++++--- native/jni/src/proximity_info.h | 4 +--- native/jni/src/proximity_info_state.cpp | 6 +++--- 3 files changed, 19 insertions(+), 9 deletions(-) (limited to 'native/jni/src') diff --git a/native/jni/src/proximity_info.cpp b/native/jni/src/proximity_info.cpp index c9f83b62c..d6990325e 100644 --- a/native/jni/src/proximity_info.cpp +++ b/native/jni/src/proximity_info.cpp @@ -134,10 +134,22 @@ static inline float getNormalizedSquaredDistanceFloat(float x1, float y1, float return (SQUARE_FLOAT(deltaX) + SQUARE_FLOAT(deltaY)) / SQUARE_FLOAT(scale); } -float ProximityInfo::getNormalizedSquaredDistanceFromCenterFloat( +float ProximityInfo::getNormalizedSquaredDistanceFromCenterFloatG( const int keyId, const int x, const int y) const { - const float centerX = static_cast(getKeyCenterXOfKeyIdG(keyId)); - const float centerY = static_cast(getKeyCenterYOfKeyIdG(keyId)); + const static float verticalSweetSpotScaleForGeometric = 1.1f; + const bool correctTouchPosition = hasTouchPositionCorrectionData(); + const float centerX = static_cast(correctTouchPosition + ? getSweetSpotCenterXAt(keyId) + : getKeyCenterXOfKeyIdG(keyId)); + const float visualKeyCenterY = static_cast(getKeyCenterYOfKeyIdG(keyId)); + float centerY; + if (correctTouchPosition) { + const float sweetSpotCenterY = static_cast(getSweetSpotCenterYAt(keyId)); + const float gapY = sweetSpotCenterY - visualKeyCenterY; + centerY = visualKeyCenterY + gapY * verticalSweetSpotScaleForGeometric; + } else { + centerY = visualKeyCenterY; + } const float touchX = static_cast(x); const float touchY = static_cast(y); const float keyWidth = static_cast(getMostCommonKeyWidth()); diff --git a/native/jni/src/proximity_info.h b/native/jni/src/proximity_info.h index 0d8c6a3ca..2947f9ba6 100644 --- a/native/jni/src/proximity_info.h +++ b/native/jni/src/proximity_info.h @@ -44,7 +44,7 @@ class ProximityInfo { ~ProximityInfo(); bool hasSpaceProximity(const int x, const int y) const; int getNormalizedSquaredDistance(const int inputIndex, const int proximityIndex) const; - float getNormalizedSquaredDistanceFromCenterFloat( + float getNormalizedSquaredDistanceFromCenterFloatG( const int keyId, const int x, const int y) const; bool sameAsTyped(const unsigned short *word, int length) const; int getKeyIndexOf(const int c) const; @@ -123,8 +123,6 @@ class ProximityInfo { int getStartIndexFromCoordinates(const int x, const int y) const; void initializeG(); float calculateNormalizedSquaredDistance(const int keyIndex, const int inputIndex) const; - float calculateSquaredDistanceFromSweetSpotCenter( - const int keyIndex, const int inputIndex) const; bool hasInputCoordinates() 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 { diff --git a/native/jni/src/proximity_info_state.cpp b/native/jni/src/proximity_info_state.cpp index c5f2884c6..cefe8ab4d 100644 --- a/native/jni/src/proximity_info_state.cpp +++ b/native/jni/src/proximity_info_state.cpp @@ -171,7 +171,7 @@ void ProximityInfoState::initInputParams(const int pointerId, const float maxPoi const int x = mInputXs[i]; const int y = mInputYs[i]; const float normalizedSquaredDistance = - mProximityInfo->getNormalizedSquaredDistanceFromCenterFloat(k, x, y); + mProximityInfo->getNormalizedSquaredDistanceFromCenterFloatG(k, x, y); mDistanceCache[index] = normalizedSquaredDistance; if (normalizedSquaredDistance < NEAR_KEY_NORMALIZED_SQUARED_THRESHOLD) { mNearKeysVector[i].set(k, 1); @@ -203,7 +203,7 @@ void ProximityInfoState::initInputParams(const int pointerId, const float maxPoi memset(mNormalizedSquaredDistances, NOT_A_DISTANCE, sizeof(mNormalizedSquaredDistances)); memset(mPrimaryInputWord, 0, sizeof(mPrimaryInputWord)); mTouchPositionCorrectionEnabled = mInputSize > 0 && mHasTouchPositionCorrectionData - && xCoordinates && yCoordinates && !isGeometric; + && xCoordinates && yCoordinates; if (!isGeometric && pointerId == 0) { for (int i = 0; i < inputSize; ++i) { mPrimaryInputWord[i] = getPrimaryCharAt(i); @@ -267,7 +267,7 @@ float ProximityInfoState::updateNearKeysDistances(const int x, const int y, const int keyCount = mProximityInfo->getKeyCount(); float nearestKeyDistance = mMaxPointToKeyLength; for (int k = 0; k < keyCount; ++k) { - const float dist = mProximityInfo->getNormalizedSquaredDistanceFromCenterFloat(k, x, y); + const float dist = mProximityInfo->getNormalizedSquaredDistanceFromCenterFloatG(k, x, y); if (dist < NEAR_KEY_THRESHOLD) { currentNearKeysDistances->insert(std::pair(k, dist)); } -- cgit v1.2.3-83-g751a From 4d75fe9bcaaf63d61bdafea3ad88ea22ebe54430 Mon Sep 17 00:00:00 2001 From: Keisuke Kuroyanagi Date: Tue, 25 Sep 2012 13:03:56 +0900 Subject: FIX: Wrong way to gesture speed calculation. This is a follow-up to bug: 7165929 Change-Id: I7ad2bbd1f6ef1f74ea8770585f584d4232cb40b5 --- native/jni/src/proximity_info_state.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'native/jni/src') diff --git a/native/jni/src/proximity_info_state.cpp b/native/jni/src/proximity_info_state.cpp index fbca7200e..392ec8194 100644 --- a/native/jni/src/proximity_info_state.cpp +++ b/native/jni/src/proximity_info_state.cpp @@ -179,7 +179,9 @@ void ProximityInfoState::initInputParams(const int pointerId, const float maxPoi duration = times[index] - times[index - 1]; } else if (0 < index && index < inputSize - 1) { length = getDistanceInt(xCoordinates[index - 1], yCoordinates[index - 1], - xCoordinates[index + 1], yCoordinates[index + 1]); + xCoordinates[index], yCoordinates[index]) + + getDistanceInt(xCoordinates[index], yCoordinates[index], + xCoordinates[index + 1], yCoordinates[index + 1]); duration = times[index + 1] - times[index - 1]; } else { length = 0; @@ -509,7 +511,7 @@ float ProximityInfoState::getPointToKeyLength(const int inputIndex, const int co return min(mDistanceCache[index] * scale, mMaxPointToKeyLength); } if (isSkippableChar(codePoint)) { - return 0; + return 0.0f; } // If the char is not a key on the keyboard then return the max length. return MAX_POINT_TO_KEY_LENGTH; -- cgit v1.2.3-83-g751a From edd5b7365f4ed709426cd685d5506b9461c9a2f9 Mon Sep 17 00:00:00 2001 From: Tom Ouyang Date: Tue, 25 Sep 2012 17:04:35 -0700 Subject: Fix lower case conversion bug for some characters Bug: 7232296 Change-Id: Iaf3f6be55f1bdc2294533938bb54fedcf25fb0cb --- native/jni/src/char_utils.cpp | 2 ++ native/jni/src/char_utils.h | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'native/jni/src') diff --git a/native/jni/src/char_utils.cpp b/native/jni/src/char_utils.cpp index 9d886da31..d0547a982 100644 --- a/native/jni/src/char_utils.cpp +++ b/native/jni/src/char_utils.cpp @@ -88,6 +88,7 @@ static const struct LatinCapitalSmallPair SORTED_CHAR_MAP[] = { { 0x00C5, 0x00E5 }, // LATIN CAPITAL LETTER A WITH RING ABOVE { 0x00C6, 0x00E6 }, // LATIN CAPITAL LETTER AE { 0x00D0, 0x00F0 }, // LATIN CAPITAL LETTER ETH + { 0x00D1, 0x00F1 }, // LATIN CAPITAL LETTER N WITH TILDE { 0x00D5, 0x00F5 }, // LATIN CAPITAL LETTER O WITH TILDE { 0x00D6, 0x00F6 }, // LATIN CAPITAL LETTER O WITH DIAERESIS { 0x00D8, 0x00F8 }, // LATIN CAPITAL LETTER O WITH STROKE @@ -219,6 +220,7 @@ static const struct LatinCapitalSmallPair SORTED_CHAR_MAP[] = { { 0x0416, 0x0436 }, // CYRILLIC CAPITAL LETTER ZHE { 0x0417, 0x0437 }, // CYRILLIC CAPITAL LETTER ZE { 0x0418, 0x0438 }, // CYRILLIC CAPITAL LETTER I + { 0x0419, 0x0439 }, // CYRILLIC CAPITAL LETTER SHORT I { 0x041A, 0x043A }, // CYRILLIC CAPITAL LETTER KA { 0x041B, 0x043B }, // CYRILLIC CAPITAL LETTER EL { 0x041C, 0x043C }, // CYRILLIC CAPITAL LETTER EM diff --git a/native/jni/src/char_utils.h b/native/jni/src/char_utils.h index b17f262ec..20cf2e8b5 100644 --- a/native/jni/src/char_utils.h +++ b/native/jni/src/char_utils.h @@ -23,7 +23,9 @@ namespace latinime { inline static bool isAsciiUpper(unsigned short c) { - return isupper(static_cast(c)) != 0; + // Note: isupper(...) reports false positives for some Cyrillic characters, causing them to + // be incorrectly lower-cased using toAsciiLower(...) rather than latin_tolower(...). + return (c >= 'A' && c <= 'Z'); } inline static unsigned short toAsciiLower(unsigned short c) { -- cgit v1.2.3-83-g751a From f34ec5aa9557d9986a296c3e636b5c1ab42ff641 Mon Sep 17 00:00:00 2001 From: Tom Ouyang Date: Tue, 25 Sep 2012 00:06:31 -0700 Subject: Make gestures work correctly on keyboards with accented keys Examples: Spanish, Russian Bug: 7225962 Change-Id: I6887bc6d81b84e4a73a74de679b955f7abf0ba4f --- native/jni/src/proximity_info.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'native/jni/src') diff --git a/native/jni/src/proximity_info.cpp b/native/jni/src/proximity_info.cpp index d6990325e..fde93b5a9 100644 --- a/native/jni/src/proximity_info.cpp +++ b/native/jni/src/proximity_info.cpp @@ -239,8 +239,8 @@ int ProximityInfo::getKeyIndexOf(const int c) const { // We do not have the coordinate data return NOT_AN_INDEX; } - const int baseLowerC = static_cast(toBaseLowerCase(c)); - hash_map_compat::const_iterator mapPos = mCodeToKeyMap.find(baseLowerC); + const int lowerCode = static_cast(toLowerCase(c)); + hash_map_compat::const_iterator mapPos = mCodeToKeyMap.find(lowerCode); if (mapPos != mCodeToKeyMap.end()) { return mapPos->second; } @@ -258,7 +258,7 @@ void ProximityInfo::initializeG() { // TODO: Optimize for (int i = 0; i < KEY_COUNT; ++i) { const int code = mKeyCodePoints[i]; - const int lowerCode = toBaseLowerCase(code); + const int lowerCode = static_cast(toLowerCase(code)); mCenterXsG[i] = mKeyXCoordinates[i] + mKeyWidths[i] / 2; mCenterYsG[i] = mKeyYCoordinates[i] + mKeyHeights[i] / 2; mCodeToKeyMap[lowerCode] = i; -- cgit v1.2.3-83-g751a From 5150e154f0fca74c40eb8898fd0eba81382f8878 Mon Sep 17 00:00:00 2001 From: Ken Wakasa Date: Thu, 27 Sep 2012 19:21:25 +0900 Subject: Cleanups in LatinIME native source code Change-Id: I9b5e57583deb2d0c980e66c3dfbfd1e12734bc8e --- native/jni/src/char_utils.h | 6 ++++++ native/jni/src/defines.h | 3 +++ native/jni/src/geometry_utils.h | 4 ---- native/jni/src/proximity_info.h | 5 ----- 4 files changed, 9 insertions(+), 9 deletions(-) (limited to 'native/jni/src') diff --git a/native/jni/src/char_utils.h b/native/jni/src/char_utils.h index 20cf2e8b5..9008e364c 100644 --- a/native/jni/src/char_utils.h +++ b/native/jni/src/char_utils.h @@ -67,5 +67,11 @@ inline static unsigned short toLowerCase(const unsigned short c) { inline static unsigned short toBaseLowerCase(const unsigned short c) { return toLowerCase(toBaseChar(c)); } + +inline static bool isSkippableChar(const uint16_t character) { + // TODO: Do not hardcode here + return character == '\'' || character == '-'; +} + } // namespace latinime #endif // LATINIME_CHAR_UTILS_H diff --git a/native/jni/src/defines.h b/native/jni/src/defines.h index ad526fb7f..ea0f0ef70 100644 --- a/native/jni/src/defines.h +++ b/native/jni/src/defines.h @@ -368,6 +368,9 @@ static inline void prof_out(void) { #define MIN_USER_TYPED_LENGTH_FOR_MULTIPLE_WORD_SUGGESTION 3 #define MIN_USER_TYPED_LENGTH_FOR_EXCESSIVE_CHARACTER_SUGGESTION 3 +// TODO: Remove +#define MAX_POINTER_COUNT_FOR_G 2 + // Size, in bytes, of the bloom filter index for bigrams // 128 gives us 1024 buckets. The probability of false positive is (1 - e ** (-kn/m))**k, // where k is the number of hash functions, n the number of bigrams, and m the number of diff --git a/native/jni/src/geometry_utils.h b/native/jni/src/geometry_utils.h index 3892b46a0..31359e19d 100644 --- a/native/jni/src/geometry_utils.h +++ b/native/jni/src/geometry_utils.h @@ -19,15 +19,11 @@ #include -#define MAX_PATHS 2 - #define DEBUG_DECODER false #define M_PI_F 3.14159265f - #define ROUND_FLOAT_10000(f) ((f) < 1000.0f && (f) > 0.001f) \ ? (floorf((f) * 10000.0f) / 10000.0f) : (f) - #define SQUARE_FLOAT(x) ((x) * (x)) namespace latinime { diff --git a/native/jni/src/proximity_info.h b/native/jni/src/proximity_info.h index 2947f9ba6..70942aa19 100644 --- a/native/jni/src/proximity_info.h +++ b/native/jni/src/proximity_info.h @@ -27,11 +27,6 @@ namespace latinime { class Correction; -inline bool isSkippableChar(const uint16_t character) { - // TODO: Do not hardcode here - return character == '\'' || character == '-'; -} - class ProximityInfo { public: ProximityInfo(JNIEnv *env, const jstring localeJStr, const int maxProximityCharsSize, -- cgit v1.2.3-83-g751a From 441b3e5a906d12207ee4522849053679506207e5 Mon Sep 17 00:00:00 2001 From: Satoshi Kataoka Date: Fri, 5 Oct 2012 20:54:57 +0900 Subject: Fix addtional proximity correction Change-Id: I3125764b98af28ce423dc12cbf0dac321ef22386 --- native/jni/src/correction.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'native/jni/src') diff --git a/native/jni/src/correction.cpp b/native/jni/src/correction.cpp index 49e3e3c8c..26d8ed715 100644 --- a/native/jni/src/correction.cpp +++ b/native/jni/src/correction.cpp @@ -764,13 +764,23 @@ int Correction::RankingAlgorithm::calculateFinalProbability(const int inputIndex } } + int additionalProximityCount = 0; + // Demote additional proximity characters + for (int i = 0; i < outputLength; ++i) { + const int squaredDistance = correction->mDistances[i]; + if (squaredDistance == ADDITIONAL_PROXIMITY_CHAR_DISTANCE_INFO) { + ++additionalProximityCount; + } + } + const bool performTouchPositionCorrection = CALIBRATE_SCORE_BY_TOUCH_COORDINATES && proximityInfoState->touchPositionCorrectionEnabled() - && skippedCount == 0 && excessiveCount == 0 && transposedCount == 0; + && skippedCount == 0 && excessiveCount == 0 && transposedCount == 0 + && additionalProximityCount == 0; + // Score calibration by touch coordinates is being done only for pure-fat finger typing error // cases. - int additionalProximityCount = 0; // TODO: Remove this constraint. if (performTouchPositionCorrection) { for (int i = 0; i < outputLength; ++i) { @@ -802,19 +812,9 @@ int Correction::RankingAlgorithm::calculateFinalProbability(const int inputIndex multiplyRate((int)(factor * 100), &finalFreq); } else if (squaredDistance == PROXIMITY_CHAR_WITHOUT_DISTANCE_INFO) { multiplyRate(WORDS_WITH_PROXIMITY_CHARACTER_DEMOTION_RATE, &finalFreq); - } else if (squaredDistance == ADDITIONAL_PROXIMITY_CHAR_DISTANCE_INFO) { - ++additionalProximityCount; - multiplyRate(WORDS_WITH_ADDITIONAL_PROXIMITY_CHARACTER_DEMOTION_RATE, &finalFreq); } } } else { - // Demote additional proximity characters - for (int i = 0; i < outputLength; ++i) { - const int squaredDistance = correction->mDistances[i]; - if (squaredDistance == ADDITIONAL_PROXIMITY_CHAR_DISTANCE_INFO) { - ++additionalProximityCount; - } - } // Promotion for a word with proximity characters for (int i = 0; i < adjustedProximityMatchedCount; ++i) { // A word with proximity corrections -- cgit v1.2.3-83-g751a From 448e732272bb3e55d649d2d5dd6a0acb9efdaec3 Mon Sep 17 00:00:00 2001 From: Satoshi Kataoka Date: Fri, 5 Oct 2012 21:16:23 +0900 Subject: Follow up change for I5f166a738f6e84a1b807be Bug: 7283955 Change-Id: Iec716d75e7c8a727b198688f44ef4a8cd1255ec1 --- native/jni/src/correction.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'native/jni/src') diff --git a/native/jni/src/correction.cpp b/native/jni/src/correction.cpp index 26d8ed715..524abe9a1 100644 --- a/native/jni/src/correction.cpp +++ b/native/jni/src/correction.cpp @@ -799,9 +799,9 @@ int Correction::RankingAlgorithm::calculateFinalProbability(const int inputIndex const float x = static_cast(squaredDistance) / 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); - // factor is piecewise linear function like: + ? (A * (R1 - x) + B * x) / R1 + : (B * (R2 - x) + C * (x - R1)) / (R2 - R1), MIN); + // factor is a piecewise linear function like: // A -_ . // ^-_ . // B \ . @@ -809,7 +809,7 @@ int Correction::RankingAlgorithm::calculateFinalProbability(const int inputIndex // C ------------. // . // 0 R1 R2 . - multiplyRate((int)(factor * 100), &finalFreq); + multiplyRate((int)(factor * 100.0f), &finalFreq); } else if (squaredDistance == PROXIMITY_CHAR_WITHOUT_DISTANCE_INFO) { multiplyRate(WORDS_WITH_PROXIMITY_CHARACTER_DEMOTION_RATE, &finalFreq); } -- cgit v1.2.3-83-g751a From b02ee3d67a1884b6ff59cc16c29a476845c0694f Mon Sep 17 00:00:00 2001 From: Ken Wakasa Date: Mon, 8 Oct 2012 11:46:14 +0900 Subject: Make use of the NELEMS and KEYCODE_SPACE macro. Also, remove an unused parameter. Change-Id: I3c7e6c59990c92b0d5e2fb80493e8673cdd37b09 --- .../inputmethod/latin/BinaryDictionary.java | 12 ++++------- ..._android_inputmethod_keyboard_ProximityInfo.cpp | 6 +++--- ..._android_inputmethod_latin_BinaryDictionary.cpp | 12 +++++------ ...ndroid_inputmethod_latin_DicTraverseSession.cpp | 4 ++-- native/jni/src/char_utils.cpp | 7 +++---- native/jni/src/correction.cpp | 2 +- native/jni/src/correction.h | 1 - native/jni/src/defines.h | 6 ++++-- native/jni/src/dictionary.cpp | 7 +++---- native/jni/src/dictionary.h | 4 ++-- native/jni/src/proximity_info_state.cpp | 2 +- native/jni/src/unigram_dictionary.cpp | 24 ++++++++-------------- native/jni/src/unigram_dictionary.h | 5 ++--- 13 files changed, 39 insertions(+), 53 deletions(-) (limited to 'native/jni/src') diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionary.java b/java/src/com/android/inputmethod/latin/BinaryDictionary.java index 7184f1d8a..9c48aa1a4 100644 --- a/java/src/com/android/inputmethod/latin/BinaryDictionary.java +++ b/java/src/com/android/inputmethod/latin/BinaryDictionary.java @@ -31,7 +31,7 @@ import java.util.Locale; * Implements a static, compacted, binary dictionary of standard words. */ public final class BinaryDictionary extends Dictionary { - + private static final String TAG = BinaryDictionary.class.getSimpleName(); public static final String DICTIONARY_PACK_AUTHORITY = "com.android.inputmethod.latin.dictionarypack"; @@ -45,12 +45,9 @@ public final class BinaryDictionary extends Dictionary { public static final int MAX_WORDS = 18; public static final int MAX_SPACES = 16; - private static final String TAG = BinaryDictionary.class.getSimpleName(); private static final int MAX_PREDICTIONS = 60; private static final int MAX_RESULTS = Math.max(MAX_PREDICTIONS, MAX_WORDS); - private static final int TYPED_LETTER_MULTIPLIER = 2; - private long mNativeDict; private final Locale mLocale; private final int[] mInputCodePoints = new int[MAX_WORD_LENGTH]; @@ -106,8 +103,7 @@ public final class BinaryDictionary extends Dictionary { } private native long openNative(String sourceDir, long dictOffset, long dictSize, - int typedLetterMultiplier, int fullWordMultiplier, int maxWordLength, int maxWords, - int maxPredictions); + int fullWordMultiplier, int maxWordLength, int maxWords, int maxPredictions); private native void closeNative(long dict); private native int getFrequencyNative(long dict, int[] word); private native boolean isValidBigramNative(long dict, int[] word1, int[] word2); @@ -121,8 +117,8 @@ public final class BinaryDictionary extends Dictionary { // TODO: Move native dict into session private final void loadDictionary(String path, long startOffset, long length) { - mNativeDict = openNative(path, startOffset, length, TYPED_LETTER_MULTIPLIER, - FULL_WORD_SCORE_MULTIPLIER, MAX_WORD_LENGTH, MAX_WORDS, MAX_PREDICTIONS); + mNativeDict = openNative(path, startOffset, length, FULL_WORD_SCORE_MULTIPLIER, + MAX_WORD_LENGTH, MAX_WORDS, MAX_PREDICTIONS); } @Override diff --git a/native/jni/com_android_inputmethod_keyboard_ProximityInfo.cpp b/native/jni/com_android_inputmethod_keyboard_ProximityInfo.cpp index 560b3a533..2423bb53b 100644 --- a/native/jni/com_android_inputmethod_keyboard_ProximityInfo.cpp +++ b/native/jni/com_android_inputmethod_keyboard_ProximityInfo.cpp @@ -17,6 +17,7 @@ #define LOG_TAG "LatinIME: jni: ProximityInfo" #include "com_android_inputmethod_keyboard_ProximityInfo.h" +#include "defines.h" #include "jni.h" #include "jni_common.h" #include "proximity_info.h" @@ -41,7 +42,7 @@ static void latinime_Keyboard_release(JNIEnv *env, jobject object, jlong proximi delete pi; } -static JNINativeMethod sKeyboardMethods[] = { +static JNINativeMethod sMethods[] = { {"setProximityInfoNative", "(Ljava/lang/String;IIIIII[II[I[I[I[I[I[F[F[F)J", reinterpret_cast(latinime_Keyboard_setProximityInfo)}, {"releaseProximityInfoNative", "(J)V", reinterpret_cast(latinime_Keyboard_release)} @@ -49,7 +50,6 @@ static JNINativeMethod sKeyboardMethods[] = { int register_ProximityInfo(JNIEnv *env) { const char *const kClassPathName = "com/android/inputmethod/keyboard/ProximityInfo"; - return registerNativeMethods(env, kClassPathName, sKeyboardMethods, - sizeof(sKeyboardMethods) / sizeof(sKeyboardMethods[0])); + return registerNativeMethods(env, kClassPathName, sMethods, NELEMS(sMethods)); } } // namespace latinime diff --git a/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp b/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp index dd2513f9f..42f7da9d3 100644 --- a/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp +++ b/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp @@ -44,9 +44,8 @@ class ProximityInfo; static void releaseDictBuf(const void *dictBuf, const size_t length, const int fd); static jlong latinime_BinaryDictionary_open(JNIEnv *env, jobject object, - jstring sourceDir, jlong dictOffset, jlong dictSize, - jint typedLetterMultiplier, jint fullWordMultiplier, jint maxWordLength, jint maxWords, - jint maxPredictions) { + jstring sourceDir, jlong dictOffset, jlong dictSize, jint fullWordMultiplier, + jint maxWordLength, jint maxWords, jint maxPredictions) { PROF_OPEN; PROF_START(66); const jsize sourceDirUtf8Length = env->GetStringUTFLength(sourceDir); @@ -121,7 +120,7 @@ static jlong latinime_BinaryDictionary_open(JNIEnv *env, jobject object, #endif // USE_MMAP_FOR_DICTIONARY } else { dictionary = new Dictionary(dictBuf, static_cast(dictSize), fd, adjust, - typedLetterMultiplier, fullWordMultiplier, maxWordLength, maxWords, maxPredictions); + fullWordMultiplier, maxWordLength, maxWords, maxPredictions); } PROF_END(66); PROF_CLOSE; @@ -277,7 +276,7 @@ static void releaseDictBuf(const void *dictBuf, const size_t length, const int f } static JNINativeMethod sMethods[] = { - {"openNative", "(Ljava/lang/String;JJIIIII)J", + {"openNative", "(Ljava/lang/String;JJIIII)J", reinterpret_cast(latinime_BinaryDictionary_open)}, {"closeNative", "(J)V", reinterpret_cast(latinime_BinaryDictionary_close)}, {"getSuggestionsNative", "(JJJ[I[I[I[I[IIIZ[IZ[C[I[I[I)I", @@ -294,7 +293,6 @@ static JNINativeMethod sMethods[] = { int register_BinaryDictionary(JNIEnv *env) { const char *const kClassPathName = "com/android/inputmethod/latin/BinaryDictionary"; - return registerNativeMethods(env, kClassPathName, sMethods, - sizeof(sMethods) / sizeof(sMethods[0])); + return registerNativeMethods(env, kClassPathName, sMethods, NELEMS(sMethods)); } } // namespace latinime diff --git a/native/jni/com_android_inputmethod_latin_DicTraverseSession.cpp b/native/jni/com_android_inputmethod_latin_DicTraverseSession.cpp index 5d405f117..7bb8dc56e 100644 --- a/native/jni/com_android_inputmethod_latin_DicTraverseSession.cpp +++ b/native/jni/com_android_inputmethod_latin_DicTraverseSession.cpp @@ -17,6 +17,7 @@ #define LOG_TAG "LatinIME: jni: Session" #include "com_android_inputmethod_latin_DicTraverseSession.h" +#include "defines.h" #include "dic_traverse_wrapper.h" #include "jni.h" #include "jni_common.h" @@ -57,7 +58,6 @@ static JNINativeMethod sMethods[] = { int register_DicTraverseSession(JNIEnv *env) { const char *const kClassPathName = "com/android/inputmethod/latin/DicTraverseSession"; - return registerNativeMethods(env, kClassPathName, sMethods, - sizeof(sMethods) / sizeof(sMethods[0])); + return registerNativeMethods(env, kClassPathName, sMethods, NELEMS(sMethods)); } } // namespace latinime diff --git a/native/jni/src/char_utils.cpp b/native/jni/src/char_utils.cpp index d0547a982..9d27cadad 100644 --- a/native/jni/src/char_utils.cpp +++ b/native/jni/src/char_utils.cpp @@ -17,6 +17,7 @@ #include #include "char_utils.h" +#include "defines.h" namespace latinime { @@ -33,7 +34,7 @@ struct LatinCapitalSmallPair { // // unsigned short c, cc, ccc, ccc2; // for (c = 0; c < 0xFFFF ; c++) { -// if (c < sizeof(BASE_CHARS) / sizeof(BASE_CHARS[0])) { +// if (c < NELEMS(BASE_CHARS)) { // cc = BASE_CHARS[c]; // } else { // cc = c; @@ -894,9 +895,7 @@ static int compare_pair_capital(const void *a, const void *b) { unsigned short latin_tolower(const unsigned short c) { struct LatinCapitalSmallPair *p = static_cast(bsearch(&c, SORTED_CHAR_MAP, - sizeof(SORTED_CHAR_MAP) / sizeof(SORTED_CHAR_MAP[0]), - sizeof(SORTED_CHAR_MAP[0]), - compare_pair_capital)); + NELEMS(SORTED_CHAR_MAP), sizeof(SORTED_CHAR_MAP[0]), compare_pair_capital)); return p ? p->small : c; } } // namespace latinime diff --git a/native/jni/src/correction.cpp b/native/jni/src/correction.cpp index 524abe9a1..d57b0e370 100644 --- a/native/jni/src/correction.cpp +++ b/native/jni/src/correction.cpp @@ -1118,7 +1118,7 @@ float Correction::RankingAlgorithm::calcNormalizedScore(const unsigned short *be const int distance = editDistance(before, beforeLength, after, afterLength); int spaceCount = 0; for (int i = 0; i < afterLength; ++i) { - if (after[i] == CODE_SPACE) { + if (after[i] == KEYCODE_SPACE) { ++spaceCount; } } diff --git a/native/jni/src/correction.h b/native/jni/src/correction.h index f016d5453..a099853e6 100644 --- a/native/jni/src/correction.h +++ b/native/jni/src/correction.h @@ -116,7 +116,6 @@ class Correction { static int editDistance(const unsigned short *before, const int beforeLength, const unsigned short *after, const int afterLength); private: - static const int CODE_SPACE = ' '; static const int MAX_INITIAL_SCORE = 255; }; diff --git a/native/jni/src/defines.h b/native/jni/src/defines.h index ea0f0ef70..1bb031312 100644 --- a/native/jni/src/defines.h +++ b/native/jni/src/defines.h @@ -344,8 +344,8 @@ static inline void prof_out(void) { #define MULTIPLE_WORDS_DEMOTION_RATE 80 #define MIN_INPUT_LENGTH_FOR_THREE_OR_MORE_WORDS_CORRECTION 6 -#define TWO_WORDS_CORRECTION_WITH_OTHER_ERROR_THRESHOLD 0.35 -#define START_TWO_WORDS_CORRECTION_THRESHOLD 0.185 +#define TWO_WORDS_CORRECTION_WITH_OTHER_ERROR_THRESHOLD 0.35f +#define START_TWO_WORDS_CORRECTION_THRESHOLD 0.185f /* heuristic... This should be changed if we change the unit of the frequency. */ #define SUPPRESS_SHORT_MULTIPLE_WORDS_THRESHOLD_FREQ (MAX_FREQ * 58 / 100) @@ -392,6 +392,8 @@ static inline void prof_out(void) { template inline T min(T a, T b) { return a < b ? a : b; } template inline T max(T a, T b) { return a > b ? a : b; } +#define NELEMS(x) (sizeof(x) / sizeof((x)[0])) + // The ratio of neutral area radius to sweet spot radius. #define NEUTRAL_AREA_RADIUS_RATIO 1.3f diff --git a/native/jni/src/dictionary.cpp b/native/jni/src/dictionary.cpp index 2fbe83e86..81789ccfc 100644 --- a/native/jni/src/dictionary.cpp +++ b/native/jni/src/dictionary.cpp @@ -30,13 +30,12 @@ namespace latinime { // TODO: Change the type of all keyCodes to uint32_t Dictionary::Dictionary(void *dict, int dictSize, int mmapFd, int dictBufAdjust, - int typedLetterMultiplier, int fullWordMultiplier, int maxWordLength, int maxWords, - int maxPredictions) + int fullWordMultiplier, int maxWordLength, int maxWords, int maxPredictions) : mDict(static_cast(dict)), mOffsetDict((static_cast(dict)) + BinaryFormat::getHeaderSize(mDict)), mDictSize(dictSize), mMmapFd(mmapFd), mDictBufAdjust(dictBufAdjust), - mUnigramDictionary(new UnigramDictionary(mOffsetDict, typedLetterMultiplier, - fullWordMultiplier, maxWordLength, maxWords, BinaryFormat::getFlags(mDict))), + mUnigramDictionary(new UnigramDictionary(mOffsetDict, fullWordMultiplier, maxWordLength, + maxWords, BinaryFormat::getFlags(mDict))), mBigramDictionary(new BigramDictionary(mOffsetDict, maxWordLength, maxPredictions)), mGestureDecoder(new GestureDecoderWrapper(maxWordLength, maxWords)) { if (DEBUG_DICT) { diff --git a/native/jni/src/dictionary.h b/native/jni/src/dictionary.h index a1358890d..120ca5f7f 100644 --- a/native/jni/src/dictionary.h +++ b/native/jni/src/dictionary.h @@ -41,8 +41,8 @@ class Dictionary { const static int KIND_SHORTCUT = 7; // A shortcut const static int KIND_PREDICTION = 8; // A prediction (== a suggestion with no input) - Dictionary(void *dict, int dictSize, int mmapFd, int dictBufAdjust, int typedLetterMultipler, - int fullWordMultiplier, int maxWordLength, int maxWords, int maxPredictions); + Dictionary(void *dict, int dictSize, int mmapFd, int dictBufAdjust, int fullWordMultiplier, + int maxWordLength, int maxWords, int maxPredictions); int getSuggestions(ProximityInfo *proximityInfo, void *traverseSession, int *xcoordinates, int *ycoordinates, int *times, int *pointerIds, int *codes, int codesSize, diff --git a/native/jni/src/proximity_info_state.cpp b/native/jni/src/proximity_info_state.cpp index 392ec8194..015174356 100644 --- a/native/jni/src/proximity_info_state.cpp +++ b/native/jni/src/proximity_info_state.cpp @@ -518,7 +518,7 @@ float ProximityInfoState::getPointToKeyLength(const int inputIndex, const int co } int ProximityInfoState::getSpaceY() const { - const int keyId = mProximityInfo->getKeyIndexOf(' '); + const int keyId = mProximityInfo->getKeyIndexOf(KEYCODE_SPACE); return mProximityInfo->getKeyCenterYOfKeyIdG(keyId); } diff --git a/native/jni/src/unigram_dictionary.cpp b/native/jni/src/unigram_dictionary.cpp index 49d044fbc..3b485a055 100644 --- a/native/jni/src/unigram_dictionary.cpp +++ b/native/jni/src/unigram_dictionary.cpp @@ -41,14 +41,12 @@ const UnigramDictionary::digraph_t UnigramDictionary::FRENCH_LIGATURES_DIGRAPHS[ { 'o', 'e', 0x0153 } }; // U+0153 : LATIN SMALL LIGATURE OE // TODO: check the header -UnigramDictionary::UnigramDictionary(const uint8_t *const streamStart, int typedLetterMultiplier, - int fullWordMultiplier, int maxWordLength, int maxWords, const unsigned int flags) - : DICT_ROOT(streamStart), MAX_WORD_LENGTH(maxWordLength), MAX_WORDS(maxWords), - TYPED_LETTER_MULTIPLIER(typedLetterMultiplier), FULL_WORD_MULTIPLIER(fullWordMultiplier), - // TODO : remove this variable. - ROOT_POS(0), - BYTES_IN_ONE_CHAR(sizeof(int)), - MAX_DIGRAPH_SEARCH_DEPTH(DEFAULT_MAX_DIGRAPH_SEARCH_DEPTH), FLAGS(flags) { +UnigramDictionary::UnigramDictionary(const uint8_t *const streamStart, int fullWordMultiplier, + int maxWordLength, int maxWords, const unsigned int flags) + : DICT_ROOT(streamStart), MAX_WORD_LENGTH(maxWordLength), MAX_WORDS(maxWords), + FULL_WORD_MULTIPLIER(fullWordMultiplier), // TODO : remove this variable. + ROOT_POS(0), BYTES_IN_ONE_CHAR(sizeof(int)), + MAX_DIGRAPH_SEARCH_DEPTH(DEFAULT_MAX_DIGRAPH_SEARCH_DEPTH), FLAGS(flags) { if (DEBUG_DICT) { AKLOGI("UnigramDictionary - constructor"); } @@ -188,8 +186,7 @@ int UnigramDictionary::getSuggestions(ProximityInfo *proximityInfo, const int *x getWordWithDigraphSuggestionsRec(proximityInfo, xcoordinates, ycoordinates, codesBuffer, xCoordinatesBuffer, yCoordinatesBuffer, codesSize, bigramMap, bigramFilter, useFullEditDistance, codes, codesSize, 0, codesBuffer, &masterCorrection, - &queuePool, GERMAN_UMLAUT_DIGRAPHS, - sizeof(GERMAN_UMLAUT_DIGRAPHS) / sizeof(GERMAN_UMLAUT_DIGRAPHS[0])); + &queuePool, GERMAN_UMLAUT_DIGRAPHS, NELEMS(GERMAN_UMLAUT_DIGRAPHS)); } else if (BinaryFormat::REQUIRES_FRENCH_LIGATURES_PROCESSING & FLAGS) { int codesBuffer[getCodesBufferSize(codes, codesSize)]; int xCoordinatesBuffer[codesSize]; @@ -197,8 +194,7 @@ int UnigramDictionary::getSuggestions(ProximityInfo *proximityInfo, const int *x getWordWithDigraphSuggestionsRec(proximityInfo, xcoordinates, ycoordinates, codesBuffer, xCoordinatesBuffer, yCoordinatesBuffer, codesSize, bigramMap, bigramFilter, useFullEditDistance, codes, codesSize, 0, codesBuffer, &masterCorrection, - &queuePool, FRENCH_LIGATURES_DIGRAPHS, - sizeof(FRENCH_LIGATURES_DIGRAPHS) / sizeof(FRENCH_LIGATURES_DIGRAPHS[0])); + &queuePool, FRENCH_LIGATURES_DIGRAPHS, NELEMS(FRENCH_LIGATURES_DIGRAPHS)); } else { // Normal processing getWordSuggestions(proximityInfo, xcoordinates, ycoordinates, codes, codesSize, bigramMap, bigramFilter, useFullEditDistance, &masterCorrection, &queuePool); @@ -314,8 +310,6 @@ void UnigramDictionary::initSuggestions(ProximityInfo *proximityInfo, const int correction->initCorrection(proximityInfo, inputSize, maxDepth); } -static const char SPACE = ' '; - void UnigramDictionary::getOneWordSuggestions(ProximityInfo *proximityInfo, const int *xcoordinates, const int *ycoordinates, const int *codes, const std::map *bigramMap, const uint8_t *bigramFilter, @@ -570,7 +564,7 @@ int UnigramDictionary::getSubStringSuggestion( if (outputWordStartPos + nextWordLength >= MAX_WORD_LENGTH) { return FLAG_MULTIPLE_SUGGEST_SKIP; } - outputWord[tempOutputWordLength] = SPACE; + outputWord[tempOutputWordLength] = KEYCODE_SPACE; if (outputWordLength) { ++*outputWordLength; } diff --git a/native/jni/src/unigram_dictionary.h b/native/jni/src/unigram_dictionary.h index 57129bb07..244d78d8c 100644 --- a/native/jni/src/unigram_dictionary.h +++ b/native/jni/src/unigram_dictionary.h @@ -39,8 +39,8 @@ class UnigramDictionary { static const int FLAG_MULTIPLE_SUGGEST_ABORT = 0; static const int FLAG_MULTIPLE_SUGGEST_SKIP = 1; static const int FLAG_MULTIPLE_SUGGEST_CONTINUE = 2; - UnigramDictionary(const uint8_t *const streamStart, int typedLetterMultipler, - int fullWordMultiplier, int maxWordLength, int maxWords, const unsigned int flags); + UnigramDictionary(const uint8_t *const streamStart, int fullWordMultiplier, int maxWordLength, + int maxWords, const unsigned int flags); int getFrequency(const int32_t *const inWord, const int length) const; int getBigramPosition(int pos, unsigned short *word, int offset, int length) const; int getSuggestions(ProximityInfo *proximityInfo, const int *xcoordinates, @@ -115,7 +115,6 @@ class UnigramDictionary { const uint8_t *const DICT_ROOT; const int MAX_WORD_LENGTH; const int MAX_WORDS; - const int TYPED_LETTER_MULTIPLIER; const int FULL_WORD_MULTIPLIER; const int ROOT_POS; const unsigned int BYTES_IN_ONE_CHAR; -- cgit v1.2.3-83-g751a From 806eba452423e5e5971ef096dfae3fed180db665 Mon Sep 17 00:00:00 2001 From: Keisuke Kuroyanagi Date: Tue, 9 Oct 2012 19:57:08 +0900 Subject: Improve gesture input scoring method 1. Calculate probabilities for each points in advance. It enables to input not in the dictionary word. Change-Id: I8d84642045dc3b8ad49719d9b70dda14457995cd --- native/jni/src/defines.h | 4 + native/jni/src/geometry_utils.h | 19 ++ native/jni/src/proximity_info_state.cpp | 374 +++++++++++++++++++++++++++----- native/jni/src/proximity_info_state.h | 18 +- 4 files changed, 356 insertions(+), 59 deletions(-) (limited to 'native/jni/src') diff --git a/native/jni/src/defines.h b/native/jni/src/defines.h index 1bb031312..942068a49 100644 --- a/native/jni/src/defines.h +++ b/native/jni/src/defines.h @@ -219,6 +219,8 @@ static inline void prof_out(void) { #define DEBUG_CORRECTION false #define DEBUG_CORRECTION_FREQ false #define DEBUG_WORDS_PRIORITY_QUEUE false +#define DEBUG_SAMPLING_POINTS true +#define DEBUG_POINTS_PROBABILITY true #ifdef FLAG_FULL_DBG #define DEBUG_GEO_FULL true @@ -239,6 +241,8 @@ static inline void prof_out(void) { #define DEBUG_CORRECTION false #define DEBUG_CORRECTION_FREQ false #define DEBUG_WORDS_PRIORITY_QUEUE false +#define DEBUG_SAMPLING_POINTS false +#define DEBUG_POINTS_PROBABILITY false #define DEBUG_GEO_FULL false diff --git a/native/jni/src/geometry_utils.h b/native/jni/src/geometry_utils.h index 31359e19d..734fbefda 100644 --- a/native/jni/src/geometry_utils.h +++ b/native/jni/src/geometry_utils.h @@ -85,5 +85,24 @@ static inline float pointToLineSegSquaredDistanceFloat( } return getSquaredDistanceFloat(x, y, projectionX, projectionY); } + +// Normal distribution N(u, sigma^2). +struct NormalDistribution { + NormalDistribution(const float u, const float sigma) + : mU(u), mSigma(sigma), + mPreComputedNonExpPart(1.0f / sqrtf(2.0f * M_PI_F * sigma * sigma)), + mPreComputedExponentPart(-1.0f / (2.0f * sigma * sigma)) {} + + float getProbabilityDensity(const float x) { + const float shiftedX = x - mU; + return mPreComputedNonExpPart * expf(mPreComputedExponentPart * SQUARE_FLOAT(shiftedX)); + } +private: + DISALLOW_IMPLICIT_CONSTRUCTORS(NormalDistribution); + float mU; // mean value + float mSigma; // standard deviation + float mPreComputedNonExpPart; // = 1 / sqrt(2 * PI * sigma^2) + float mPreComputedExponentPart; // = -1 / (2 * sigma^2) +}; } // namespace latinime #endif // LATINIME_GEOMETRY_UTILS_H diff --git a/native/jni/src/proximity_info_state.cpp b/native/jni/src/proximity_info_state.cpp index 015174356..90e3671eb 100644 --- a/native/jni/src/proximity_info_state.cpp +++ b/native/jni/src/proximity_info_state.cpp @@ -15,6 +15,7 @@ */ #include // for memset() +#include // for debug prints #include #define LOG_TAG "LatinIME: proximity_info_state.cpp" @@ -105,6 +106,7 @@ void ProximityInfoState::initInputParams(const int pointerId, const float maxPoi mDistanceCache.clear(); mNearKeysVector.clear(); mRelativeSpeeds.clear(); + mCharProbabilities.clear(); } if (DEBUG_GEO_FULL) { AKLOGI("Init ProximityInfoState: reused points = %d, last input size = %d", @@ -161,34 +163,42 @@ void ProximityInfoState::initInputParams(const int pointerId, const float maxPoi } if (mInputSize > 0 && isGeometric) { - int sumDuration = mTimes.back() - mTimes.front(); - int sumLength = mLengthCache.back() - mLengthCache.front(); - float averageSpeed = static_cast(sumLength) / static_cast(sumDuration); + const int sumDuration = mTimes.back() - mTimes.front(); + const int sumLength = mLengthCache.back() - mLengthCache.front(); + const float averageSpeed = static_cast(sumLength) / static_cast(sumDuration); mRelativeSpeeds.resize(mInputSize); for (int i = lastSavedInputSize; i < mInputSize; ++i) { const int index = mInputIndice[i]; int length = 0; int duration = 0; - if (index == 0 && index < inputSize - 1) { - length = getDistanceInt(xCoordinates[index], yCoordinates[index], - xCoordinates[index + 1], yCoordinates[index + 1]); - duration = times[index + 1] - times[index]; - } else if (index == inputSize - 1 && index > 0) { - length = getDistanceInt(xCoordinates[index - 1], yCoordinates[index - 1], - xCoordinates[index], yCoordinates[index]); - duration = times[index] - times[index - 1]; - } else if (0 < index && index < inputSize - 1) { - length = getDistanceInt(xCoordinates[index - 1], yCoordinates[index - 1], - xCoordinates[index], yCoordinates[index]) - + getDistanceInt(xCoordinates[index], yCoordinates[index], - xCoordinates[index + 1], yCoordinates[index + 1]); - duration = times[index + 1] - times[index - 1]; + + // Calculate velocity by using distances and durations of + // NUM_POINTS_FOR_SPEED_CALCULATION points for both forward and backward. + static const int NUM_POINTS_FOR_SPEED_CALCULATION = 1; + for (int j = index; j < min(inputSize - 1, index + NUM_POINTS_FOR_SPEED_CALCULATION); + ++j) { + if (i < mInputSize - 1 && j >= mInputIndice[i + 1]) { + break; + } + length += getDistanceInt(xCoordinates[j], yCoordinates[j], + xCoordinates[j + 1], yCoordinates[j + 1]); + duration += times[j + 1] - times[j]; + } + for (int j = index - 1; j >= max(0, index - NUM_POINTS_FOR_SPEED_CALCULATION); --j) { + if (i > 0 && j < mInputIndice[i - 1]) { + break; + } + length += getDistanceInt(xCoordinates[j], yCoordinates[j], + xCoordinates[j + 1], yCoordinates[j + 1]); + duration += times[j + 1] - times[j]; + } + if (duration == 0 || sumDuration == 0) { + // Cannot calculate speed; thus, it gives an average value (1.0); + mRelativeSpeeds[i] = 1.0f; } else { - length = 0; - duration = 1; + const float speed = static_cast(length) / static_cast(duration); + mRelativeSpeeds[i] = speed / averageSpeed; } - const float speed = static_cast(length) / static_cast(duration); - mRelativeSpeeds[i] = speed / averageSpeed; } } @@ -215,7 +225,7 @@ void ProximityInfoState::initInputParams(const int pointerId, const float maxPoi static const float READ_FORWORD_LENGTH_SCALE = 0.95f; const int readForwordLength = static_cast( hypotf(mProximityInfo->getKeyboardWidth(), mProximityInfo->getKeyboardHeight()) - * READ_FORWORD_LENGTH_SCALE); + * READ_FORWORD_LENGTH_SCALE); for (int i = 0; i < mInputSize; ++i) { if (DEBUG_GEO_FULL) { AKLOGI("Sampled(%d): x = %d, y = %d, time = %d", i, mInputXs[i], mInputYs[i], @@ -230,6 +240,27 @@ void ProximityInfoState::initInputParams(const int pointerId, const float maxPoi } } + if (DEBUG_SAMPLING_POINTS) { + std::stringstream originalX, originalY, sampledX, sampledY; + for (int i = 0; i < inputSize; ++i) { + originalX << xCoordinates[i]; + originalY << yCoordinates[i]; + if (i != inputSize - 1) { + originalX << ";"; + originalY << ";"; + } + } + for (int i = 0; i < mInputSize; ++i) { + sampledX << mInputXs[i]; + sampledY << mInputYs[i]; + if (i != mInputSize - 1) { + sampledX << ";"; + sampledY << ";"; + } + } + AKLOGI("\n%s, %s,\n%s, %s,\n", originalX.str().c_str(), originalY.str().c_str(), + sampledX.str().c_str(), sampledY.str().c_str()); + } // end /////////////////////// @@ -276,6 +307,10 @@ void ProximityInfoState::initInputParams(const int pointerId, const float maxPoi if (DEBUG_GEO_FULL) { AKLOGI("ProximityState init finished: %d points out of %d", mInputSize, inputSize); } + if (isGeometric && mInputSize > 0) { + // updates probabilities of skipping or mapping each key for all points. + updateAlignPointProbabilities(); + } } bool ProximityInfoState::checkAndReturnIsContinuationPossible(const int inputSize, @@ -294,7 +329,7 @@ bool ProximityInfoState::checkAndReturnIsContinuationPossible(const int inputSiz // the given point and the nearest key position. float ProximityInfoState::updateNearKeysDistances(const int x, const int y, NearKeysDistanceMap *const currentNearKeysDistances) { - static const float NEAR_KEY_THRESHOLD = 4.0f; + static const float NEAR_KEY_THRESHOLD = 1.7f; currentNearKeysDistances->clear(); const int keyCount = mProximityInfo->getKeyCount(); @@ -315,7 +350,7 @@ float ProximityInfoState::updateNearKeysDistances(const int x, const int y, bool ProximityInfoState::isPrevLocalMin(const NearKeysDistanceMap *const currentNearKeysDistances, const NearKeysDistanceMap *const prevNearKeysDistances, const NearKeysDistanceMap *const prevPrevNearKeysDistances) const { - static const float MARGIN = 0.01f; + static const float MARGIN = 0.03f; for (NearKeysDistanceMap::const_iterator it = prevNearKeysDistances->begin(); it != prevNearKeysDistances->end(); ++it) { @@ -336,18 +371,20 @@ float ProximityInfoState::getPointScore( const NearKeysDistanceMap *const prevNearKeysDistances, const NearKeysDistanceMap *const prevPrevNearKeysDistances) const { static const int DISTANCE_BASE_SCALE = 100; - static const int SAVE_DISTANCE_SCALE = 200; - static const int SKIP_DISTANCE_SCALE = 25; - static const int CHECK_LOCALMIN_DISTANCE_THRESHOLD_SCALE = 40; - static const int STRAIGHT_SKIP_DISTANCE_THRESHOLD_SCALE = 50; - static const int CORNER_CHECK_DISTANCE_THRESHOLD_SCALE = 27; + static const int SAVE_DISTANCE_SCALE = 500; + static const int SKIP_DISTANCE_SCALE = 10; + static const float NEAR_KEY_THRESHOLD = 1.0f; + static const int CHECK_LOCALMIN_DISTANCE_THRESHOLD_SCALE = 100; + static const int STRAIGHT_SKIP_DISTANCE_THRESHOLD_SCALE = 200; + static const int CORNER_CHECK_DISTANCE_THRESHOLD_SCALE = 20; static const float SAVE_DISTANCE_SCORE = 2.0f; static const float SKIP_DISTANCE_SCORE = -1.0f; - static const float CHECK_LOCALMIN_DISTANCE_SCORE = -1.0f; + static const float NOT_LOCALMIN_DISTANCE_SCORE = -1.0f; + static const float LOCALMIN_DISTANCE_AND_NEAR_TO_KEY_SCORE = 2.0f; static const float STRAIGHT_ANGLE_THRESHOLD = M_PI_F / 36.0f; static const float STRAIGHT_SKIP_NEAREST_DISTANCE_THRESHOLD = 0.5f; static const float STRAIGHT_SKIP_SCORE = -1.0f; - static const float CORNER_ANGLE_THRESHOLD = M_PI_F / 2.0f; + static const float CORNER_ANGLE_THRESHOLD = M_PI_F / 6.0f; static const float CORNER_SCORE = 1.0f; const std::size_t size = mInputXs.size(); @@ -373,7 +410,10 @@ float ProximityInfoState::getPointScore( if (distPrev < baseSampleRate * CHECK_LOCALMIN_DISTANCE_THRESHOLD_SCALE) { if (!isPrevLocalMin(currentNearKeysDistances, prevNearKeysDistances, prevPrevNearKeysDistances)) { - score += CHECK_LOCALMIN_DISTANCE_SCORE; + score += NOT_LOCALMIN_DISTANCE_SCORE; + } else if (nearest < NEAR_KEY_THRESHOLD) { + // Promote points nearby keys + score += LOCALMIN_DISTANCE_AND_NEAR_TO_KEY_SCORE; } } // Angle @@ -402,7 +442,8 @@ bool ProximityInfoState::pushTouchPoint(const int inputIndex, const int nodeChar NearKeysDistanceMap *const currentNearKeysDistances, const NearKeysDistanceMap *const prevNearKeysDistances, const NearKeysDistanceMap *const prevPrevNearKeysDistances) { - static const float LAST_POINT_SKIP_DISTANCE_SCALE = 0.25f; + static const int LAST_POINT_SKIP_DISTANCE_SCALE = 4; + static const int LAST_AND_NOT_NEAREST_POINT_SKIP_DISTANCE_SCALE = 2; size_t size = mInputXs.size(); bool popped = false; @@ -419,33 +460,38 @@ bool ProximityInfoState::pushTouchPoint(const int inputIndex, const int nodeChar popped = false; } // Check if the last point should be skipped. - if (isLastPoint) { - if (size > 0 && getDistanceFloat(x, y, mInputXs.back(), mInputYs.back()) - < mProximityInfo->getMostCommonKeyWidth() * LAST_POINT_SKIP_DISTANCE_SCALE) { + if (isLastPoint && size > 0) { + const int lastPointsDistance = getDistanceInt(x, y, mInputXs.back(), mInputYs.back()); + if (lastPointsDistance * LAST_POINT_SKIP_DISTANCE_SCALE + < mProximityInfo->getMostCommonKeyWidth()) { + // This point is not used because it's too close to the previous point. if (DEBUG_GEO_FULL) { - AKLOGI("p0: size = %zd, x = %d, y = %d, lx = %d, ly = %d, dist = %f, " - "width = %f", size, x, y, mInputXs.back(), mInputYs.back(), - getDistanceFloat(x, y, mInputXs.back(), mInputYs.back()), + AKLOGI("p0: size = %zd, x = %d, y = %d, lx = %d, ly = %d, dist = %d, " + "width = %d", size, x, y, mInputXs.back(), mInputYs.back(), + getDistanceInt(x, y, mInputXs.back(), mInputYs.back()), mProximityInfo->getMostCommonKeyWidth() - * LAST_POINT_SKIP_DISTANCE_SCALE); + / LAST_POINT_SKIP_DISTANCE_SCALE); } return popped; - } else if (size > 1) { - int minChar = 0; - float minDist = mMaxPointToKeyLength; + } else if (lastPointsDistance * LAST_AND_NOT_NEAREST_POINT_SKIP_DISTANCE_SCALE + < mProximityInfo->getMostCommonKeyWidth()) { + int nearestChar = 0; + float nearestCharDistance = mMaxPointToKeyLength; for (NearKeysDistanceMap::const_iterator it = currentNearKeysDistances->begin(); it != currentNearKeysDistances->end(); ++it) { - if (minDist > it->second) { - minChar = it->first; - minDist = it->second; + if (nearestCharDistance > it->second) { + nearestChar = it->first; + nearestCharDistance = it->second; } } NearKeysDistanceMap::const_iterator itPP = - prevNearKeysDistances->find(minChar); - if (itPP != prevNearKeysDistances->end() && minDist > itPP->second) { + prevNearKeysDistances->find(nearestChar); + if (itPP != prevNearKeysDistances->end() && nearestCharDistance > itPP->second) { + // The nearest key of the penultimate point is same as the nearest key of the + // last point. So, we don't need to use the last point. if (DEBUG_GEO_FULL) { AKLOGI("p1: char = %c, minDist = %f, prevNear key minDist = %f", - minChar, itPP->second, minDist); + nearestChar, itPP->second, nearestCharDistance); } return popped; } @@ -503,18 +549,21 @@ int ProximityInfoState::getDuration(const int index) const { return 0; } -float ProximityInfoState::getPointToKeyLength(const int inputIndex, const int codePoint, - const float scale) const { +float ProximityInfoState::getPointToKeyLength(const int inputIndex, const int codePoint) const { + if (isSkippableChar(codePoint)) { + return 0.0f; + } const int keyId = mProximityInfo->getKeyIndexOf(codePoint); + return getPointToKeyByIdLength(inputIndex, keyId); +} + +float ProximityInfoState::getPointToKeyByIdLength(const int inputIndex, const int keyId) const { if (keyId != NOT_AN_INDEX) { const int index = inputIndex * mProximityInfo->getKeyCount() + keyId; - return min(mDistanceCache[index] * scale, mMaxPointToKeyLength); - } - if (isSkippableChar(codePoint)) { - return 0.0f; + return min(mDistanceCache[index], mMaxPointToKeyLength); } // If the char is not a key on the keyboard then return the max length. - return MAX_POINT_TO_KEY_LENGTH; + return static_cast(MAX_POINT_TO_KEY_LENGTH); } int ProximityInfoState::getSpaceY() const { @@ -565,4 +614,217 @@ void ProximityInfoState::popInputData() { mInputIndice.pop_back(); } +float ProximityInfoState::getPointAngle(const int index) const { + if (index <= 0 || index >= mInputSize - 1) { + return 0.0f; + } + const int x = mInputXs[index]; + const int y = mInputYs[index]; + const int nextX = mInputXs[index + 1]; + const int nextY = mInputYs[index + 1]; + const int previousX = mInputXs[index - 1]; + const int previousY = mInputYs[index - 1]; + const float previousDirection = getAngle(previousX, previousY, x, y); + const float nextDirection = getAngle(x, y, nextX, nextY); + const float directionDiff = getAngleDiff(previousDirection, nextDirection); + return directionDiff; +} + +float ProximityInfoState::getPointsAngle( + const int index0, const int index1, const int index2) const { + if (index0 < 0 || index0 > mInputSize - 1) { + return 0.0f; + } + if (index1 < 0 || index1 > mInputSize - 1) { + return 0.0f; + } + if (index2 < 0 || index2 > mInputSize - 1) { + return 0.0f; + } + const int x0 = mInputXs[index0]; + const int y0 = mInputYs[index0]; + const int x1 = mInputXs[index1]; + const int y1 = mInputYs[index1]; + const int x2 = mInputXs[index2]; + const int y2 = mInputYs[index2]; + const float previousDirection = getAngle(x0, y0, x1, y1); + const float nextDirection = getAngle(x1, y1, x2, y2); + const float directionDiff = getAngleDiff(previousDirection, nextDirection); + return directionDiff; +} + +// Updates probabilities of aligning to some keys and skipping. +// Word suggestion should be based on this probabilities. +void ProximityInfoState::updateAlignPointProbabilities() { + static const float MIN_PROBABILITY = 0.00001f; + static const float SKIP_FIRST_POINT_PROBABILITY = 0.01f; + static const float SKIP_LAST_POINT_PROBABILITY = 0.1f; + static const float ANGLE_RATE = 0.8f; + static const float DEEP_CORNER_ANGLE_THRESHOLD = M_PI_F * 0.5f; + static const float SKIP_DEEP_CORNER_PROBABILITY = 0.3f; + static const float CORNER_ANGLE_THRESHOLD = M_PI_F * 35.0f / 180.0f; + static const float STRAIGHT_ANGLE_THRESHOLD = M_PI_F * 15.0f / 180.0f; + static const float SKIP_CORNER_PROBABILITY = 0.5f; + static const float SLOW_STRAIGHT_WEIGHT = 0.8f; + static const float CENTER_VALUE_OF_NORMALIZED_DISTRIBUTION = 0.0f; + + mCharProbabilities.resize(mInputSize); + // Calculates probabilities of using a point as a correlated point with the character + // for each point. + for (int i = 0; i < mInputSize; ++i) { + // First, calculates skip probability. Starts form 100%. + // Note that all values that are multiplied to this probability should be in [0.0, 1.0]; + float skipProbability = 1.0f; + const float speed = getRelativeSpeed(i); + + // Adjusts skip probability by a rate depending on speed. + skipProbability *= min(1.0f, speed); + if (i == 0) { + skipProbability *= SKIP_FIRST_POINT_PROBABILITY; + } else if (i == mInputSize - 1) { + skipProbability *= SKIP_LAST_POINT_PROBABILITY; + } else { + const float currentAngle = getPointAngle(i); + + // Adjusts skip probability by a rate depending on angle. + // ANGLE_RATE of skipProbability is adjusted by current angle. + skipProbability *= max((M_PI_F - currentAngle) / M_PI_F, 0.0f) * ANGLE_RATE + + (1.0f - ANGLE_RATE); + if (currentAngle > DEEP_CORNER_ANGLE_THRESHOLD) { + skipProbability *= SKIP_DEEP_CORNER_PROBABILITY; + } + const float prevAngle = getPointsAngle(i, i - 1, i - 2); + if (prevAngle < STRAIGHT_ANGLE_THRESHOLD && currentAngle > CORNER_ANGLE_THRESHOLD) { + skipProbability *= SKIP_CORNER_PROBABILITY; + } + if (currentAngle < STRAIGHT_ANGLE_THRESHOLD) { + // Adjusts skip probability by speed. + skipProbability *= min(1.0f, speed * SLOW_STRAIGHT_WEIGHT); + } + } + + // probabilities must be in [0.0, 1.0]; + ASSERT(skipProbability >= 0.0f); + ASSERT(skipProbability <= 1.0f); + + mCharProbabilities[i][NOT_AN_INDEX] = skipProbability; + // Second, calculates key probabilities by dividing the rest probability + // (1.0f - skipProbability). + const float inputCharProbability = 1.0f - skipProbability; + // Summing up probability densities of all near keys. + float sumOfProbabilityDensityOfNearKeys = 0.0f; + const float sigma = speed; + NormalDistribution distribution(CENTER_VALUE_OF_NORMALIZED_DISTRIBUTION, sigma); + for (int j = 0; j < mProximityInfo->getKeyCount(); ++j) { + if (mNearKeysVector[i].test(j)) { + const float distance = sqrtf(getPointToKeyByIdLength(i, j)); + sumOfProbabilityDensityOfNearKeys += distribution.getProbabilityDensity(distance); + } + } + for (int j = 0; j < mProximityInfo->getKeyCount(); ++j) { + if (mNearKeysVector[i].test(j)) { + const float distance = sqrtf(getPointToKeyByIdLength(i, j)); + const float probabilityDessity = distribution.getProbabilityDensity(distance); + // inputCharProbability divided to the probability for each near key. + const float probability = inputCharProbability * probabilityDessity + / sumOfProbabilityDensityOfNearKeys; + if (probability > MIN_PROBABILITY) { + mCharProbabilities[i][j] = probability; + } + } + } + } + + // Decrease key probabilities of points which don't have the highest probability of that key + // among nearby points. Probabilities of the first point and the last point are not suppressed. + for (int i = 1; i < mInputSize - 1; ++i) { + // forward + for (int j = i + 1; j < mInputSize; ++j) { + if (suppressCharProbabilities(i, j)) { + break; + } + } + // backward + for (int j = i - 1; j >= 0; --j) { + if (suppressCharProbabilities(i, j)) { + break; + } + } + } + + if (DEBUG_POINTS_PROBABILITY) { + for (int i = 0; i < mInputSize; ++i) { + std::stringstream sstream; + sstream << i << ", "; + for (hash_map_compat::iterator it = mCharProbabilities[i].begin(); + it != mCharProbabilities[i].end(); ++it) { + sstream << it->first + << "(" + << static_cast(mProximityInfo->getCodePointOf(it->first)) + << "):" + << it->second + << ", "; + } + AKLOGI("%s", sstream.str().c_str()); + } + } +} + +// Decreases char probabilities of index0 by checking probabilities of a near point (index1). +bool ProximityInfoState::suppressCharProbabilities(const int index0, const int index1) { + ASSERT(0 <= index0 && index0 < mInputSize); + ASSERT(0 <= index1 && index1 < mInputSize); + static const float SUPPRESSION_LENGTH_WEIGHT = 1.5f; + const float keyWidthFloat = static_cast(mProximityInfo->getMostCommonKeyWidth()); + const float diff = fabsf(static_cast(mLengthCache[index0] - mLengthCache[index1])); + if (diff > keyWidthFloat * SUPPRESSION_LENGTH_WEIGHT) { + return false; + } + // Summing up decreased amount of probabilities from 0%. + float sumOfAdjustedProbabilities = 0.0f; + const float suppressionRate = diff / keyWidthFloat / SUPPRESSION_LENGTH_WEIGHT; + for (hash_map_compat::iterator it = mCharProbabilities[index0].begin(); + it != mCharProbabilities[index0].end(); ++it) { + hash_map_compat::const_iterator it2 = + mCharProbabilities[index1].find(it->first); + if (it2 != mCharProbabilities[index1].end() && it->second < it2->second) { + const float newProbability = it->second * suppressionRate; + sumOfAdjustedProbabilities += it->second - newProbability; + it->second = newProbability; + } + } + // All decreased amount of probabilities are added to the probability of skipping. + mCharProbabilities[index0][NOT_AN_INDEX] += sumOfAdjustedProbabilities; + return true; +} + +// Get a word that is detected by tracing highest probability sequence into charBuf and returns +// probability of generating the word. +float ProximityInfoState::getHighestProbabilitySequence(uint16_t *const charBuf) const { + int buf[mInputSize]; + // Maximum probabilities of each point are multiplied to 100%. + float probability = 1.0f; + // TODO: Current implementation is greedy algorithm. DP would be efficient for many cases. + for (int i = 0; i < mInputSize; ++i) { + float maxProbability = 0.0f; + for (hash_map_compat::const_iterator it = mCharProbabilities[i].begin(); + it != mCharProbabilities[i].end(); ++it) { + if (it->second > maxProbability) { + maxProbability = it->second; + buf[i] = it->first; + } + } + probability *= maxProbability; + } + int index = 0; + for (int i = 0; i < mInputSize && index < MAX_WORD_LENGTH_INTERNAL - 1; ++i) { + if (buf[i] != NOT_AN_INDEX) { + charBuf[index] = mProximityInfo->getCodePointOf(buf[i]); + index++; + } + } + charBuf[index] = '\0'; + return probability; +} + } // namespace latinime diff --git a/native/jni/src/proximity_info_state.h b/native/jni/src/proximity_info_state.h index c1ec76c38..7286e5ed5 100644 --- a/native/jni/src/proximity_info_state.h +++ b/native/jni/src/proximity_info_state.h @@ -55,8 +55,8 @@ class ProximityInfoState { mHasTouchPositionCorrectionData(false), mMostCommonKeyWidthSquare(0), mLocaleStr(), mKeyCount(0), mCellHeight(0), mCellWidth(0), mGridHeight(0), mGridWidth(0), mIsContinuationPossible(false), mInputXs(), mInputYs(), mTimes(), mInputIndice(), - mDistanceCache(), mLengthCache(), mRelativeSpeeds(), mNearKeysVector(), - mTouchPositionCorrectionEnabled(false), mInputSize(0) { + mDistanceCache(), mLengthCache(), mRelativeSpeeds(), mCharProbabilities(), + mNearKeysVector(), mTouchPositionCorrectionEnabled(false), mInputSize(0) { memset(mInputCodes, 0, sizeof(mInputCodes)); memset(mNormalizedSquaredDistances, 0, sizeof(mNormalizedSquaredDistances)); memset(mPrimaryInputWord, 0, sizeof(mPrimaryInputWord)); @@ -213,7 +213,9 @@ class ProximityInfoState { return mIsContinuationPossible; } - float getPointToKeyLength(const int inputIndex, const int charCode, const float scale) const; + float getPointToKeyLength(const int inputIndex, const int charCode) const; + + float getPointToKeyByIdLength(const int inputIndex, const int keyId) const; int getSpaceY() const; @@ -223,6 +225,12 @@ class ProximityInfoState { float getRelativeSpeed(const int index) const { return mRelativeSpeeds[index]; } + + float getPointAngle(const int index) const; + // Returns angle of three points. x, y, and z are indices. + float getPointsAngle(const int index0, const int index1, const int index2) const; + + float getHighestProbabilitySequence(uint16_t *const charBuf) const; private: DISALLOW_COPY_AND_ASSIGN(ProximityInfoState); typedef hash_map_compat NearKeysDistanceMap; @@ -265,6 +273,8 @@ class ProximityInfoState { bool checkAndReturnIsContinuationPossible(const int inputSize, const int *const xCoordinates, const int *const yCoordinates, const int *const times); void popInputData(); + void updateAlignPointProbabilities(); + bool suppressCharProbabilities(const int index1, const int index2); // const const ProximityInfo *mProximityInfo; @@ -286,6 +296,8 @@ class ProximityInfoState { std::vector mDistanceCache; std::vector mLengthCache; std::vector mRelativeSpeeds; + // probabilities of skipping or mapping to a key for each point. + std::vector > mCharProbabilities; std::vector mNearKeysVector; bool mTouchPositionCorrectionEnabled; int32_t mInputCodes[MAX_PROXIMITY_CHARS_SIZE_INTERNAL * MAX_WORD_LENGTH_INTERNAL]; -- cgit v1.2.3-83-g751a From 516f9d6ea40cbd74e4e166fb5e8ec568bab45bf1 Mon Sep 17 00:00:00 2001 From: Jean Chalard Date: Tue, 9 Oct 2012 20:24:13 +0900 Subject: Fix a bug in multiple shortcut handling code. Bug: 7301525 Change-Id: Ib38f5ab4b7e4f7996bccbc6830d46f52fd71c6f9 --- native/jni/src/terminal_attributes.h | 1 - 1 file changed, 1 deletion(-) (limited to 'native/jni/src') diff --git a/native/jni/src/terminal_attributes.h b/native/jni/src/terminal_attributes.h index 53ae385ea..e72e7e3be 100644 --- a/native/jni/src/terminal_attributes.h +++ b/native/jni/src/terminal_attributes.h @@ -57,7 +57,6 @@ class TerminalAttributes { outWord[i] = (uint16_t)codePoint; } *outFreq = BinaryFormat::getAttributeFrequencyFromFlags(shortcutFlags); - mPos += BinaryFormat::CHARACTER_ARRAY_TERMINATOR_SIZE; return i; } }; -- cgit v1.2.3-83-g751a From ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115 Mon Sep 17 00:00:00 2001 From: Keisuke Kuroyanagi Date: Thu, 11 Oct 2012 13:08:06 +0900 Subject: Improve gesture input scoring method 2. Align next key to path bases its scoring method on probabilities. Change-Id: I5247c965b92c0052bfdab8a9b1027bc86eb33218 --- native/jni/src/geometry_utils.h | 4 +- native/jni/src/proximity_info.cpp | 7 +- native/jni/src/proximity_info.h | 2 +- native/jni/src/proximity_info_state.cpp | 560 +++++++++++++++++++++----------- native/jni/src/proximity_info_state.h | 28 +- 5 files changed, 392 insertions(+), 209 deletions(-) (limited to 'native/jni/src') diff --git a/native/jni/src/geometry_utils.h b/native/jni/src/geometry_utils.h index 734fbefda..ee7c98562 100644 --- a/native/jni/src/geometry_utils.h +++ b/native/jni/src/geometry_utils.h @@ -90,8 +90,8 @@ static inline float pointToLineSegSquaredDistanceFloat( struct NormalDistribution { NormalDistribution(const float u, const float sigma) : mU(u), mSigma(sigma), - mPreComputedNonExpPart(1.0f / sqrtf(2.0f * M_PI_F * sigma * sigma)), - mPreComputedExponentPart(-1.0f / (2.0f * sigma * sigma)) {} + mPreComputedNonExpPart(1.0f / sqrtf(2.0f * M_PI_F * SQUARE_FLOAT(sigma))), + mPreComputedExponentPart(-1.0f / (2.0f * SQUARE_FLOAT(sigma))) {} float getProbabilityDensity(const float x) { const float shiftedX = x - mU; diff --git a/native/jni/src/proximity_info.cpp b/native/jni/src/proximity_info.cpp index fde93b5a9..e2aa15674 100644 --- a/native/jni/src/proximity_info.cpp +++ b/native/jni/src/proximity_info.cpp @@ -239,6 +239,9 @@ int ProximityInfo::getKeyIndexOf(const int c) const { // We do not have the coordinate data return NOT_AN_INDEX; } + if (c == NOT_A_CODE_POINT) { + return NOT_AN_INDEX; + } const int lowerCode = static_cast(toLowerCase(c)); hash_map_compat::const_iterator mapPos = mCodeToKeyMap.find(lowerCode); if (mapPos != mCodeToKeyMap.end()) { @@ -296,9 +299,7 @@ int ProximityInfo::getKeyCenterYOfKeyIdG(int keyId) const { return 0; } -int ProximityInfo::getKeyKeyDistanceG(int key0, int key1) const { - const int keyId0 = getKeyIndexOf(key0); - const int keyId1 = getKeyIndexOf(key1); +int ProximityInfo::getKeyKeyDistanceG(const int keyId0, const int keyId1) const { if (keyId0 >= 0 && keyId1 >= 0) { return mKeyKeyDistancesG[keyId0][keyId1]; } diff --git a/native/jni/src/proximity_info.h b/native/jni/src/proximity_info.h index 70942aa19..7ee15d578 100644 --- a/native/jni/src/proximity_info.h +++ b/native/jni/src/proximity_info.h @@ -109,7 +109,7 @@ class ProximityInfo { int getKeyCenterYOfCodePointG(int charCode) const; int getKeyCenterXOfKeyIdG(int keyId) const; int getKeyCenterYOfKeyIdG(int keyId) const; - int getKeyKeyDistanceG(int key0, int key1) const; + int getKeyKeyDistanceG(int keyId0, int keyId1) const; private: DISALLOW_IMPLICIT_CONSTRUCTORS(ProximityInfo); diff --git a/native/jni/src/proximity_info_state.cpp b/native/jni/src/proximity_info_state.cpp index 90e3671eb..0f7e4d65f 100644 --- a/native/jni/src/proximity_info_state.cpp +++ b/native/jni/src/proximity_info_state.cpp @@ -105,6 +105,7 @@ void ProximityInfoState::initInputParams(const int pointerId, const float maxPoi mLengthCache.clear(); mDistanceCache.clear(); mNearKeysVector.clear(); + mSearchKeysVector.clear(); mRelativeSpeeds.clear(); mCharProbabilities.clear(); } @@ -132,6 +133,10 @@ void ProximityInfoState::initInputParams(const int pointerId, const float maxPoi NearKeysDistanceMap *currentNearKeysDistances = &nearKeysDistances[0]; NearKeysDistanceMap *prevNearKeysDistances = &nearKeysDistances[1]; NearKeysDistanceMap *prevPrevNearKeysDistances = &nearKeysDistances[2]; + // "sumAngle" is accumulated by each angle of input points. And when "sumAngle" exceeds + // the threshold we save that point, reset sumAngle. This aims to keep the figure of + // the curve. + float sumAngle = 0.0f; for (int i = pushTouchPointStartIndex; i <= lastInputIndex; ++i) { // Assuming pointerId == 0 if pointerIds is null. @@ -144,9 +149,18 @@ void ProximityInfoState::initInputParams(const int pointerId, const float maxPoi const int x = proximityOnly ? NOT_A_COORDINATE : xCoordinates[i]; const int y = proximityOnly ? NOT_A_COORDINATE : yCoordinates[i]; const int time = times ? times[i] : -1; + + if (i > 1) { + const float prevAngle = getAngle(xCoordinates[i - 2], yCoordinates[i - 2], + xCoordinates[i - 1], yCoordinates[i - 1]); + const float currentAngle = + getAngle(xCoordinates[i - 1], yCoordinates[i - 1], x, y); + sumAngle += getAngleDiff(prevAngle, currentAngle); + } + if (pushTouchPoint(i, c, x, y, time, isGeometric /* do sampling */, - i == lastInputIndex, currentNearKeysDistances, prevNearKeysDistances, - prevPrevNearKeysDistances)) { + i == lastInputIndex, sumAngle, currentNearKeysDistances, + prevNearKeysDistances, prevPrevNearKeysDistances)) { // Previous point information was popped. NearKeysDistanceMap *tmp = prevNearKeysDistances; prevNearKeysDistances = currentNearKeysDistances; @@ -156,6 +170,7 @@ void ProximityInfoState::initInputParams(const int pointerId, const float maxPoi prevPrevNearKeysDistances = prevNearKeysDistances; prevNearKeysDistances = currentNearKeysDistances; currentNearKeysDistances = tmp; + sumAngle = 0.0f; } } } @@ -163,6 +178,7 @@ void ProximityInfoState::initInputParams(const int pointerId, const float maxPoi } if (mInputSize > 0 && isGeometric) { + // Relative speed calculation. const int sumDuration = mTimes.back() - mTimes.front(); const int sumLength = mLengthCache.back() - mLengthCache.front(); const float averageSpeed = static_cast(sumLength) / static_cast(sumDuration); @@ -174,7 +190,7 @@ void ProximityInfoState::initInputParams(const int pointerId, const float maxPoi // Calculate velocity by using distances and durations of // NUM_POINTS_FOR_SPEED_CALCULATION points for both forward and backward. - static const int NUM_POINTS_FOR_SPEED_CALCULATION = 1; + static const int NUM_POINTS_FOR_SPEED_CALCULATION = 2; for (int j = index; j < min(inputSize - 1, index + NUM_POINTS_FOR_SPEED_CALCULATION); ++j) { if (i < mInputSize - 1 && j >= mInputIndice[i + 1]) { @@ -202,12 +218,21 @@ void ProximityInfoState::initInputParams(const int pointerId, const float maxPoi } } + if (DEBUG_GEO_FULL) { + for (int i = 0; i < mInputSize; ++i) { + AKLOGI("Sampled(%d): x = %d, y = %d, time = %d", i, mInputXs[i], mInputYs[i], + mTimes[i]); + } + } + if (mInputSize > 0) { const int keyCount = mProximityInfo->getKeyCount(); mNearKeysVector.resize(mInputSize); + mSearchKeysVector.resize(mInputSize); mDistanceCache.resize(mInputSize * keyCount); for (int i = lastSavedInputSize; i < mInputSize; ++i) { mNearKeysVector[i].reset(); + mSearchKeysVector[i].reset(); static const float NEAR_KEY_NORMALIZED_SQUARED_THRESHOLD = 4.0f; for (int k = 0; k < keyCount; ++k) { const int index = i * keyCount + k; @@ -217,25 +242,28 @@ void ProximityInfoState::initInputParams(const int pointerId, const float maxPoi mProximityInfo->getNormalizedSquaredDistanceFromCenterFloatG(k, x, y); mDistanceCache[index] = normalizedSquaredDistance; if (normalizedSquaredDistance < NEAR_KEY_NORMALIZED_SQUARED_THRESHOLD) { - mNearKeysVector[i].set(k, 1); + mNearKeysVector[i][k] = true; } } } - - static const float READ_FORWORD_LENGTH_SCALE = 0.95f; - const int readForwordLength = static_cast( - hypotf(mProximityInfo->getKeyboardWidth(), mProximityInfo->getKeyboardHeight()) - * READ_FORWORD_LENGTH_SCALE); - for (int i = 0; i < mInputSize; ++i) { - if (DEBUG_GEO_FULL) { - AKLOGI("Sampled(%d): x = %d, y = %d, time = %d", i, mInputXs[i], mInputYs[i], - mTimes[i]); - } - for (int j = max(i + 1, lastSavedInputSize); j < mInputSize; ++j) { - if (mLengthCache[j] - mLengthCache[i] >= readForwordLength) { - break; + if (isGeometric) { + // updates probabilities of skipping or mapping each key for all points. + updateAlignPointProbabilities(lastSavedInputSize); + + static const float READ_FORWORD_LENGTH_SCALE = 0.95f; + const int readForwordLength = static_cast( + hypotf(mProximityInfo->getKeyboardWidth(), mProximityInfo->getKeyboardHeight()) + * READ_FORWORD_LENGTH_SCALE); + for (int i = 0; i < mInputSize; ++i) { + if (i >= lastSavedInputSize) { + mSearchKeysVector[i].reset(); + } + for (int j = max(i, lastSavedInputSize); j < mInputSize; ++j) { + if (mLengthCache[j] - mLengthCache[i] >= readForwordLength) { + break; + } + mSearchKeysVector[i] |= mNearKeysVector[j]; } - mNearKeysVector[i] |= mNearKeysVector[j]; } } } @@ -307,10 +335,6 @@ void ProximityInfoState::initInputParams(const int pointerId, const float maxPoi if (DEBUG_GEO_FULL) { AKLOGI("ProximityState init finished: %d points out of %d", mInputSize, inputSize); } - if (isGeometric && mInputSize > 0) { - // updates probabilities of skipping or mapping each key for all points. - updateAlignPointProbabilities(); - } } bool ProximityInfoState::checkAndReturnIsContinuationPossible(const int inputSize, @@ -329,7 +353,7 @@ bool ProximityInfoState::checkAndReturnIsContinuationPossible(const int inputSiz // the given point and the nearest key position. float ProximityInfoState::updateNearKeysDistances(const int x, const int y, NearKeysDistanceMap *const currentNearKeysDistances) { - static const float NEAR_KEY_THRESHOLD = 1.7f; + static const float NEAR_KEY_THRESHOLD = 2.0f; currentNearKeysDistances->clear(); const int keyCount = mProximityInfo->getKeyCount(); @@ -350,7 +374,7 @@ float ProximityInfoState::updateNearKeysDistances(const int x, const int y, bool ProximityInfoState::isPrevLocalMin(const NearKeysDistanceMap *const currentNearKeysDistances, const NearKeysDistanceMap *const prevNearKeysDistances, const NearKeysDistanceMap *const prevPrevNearKeysDistances) const { - static const float MARGIN = 0.03f; + static const float MARGIN = 0.01f; for (NearKeysDistanceMap::const_iterator it = prevNearKeysDistances->begin(); it != prevNearKeysDistances->end(); ++it) { @@ -367,69 +391,49 @@ bool ProximityInfoState::isPrevLocalMin(const NearKeysDistanceMap *const current // Calculating a point score that indicates usefulness of the point. float ProximityInfoState::getPointScore( const int x, const int y, const int time, const bool lastPoint, const float nearest, - const NearKeysDistanceMap *const currentNearKeysDistances, + const float sumAngle, const NearKeysDistanceMap *const currentNearKeysDistances, const NearKeysDistanceMap *const prevNearKeysDistances, const NearKeysDistanceMap *const prevPrevNearKeysDistances) const { static const int DISTANCE_BASE_SCALE = 100; - static const int SAVE_DISTANCE_SCALE = 500; - static const int SKIP_DISTANCE_SCALE = 10; - static const float NEAR_KEY_THRESHOLD = 1.0f; - static const int CHECK_LOCALMIN_DISTANCE_THRESHOLD_SCALE = 100; - static const int STRAIGHT_SKIP_DISTANCE_THRESHOLD_SCALE = 200; - static const int CORNER_CHECK_DISTANCE_THRESHOLD_SCALE = 20; - static const float SAVE_DISTANCE_SCORE = 2.0f; - static const float SKIP_DISTANCE_SCORE = -1.0f; + static const float NEAR_KEY_THRESHOLD = 0.6f; + static const int CORNER_CHECK_DISTANCE_THRESHOLD_SCALE = 25; static const float NOT_LOCALMIN_DISTANCE_SCORE = -1.0f; - static const float LOCALMIN_DISTANCE_AND_NEAR_TO_KEY_SCORE = 2.0f; - static const float STRAIGHT_ANGLE_THRESHOLD = M_PI_F / 36.0f; - static const float STRAIGHT_SKIP_NEAREST_DISTANCE_THRESHOLD = 0.5f; - static const float STRAIGHT_SKIP_SCORE = -1.0f; - static const float CORNER_ANGLE_THRESHOLD = M_PI_F / 6.0f; + static const float LOCALMIN_DISTANCE_AND_NEAR_TO_KEY_SCORE = 1.0f; + static const float CORNER_ANGLE_THRESHOLD = M_PI_F * 2.0f / 3.0f; + static const float CORNER_SUM_ANGLE_THRESHOLD = M_PI_F / 4.0f; static const float CORNER_SCORE = 1.0f; - const std::size_t size = mInputXs.size(); - if (size <= 1) { + const size_t size = mInputXs.size(); + // If there is only one point, add this point. Besides, if the previous point's distance map + // is empty, we re-compute nearby keys distances from the current point. + // Note that the current point is the first point in the incremental input that needs to + // be re-computed. + if (size <= 1 || prevNearKeysDistances->empty()) { return 0.0f; } + const int baseSampleRate = mProximityInfo->getMostCommonKeyWidth(); - const int distNext = getDistanceInt(x, y, mInputXs.back(), mInputYs.back()) - * DISTANCE_BASE_SCALE; const int distPrev = getDistanceInt(mInputXs.back(), mInputYs.back(), mInputXs[size - 2], mInputYs[size - 2]) * DISTANCE_BASE_SCALE; float score = 0.0f; - // Sum of distances - if (distPrev + distNext > baseSampleRate * SAVE_DISTANCE_SCALE) { - score += SAVE_DISTANCE_SCORE; - } - // Distance - if (distPrev < baseSampleRate * SKIP_DISTANCE_SCALE) { - score += SKIP_DISTANCE_SCORE; - } // Location - if (distPrev < baseSampleRate * CHECK_LOCALMIN_DISTANCE_THRESHOLD_SCALE) { - if (!isPrevLocalMin(currentNearKeysDistances, prevNearKeysDistances, - prevPrevNearKeysDistances)) { - score += NOT_LOCALMIN_DISTANCE_SCORE; - } else if (nearest < NEAR_KEY_THRESHOLD) { - // Promote points nearby keys - score += LOCALMIN_DISTANCE_AND_NEAR_TO_KEY_SCORE; - } + if (!isPrevLocalMin(currentNearKeysDistances, prevNearKeysDistances, + prevPrevNearKeysDistances)) { + score += NOT_LOCALMIN_DISTANCE_SCORE; + } else if (nearest < NEAR_KEY_THRESHOLD) { + // Promote points nearby keys + score += LOCALMIN_DISTANCE_AND_NEAR_TO_KEY_SCORE; } // Angle const float angle1 = getAngle(x, y, mInputXs.back(), mInputYs.back()); const float angle2 = getAngle(mInputXs.back(), mInputYs.back(), mInputXs[size - 2], mInputYs[size - 2]); const float angleDiff = getAngleDiff(angle1, angle2); - // Skip straight - if (nearest > STRAIGHT_SKIP_NEAREST_DISTANCE_THRESHOLD - && distPrev < baseSampleRate * STRAIGHT_SKIP_DISTANCE_THRESHOLD_SCALE - && angleDiff < STRAIGHT_ANGLE_THRESHOLD) { - score += STRAIGHT_SKIP_SCORE; - } + // Save corner if (distPrev > baseSampleRate * CORNER_CHECK_DISTANCE_THRESHOLD_SCALE - && angleDiff > CORNER_ANGLE_THRESHOLD) { + && (sumAngle > CORNER_SUM_ANGLE_THRESHOLD || angleDiff > CORNER_ANGLE_THRESHOLD)) { score += CORNER_SCORE; } return score; @@ -438,18 +442,17 @@ float ProximityInfoState::getPointScore( // Sampling touch point and pushing information to vectors. // Returning if previous point is popped or not. bool ProximityInfoState::pushTouchPoint(const int inputIndex, const int nodeChar, int x, int y, - const int time, const bool sample, const bool isLastPoint, + const int time, const bool sample, const bool isLastPoint, const float sumAngle, NearKeysDistanceMap *const currentNearKeysDistances, const NearKeysDistanceMap *const prevNearKeysDistances, const NearKeysDistanceMap *const prevPrevNearKeysDistances) { static const int LAST_POINT_SKIP_DISTANCE_SCALE = 4; - static const int LAST_AND_NOT_NEAREST_POINT_SKIP_DISTANCE_SCALE = 2; size_t size = mInputXs.size(); bool popped = false; if (nodeChar < 0 && sample) { const float nearest = updateNearKeysDistances(x, y, currentNearKeysDistances); - const float score = getPointScore(x, y, time, isLastPoint, nearest, + const float score = getPointScore(x, y, time, isLastPoint, nearest, sumAngle, currentNearKeysDistances, prevNearKeysDistances, prevPrevNearKeysDistances); if (score < 0) { // Pop previous point because it would be useless. @@ -461,9 +464,8 @@ bool ProximityInfoState::pushTouchPoint(const int inputIndex, const int nodeChar } // Check if the last point should be skipped. if (isLastPoint && size > 0) { - const int lastPointsDistance = getDistanceInt(x, y, mInputXs.back(), mInputYs.back()); - if (lastPointsDistance * LAST_POINT_SKIP_DISTANCE_SCALE - < mProximityInfo->getMostCommonKeyWidth()) { + if (getDistanceInt(x, y, mInputXs.back(), mInputYs.back()) + * LAST_POINT_SKIP_DISTANCE_SCALE < mProximityInfo->getMostCommonKeyWidth()) { // This point is not used because it's too close to the previous point. if (DEBUG_GEO_FULL) { AKLOGI("p0: size = %zd, x = %d, y = %d, lx = %d, ly = %d, dist = %d, " @@ -473,28 +475,6 @@ bool ProximityInfoState::pushTouchPoint(const int inputIndex, const int nodeChar / LAST_POINT_SKIP_DISTANCE_SCALE); } return popped; - } else if (lastPointsDistance * LAST_AND_NOT_NEAREST_POINT_SKIP_DISTANCE_SCALE - < mProximityInfo->getMostCommonKeyWidth()) { - int nearestChar = 0; - float nearestCharDistance = mMaxPointToKeyLength; - for (NearKeysDistanceMap::const_iterator it = currentNearKeysDistances->begin(); - it != currentNearKeysDistances->end(); ++it) { - if (nearestCharDistance > it->second) { - nearestChar = it->first; - nearestCharDistance = it->second; - } - } - NearKeysDistanceMap::const_iterator itPP = - prevNearKeysDistances->find(nearestChar); - if (itPP != prevNearKeysDistances->end() && nearestCharDistance > itPP->second) { - // The nearest key of the penultimate point is same as the nearest key of the - // last point. So, we don't need to use the last point. - if (DEBUG_GEO_FULL) { - AKLOGI("p1: char = %c, minDist = %f, prevNear key minDist = %f", - nearestChar, itPP->second, nearestCharDistance); - } - return popped; - } } } } @@ -550,11 +530,16 @@ int ProximityInfoState::getDuration(const int index) const { } float ProximityInfoState::getPointToKeyLength(const int inputIndex, const int codePoint) const { + const int keyId = mProximityInfo->getKeyIndexOf(codePoint); + if (keyId != NOT_AN_INDEX) { + const int index = inputIndex * mProximityInfo->getKeyCount() + keyId; + return min(mDistanceCache[index], mMaxPointToKeyLength); + } if (isSkippableChar(codePoint)) { return 0.0f; } - const int keyId = mProximityInfo->getKeyIndexOf(codePoint); - return getPointToKeyByIdLength(inputIndex, keyId); + // If the char is not a key on the keyboard then return the max length. + return MAX_POINT_TO_KEY_LENGTH; } float ProximityInfoState::getPointToKeyByIdLength(const int inputIndex, const int keyId) const { @@ -587,8 +572,9 @@ int32_t ProximityInfoState::getAllPossibleChars( return filterSize; } int newFilterSize = filterSize; - for (int j = 0; j < mProximityInfo->getKeyCount(); ++j) { - if (mNearKeysVector[index].test(j)) { + const int keyCount = mProximityInfo->getKeyCount(); + for (int j = 0; j < keyCount; ++j) { + if (mSearchKeysVector[index].test(j)) { const int32_t keyCodePoint = mProximityInfo->getCodePointOf(j); bool insert = true; // TODO: Avoid linear search @@ -606,6 +592,12 @@ int32_t ProximityInfoState::getAllPossibleChars( return newFilterSize; } +bool ProximityInfoState::isKeyInSerchKeysAfterIndex(const int index, const int keyId) const { + ASSERT(keyId >= 0); + ASSERT(index >= 0 && index < mInputSize); + return mSearchKeysVector[index].test(keyId); +} + void ProximityInfoState::popInputData() { mInputXs.pop_back(); mInputYs.pop_back(); @@ -614,18 +606,26 @@ void ProximityInfoState::popInputData() { mInputIndice.pop_back(); } +float ProximityInfoState::getDirection(const int index0, const int index1) const { + if (index0 < 0 || index0 > mInputSize - 1) { + return 0.0f; + } + if (index1 < 0 || index1 > mInputSize - 1) { + return 0.0f; + } + const int x1 = mInputXs[index0]; + const int y1 = mInputYs[index0]; + const int x2 = mInputXs[index1]; + const int y2 = mInputYs[index1]; + return getAngle(x1, y1, x2, y2); +} + float ProximityInfoState::getPointAngle(const int index) const { if (index <= 0 || index >= mInputSize - 1) { return 0.0f; } - const int x = mInputXs[index]; - const int y = mInputYs[index]; - const int nextX = mInputXs[index + 1]; - const int nextY = mInputYs[index + 1]; - const int previousX = mInputXs[index - 1]; - const int previousY = mInputYs[index - 1]; - const float previousDirection = getAngle(previousX, previousY, x, y); - const float nextDirection = getAngle(x, y, nextX, nextY); + const float previousDirection = getDirection(index - 1, index); + const float nextDirection = getDirection(index, index + 1); const float directionDiff = getAngleDiff(previousDirection, nextDirection); return directionDiff; } @@ -641,190 +641,354 @@ float ProximityInfoState::getPointsAngle( if (index2 < 0 || index2 > mInputSize - 1) { return 0.0f; } - const int x0 = mInputXs[index0]; - const int y0 = mInputYs[index0]; - const int x1 = mInputXs[index1]; - const int y1 = mInputYs[index1]; - const int x2 = mInputXs[index2]; - const int y2 = mInputYs[index2]; - const float previousDirection = getAngle(x0, y0, x1, y1); - const float nextDirection = getAngle(x1, y1, x2, y2); - const float directionDiff = getAngleDiff(previousDirection, nextDirection); - return directionDiff; + const float previousDirection = getDirection(index0, index1); + const float nextDirection = getDirection(index1, index2); + return getAngleDiff(previousDirection, nextDirection); +} + +float ProximityInfoState::getLineToKeyDistance( + const int from, const int to, const int keyId, const bool extend) const { + if (from < 0 || from > mInputSize - 1) { + return 0.0f; + } + if (to < 0 || to > mInputSize - 1) { + return 0.0f; + } + const int x0 = mInputXs[from]; + const int y0 = mInputYs[from]; + const int x1 = mInputXs[to]; + const int y1 = mInputYs[to]; + + const int keyX = mProximityInfo->getKeyCenterXOfKeyIdG(keyId); + const int keyY = mProximityInfo->getKeyCenterYOfKeyIdG(keyId); + + return pointToLineSegSquaredDistanceFloat(keyX, keyY, x0, y0, x1, y1, extend); } // Updates probabilities of aligning to some keys and skipping. // Word suggestion should be based on this probabilities. -void ProximityInfoState::updateAlignPointProbabilities() { - static const float MIN_PROBABILITY = 0.00001f; +void ProximityInfoState::updateAlignPointProbabilities(const int start) { + static const float MIN_PROBABILITY = 0.000001f; + static const float MAX_SKIP_PROBABILITY = 0.95f; static const float SKIP_FIRST_POINT_PROBABILITY = 0.01f; static const float SKIP_LAST_POINT_PROBABILITY = 0.1f; - static const float ANGLE_RATE = 0.8f; - static const float DEEP_CORNER_ANGLE_THRESHOLD = M_PI_F * 0.5f; - static const float SKIP_DEEP_CORNER_PROBABILITY = 0.3f; - static const float CORNER_ANGLE_THRESHOLD = M_PI_F * 35.0f / 180.0f; + static const float MIN_SPEED_RATE_FOR_SKIP_PROBABILITY = 0.15f; + static const float SPEED_WEIGHT_FOR_SKIP_PROBABILITY = 0.9f; + static const float SLOW_STRAIGHT_WEIGHT_FOR_SKIP_PROBABILITY = 0.6f; + static const float NEAREST_DISTANCE_WEIGHT = 0.5f; + static const float NEAREST_DISTANCE_BIAS = 0.5f; + static const float NEAREST_DISTANCE_WEIGHT_FOR_LAST = 0.6f; + static const float NEAREST_DISTANCE_BIAS_FOR_LAST = 0.4f; + + static const float ANGLE_WEIGHT = 0.90f; + static const float DEEP_CORNER_ANGLE_THRESHOLD = M_PI_F * 60.0f / 180.0f; + static const float SKIP_DEEP_CORNER_PROBABILITY = 0.1f; + static const float CORNER_ANGLE_THRESHOLD = M_PI_F * 30.0f / 180.0f; static const float STRAIGHT_ANGLE_THRESHOLD = M_PI_F * 15.0f / 180.0f; - static const float SKIP_CORNER_PROBABILITY = 0.5f; - static const float SLOW_STRAIGHT_WEIGHT = 0.8f; + static const float SKIP_CORNER_PROBABILITY = 0.4f; + static const float SPEED_MARGIN = 0.1f; static const float CENTER_VALUE_OF_NORMALIZED_DISTRIBUTION = 0.0f; + const int keyCount = mProximityInfo->getKeyCount(); mCharProbabilities.resize(mInputSize); // Calculates probabilities of using a point as a correlated point with the character // for each point. - for (int i = 0; i < mInputSize; ++i) { - // First, calculates skip probability. Starts form 100%. + for (int i = start; i < mInputSize; ++i) { + mCharProbabilities[i].clear(); + // First, calculates skip probability. Starts form MIN_SKIP_PROBABILITY. // Note that all values that are multiplied to this probability should be in [0.0, 1.0]; - float skipProbability = 1.0f; - const float speed = getRelativeSpeed(i); + float skipProbability = MAX_SKIP_PROBABILITY; + + const float currentAngle = getPointAngle(i); + const float relativeSpeed = getRelativeSpeed(i); + + float nearestKeyDistance = static_cast(MAX_POINT_TO_KEY_LENGTH); + for (int j = 0; j < keyCount; ++j) { + if (mNearKeysVector[i].test(j)) { + const float distance = getPointToKeyByIdLength(i, j); + if (distance < nearestKeyDistance) { + nearestKeyDistance = distance; + } + } + } - // Adjusts skip probability by a rate depending on speed. - skipProbability *= min(1.0f, speed); if (i == 0) { + skipProbability *= min(1.0f, nearestKeyDistance * NEAREST_DISTANCE_WEIGHT + + NEAREST_DISTANCE_BIAS); + // Promote the first point skipProbability *= SKIP_FIRST_POINT_PROBABILITY; } else if (i == mInputSize - 1) { + skipProbability *= min(1.0f, nearestKeyDistance * NEAREST_DISTANCE_WEIGHT_FOR_LAST + + NEAREST_DISTANCE_BIAS_FOR_LAST); + // Promote the last point skipProbability *= SKIP_LAST_POINT_PROBABILITY; } else { - const float currentAngle = getPointAngle(i); + // If the current speed is relatively slower than adjacent keys, we promote this point. + if (getRelativeSpeed(i - 1) - SPEED_MARGIN > relativeSpeed + && relativeSpeed < getRelativeSpeed(i + 1) - SPEED_MARGIN) { + if (currentAngle < CORNER_ANGLE_THRESHOLD) { + skipProbability *= min(1.0f, relativeSpeed + * SLOW_STRAIGHT_WEIGHT_FOR_SKIP_PROBABILITY); + } else { + // If the angle is small enough, we promote this point more. (e.g. pit vs put) + skipProbability *= min(1.0f, relativeSpeed * SPEED_WEIGHT_FOR_SKIP_PROBABILITY + + MIN_SPEED_RATE_FOR_SKIP_PROBABILITY); + } + } + + skipProbability *= min(1.0f, relativeSpeed * nearestKeyDistance * + NEAREST_DISTANCE_WEIGHT + NEAREST_DISTANCE_BIAS); // Adjusts skip probability by a rate depending on angle. // ANGLE_RATE of skipProbability is adjusted by current angle. - skipProbability *= max((M_PI_F - currentAngle) / M_PI_F, 0.0f) * ANGLE_RATE + - (1.0f - ANGLE_RATE); + skipProbability *= (M_PI_F - currentAngle) / M_PI_F * ANGLE_WEIGHT + + (1.0f - ANGLE_WEIGHT); if (currentAngle > DEEP_CORNER_ANGLE_THRESHOLD) { skipProbability *= SKIP_DEEP_CORNER_PROBABILITY; } - const float prevAngle = getPointsAngle(i, i - 1, i - 2); - if (prevAngle < STRAIGHT_ANGLE_THRESHOLD && currentAngle > CORNER_ANGLE_THRESHOLD) { + // We assume the angle of this point is the angle for point[i], point[i - 2] + // and point[i - 3]. The reason why we don't use the angle for point[i], point[i - 1] + // and point[i - 2] is this angle can be more affected by the noise. + const float prevAngle = getPointsAngle(i, i - 2, i - 3); + if (i >= 3 && prevAngle < STRAIGHT_ANGLE_THRESHOLD + && currentAngle > CORNER_ANGLE_THRESHOLD) { skipProbability *= SKIP_CORNER_PROBABILITY; } - if (currentAngle < STRAIGHT_ANGLE_THRESHOLD) { - // Adjusts skip probability by speed. - skipProbability *= min(1.0f, speed * SLOW_STRAIGHT_WEIGHT); - } } - // probabilities must be in [0.0, 1.0]; + // probabilities must be in [0.0, MAX_SKIP_PROBABILITY]; ASSERT(skipProbability >= 0.0f); - ASSERT(skipProbability <= 1.0f); - + ASSERT(skipProbability <= MAX_SKIP_PROBABILITY); mCharProbabilities[i][NOT_AN_INDEX] = skipProbability; + // Second, calculates key probabilities by dividing the rest probability // (1.0f - skipProbability). const float inputCharProbability = 1.0f - skipProbability; - // Summing up probability densities of all near keys. - float sumOfProbabilityDensityOfNearKeys = 0.0f; - const float sigma = speed; + + // TODO: The variance is critical for accuracy; thus, adjusting these parameter by machine + // learning or something would be efficient. + static const float SPEEDxANGLE_WEIGHT_FOR_STANDARD_DIVIATION = 0.3f; + static const float MAX_SPEEDxANGLE_RATE_FOR_STANDERD_DIVIATION = 0.25f; + static const float SPEEDxNEAREST_WEIGHT_FOR_STANDARD_DIVIATION = 0.5f; + static const float MAX_SPEEDxNEAREST_RATE_FOR_STANDERD_DIVIATION = 0.15f; + static const float MIN_STANDERD_DIVIATION = 0.37f; + + const float speedxAngleRate = min(relativeSpeed * currentAngle / M_PI_F + * SPEEDxANGLE_WEIGHT_FOR_STANDARD_DIVIATION, + MAX_SPEEDxANGLE_RATE_FOR_STANDERD_DIVIATION); + const float speedxNearestKeyDistanceRate = min(relativeSpeed * nearestKeyDistance + * SPEEDxNEAREST_WEIGHT_FOR_STANDARD_DIVIATION, + MAX_SPEEDxNEAREST_RATE_FOR_STANDERD_DIVIATION); + const float sigma = speedxAngleRate + speedxNearestKeyDistanceRate + MIN_STANDERD_DIVIATION; + NormalDistribution distribution(CENTER_VALUE_OF_NORMALIZED_DISTRIBUTION, sigma); - for (int j = 0; j < mProximityInfo->getKeyCount(); ++j) { + static const float PREV_DISTANCE_WEIGHT = 0.5f; + static const float NEXT_DISTANCE_WEIGHT = 0.6f; + // Summing up probability densities of all near keys. + float sumOfProbabilityDensities = 0.0f; + for (int j = 0; j < keyCount; ++j) { if (mNearKeysVector[i].test(j)) { - const float distance = sqrtf(getPointToKeyByIdLength(i, j)); - sumOfProbabilityDensityOfNearKeys += distribution.getProbabilityDensity(distance); + float distance = sqrtf(getPointToKeyByIdLength(i, j)); + if (i == 0 && i != mInputSize - 1) { + // For the first point, weighted average of distances from first point and the + // next point to the key is used as a point to key distance. + const float nextDistance = sqrtf(getPointToKeyByIdLength(i + 1, j)); + if (nextDistance < distance) { + // The distance of the first point tends to bigger than continuing + // points because the first touch by the user can be sloppy. + // So we promote the first point if the distance of that point is larger + // than the distance of the next point. + distance = (distance + nextDistance * NEXT_DISTANCE_WEIGHT) + / (1.0f + NEXT_DISTANCE_WEIGHT); + } + } else if (i != 0 && i == mInputSize - 1) { + // For the first point, weighted average of distances from last point and + // the previous point to the key is used as a point to key distance. + const float previousDistance = sqrtf(getPointToKeyByIdLength(i - 1, j)); + if (previousDistance < distance) { + // The distance of the last point tends to bigger than continuing points + // because the last touch by the user can be sloppy. So we promote the + // last point if the distance of that point is larger than the distance of + // the previous point. + distance = (distance + previousDistance * PREV_DISTANCE_WEIGHT) + / (1.0f + PREV_DISTANCE_WEIGHT); + } + } + // TODO: Promote the first point when the extended line from the next input is near + // from a key. Also, promote the last point as well. + sumOfProbabilityDensities += distribution.getProbabilityDensity(distance); } } - for (int j = 0; j < mProximityInfo->getKeyCount(); ++j) { + + // Split the probability of an input point to keys that are close to the input point. + for (int j = 0; j < keyCount; ++j) { if (mNearKeysVector[i].test(j)) { - const float distance = sqrtf(getPointToKeyByIdLength(i, j)); - const float probabilityDessity = distribution.getProbabilityDensity(distance); - // inputCharProbability divided to the probability for each near key. - const float probability = inputCharProbability * probabilityDessity - / sumOfProbabilityDensityOfNearKeys; - if (probability > MIN_PROBABILITY) { - mCharProbabilities[i][j] = probability; + float distance = sqrtf(getPointToKeyByIdLength(i, j)); + if (i == 0 && i != mInputSize - 1) { + // For the first point, weighted average of distances from the first point and + // the next point to the key is used as a point to key distance. + const float prevDistance = sqrtf(getPointToKeyByIdLength(i + 1, j)); + if (prevDistance < distance) { + distance = (distance + prevDistance * NEXT_DISTANCE_WEIGHT) + / (1.0f + NEXT_DISTANCE_WEIGHT); + } + } else if (i != 0 && i == mInputSize - 1) { + // For the first point, weighted average of distances from last point and + // the previous point to the key is used as a point to key distance. + const float prevDistance = sqrtf(getPointToKeyByIdLength(i - 1, j)); + if (prevDistance < distance) { + distance = (distance + prevDistance * PREV_DISTANCE_WEIGHT) + / (1.0f + PREV_DISTANCE_WEIGHT); + } } + const float probabilityDensity = distribution.getProbabilityDensity(distance); + const float probability = inputCharProbability * probabilityDensity + / sumOfProbabilityDensities; + mCharProbabilities[i][j] = probability; } } } + + if (DEBUG_POINTS_PROBABILITY) { + for (int i = 0; i < mInputSize; ++i) { + std::stringstream sstream; + sstream << i << ", "; + sstream << "("<< mInputXs[i] << ", "; + sstream << ", "<< mInputYs[i] << "), "; + sstream << "Speed: "<< getRelativeSpeed(i) << ", "; + sstream << "Angle: "<< getPointAngle(i) << ", \n"; + + for (hash_map_compat::iterator it = mCharProbabilities[i].begin(); + it != mCharProbabilities[i].end(); ++it) { + if (it->first == NOT_AN_INDEX) { + sstream << it->first + << "(skip):" + << it->second + << "\n"; + } else { + sstream << it->first + << "(" + << static_cast(mProximityInfo->getCodePointOf(it->first)) + << "):" + << it->second + << "\n"; + } + } + AKLOGI("%s", sstream.str().c_str()); + } + } + // Decrease key probabilities of points which don't have the highest probability of that key // among nearby points. Probabilities of the first point and the last point are not suppressed. - for (int i = 1; i < mInputSize - 1; ++i) { - // forward + for (int i = max(start, 1); i < mInputSize; ++i) { for (int j = i + 1; j < mInputSize; ++j) { - if (suppressCharProbabilities(i, j)) { + if (!suppressCharProbabilities(i, j)) { break; } } - // backward - for (int j = i - 1; j >= 0; --j) { - if (suppressCharProbabilities(i, j)) { + for (int j = i - 1; j >= max(start, 0); --j) { + if (!suppressCharProbabilities(i, j)) { break; } } } - if (DEBUG_POINTS_PROBABILITY) { - for (int i = 0; i < mInputSize; ++i) { - std::stringstream sstream; - sstream << i << ", "; - for (hash_map_compat::iterator it = mCharProbabilities[i].begin(); - it != mCharProbabilities[i].end(); ++it) { - sstream << it->first - << "(" - << static_cast(mProximityInfo->getCodePointOf(it->first)) - << "):" - << it->second - << ", "; + // Converting from raw probabilities to log probabilities to calculate spatial distance. + for (int i = start; i < mInputSize; ++i) { + for (int j = 0; j < keyCount; ++j) { + hash_map_compat::iterator it = mCharProbabilities[i].find(j); + if (it == mCharProbabilities[i].end()){ + mNearKeysVector[i].reset(j); + } else if(it->second < MIN_PROBABILITY) { + // Erases from near keys vector because it has very low probability. + mNearKeysVector[i].reset(j); + mCharProbabilities[i].erase(j); + } else { + it->second = -logf(it->second); } - AKLOGI("%s", sstream.str().c_str()); } + mCharProbabilities[i][NOT_AN_INDEX] = -logf(mCharProbabilities[i][NOT_AN_INDEX]); } } -// Decreases char probabilities of index0 by checking probabilities of a near point (index1). +// Decreases char probabilities of index0 by checking probabilities of a near point (index1) and +// increases char probabilities of index1 by checking probabilities of index0. bool ProximityInfoState::suppressCharProbabilities(const int index0, const int index1) { ASSERT(0 <= index0 && index0 < mInputSize); ASSERT(0 <= index1 && index1 < mInputSize); + static const float SUPPRESSION_LENGTH_WEIGHT = 1.5f; + static const float MIN_SUPPRESSION_RATE = 0.1f; + static const float SUPPRESSION_WEIGHT = 0.5f; + static const float SUPPRESSION_WEIGHT_FOR_PROBABILITY_GAIN = 0.1f; + static const float SKIP_PROBABALITY_WEIGHT_FOR_PROBABILITY_GAIN = 0.3f; + const float keyWidthFloat = static_cast(mProximityInfo->getMostCommonKeyWidth()); const float diff = fabsf(static_cast(mLengthCache[index0] - mLengthCache[index1])); if (diff > keyWidthFloat * SUPPRESSION_LENGTH_WEIGHT) { return false; } - // Summing up decreased amount of probabilities from 0%. - float sumOfAdjustedProbabilities = 0.0f; - const float suppressionRate = diff / keyWidthFloat / SUPPRESSION_LENGTH_WEIGHT; + const float suppressionRate = MIN_SUPPRESSION_RATE + + diff / keyWidthFloat / SUPPRESSION_LENGTH_WEIGHT * SUPPRESSION_WEIGHT; for (hash_map_compat::iterator it = mCharProbabilities[index0].begin(); it != mCharProbabilities[index0].end(); ++it) { - hash_map_compat::const_iterator it2 = - mCharProbabilities[index1].find(it->first); + hash_map_compat::iterator it2 = mCharProbabilities[index1].find(it->first); if (it2 != mCharProbabilities[index1].end() && it->second < it2->second) { const float newProbability = it->second * suppressionRate; - sumOfAdjustedProbabilities += it->second - newProbability; + const float suppression = it->second - newProbability; it->second = newProbability; + // mCharProbabilities[index0][NOT_AN_INDEX] is the probability of skipping this point. + mCharProbabilities[index0][NOT_AN_INDEX] += suppression; + + // Add the probability of the same key nearby index1 + const float probabilityGain = min(suppression * SUPPRESSION_WEIGHT_FOR_PROBABILITY_GAIN, + mCharProbabilities[index1][NOT_AN_INDEX] + * SKIP_PROBABALITY_WEIGHT_FOR_PROBABILITY_GAIN); + it2->second += probabilityGain; + mCharProbabilities[index1][NOT_AN_INDEX] -= probabilityGain; } } - // All decreased amount of probabilities are added to the probability of skipping. - mCharProbabilities[index0][NOT_AN_INDEX] += sumOfAdjustedProbabilities; return true; } // Get a word that is detected by tracing highest probability sequence into charBuf and returns // probability of generating the word. float ProximityInfoState::getHighestProbabilitySequence(uint16_t *const charBuf) const { - int buf[mInputSize]; - // Maximum probabilities of each point are multiplied to 100%. - float probability = 1.0f; + static const float LOG_PROBABILITY_MARGIN = 0.2f; + 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 < mInputSize; ++i) { - float maxProbability = 0.0f; + for (int i = 0; i < mInputSize && index < MAX_WORD_LENGTH_INTERNAL - 1; ++i) { + float minLogProbability = static_cast(MAX_POINT_TO_KEY_LENGTH); + int character = NOT_AN_INDEX; for (hash_map_compat::const_iterator it = mCharProbabilities[i].begin(); it != mCharProbabilities[i].end(); ++it) { - if (it->second > maxProbability) { - maxProbability = it->second; - buf[i] = it->first; + const float logProbability = (it->first != NOT_AN_INDEX) + ? it->second + LOG_PROBABILITY_MARGIN : it->second; + if (logProbability < minLogProbability) { + minLogProbability = logProbability; + character = it->first; } } - probability *= maxProbability; - } - int index = 0; - for (int i = 0; i < mInputSize && index < MAX_WORD_LENGTH_INTERNAL - 1; ++i) { - if (buf[i] != NOT_AN_INDEX) { - charBuf[index] = mProximityInfo->getCodePointOf(buf[i]); + if (character != NOT_AN_INDEX) { + charBuf[index] = mProximityInfo->getCodePointOf(character); index++; } + sumLogProbability += minLogProbability; } charBuf[index] = '\0'; - return probability; + return sumLogProbability; +} + +// Returns a probability of mapping index to keyIndex. +float ProximityInfoState::getProbability(const int index, const int keyIndex) const { + ASSERT(0 <= index && index < mInputSize); + hash_map_compat::const_iterator it = mCharProbabilities[index].find(keyIndex); + if (it != mCharProbabilities[index].end()) { + return it->second; + } + return static_cast(MAX_POINT_TO_KEY_LENGTH); } } // namespace latinime diff --git a/native/jni/src/proximity_info_state.h b/native/jni/src/proximity_info_state.h index 7286e5ed5..927244b02 100644 --- a/native/jni/src/proximity_info_state.h +++ b/native/jni/src/proximity_info_state.h @@ -56,7 +56,8 @@ class ProximityInfoState { mKeyCount(0), mCellHeight(0), mCellWidth(0), mGridHeight(0), mGridWidth(0), mIsContinuationPossible(false), mInputXs(), mInputYs(), mTimes(), mInputIndice(), mDistanceCache(), mLengthCache(), mRelativeSpeeds(), mCharProbabilities(), - mNearKeysVector(), mTouchPositionCorrectionEnabled(false), mInputSize(0) { + mNearKeysVector(), mSearchKeysVector(), + mTouchPositionCorrectionEnabled(false), mInputSize(0) { memset(mInputCodes, 0, sizeof(mInputCodes)); memset(mNormalizedSquaredDistances, 0, sizeof(mNormalizedSquaredDistances)); memset(mPrimaryInputWord, 0, sizeof(mPrimaryInputWord)); @@ -214,7 +215,6 @@ class ProximityInfoState { } float getPointToKeyLength(const int inputIndex, const int charCode) const; - float getPointToKeyByIdLength(const int inputIndex, const int keyId) const; int getSpaceY() const; @@ -226,11 +226,21 @@ class ProximityInfoState { return mRelativeSpeeds[index]; } + // get xy direction + float getDirection(const int x, const int y) const; + float getPointAngle(const int index) const; // Returns angle of three points. x, y, and z are indices. float getPointsAngle(const int index0, const int index1, const int index2) const; float getHighestProbabilitySequence(uint16_t *const charBuf) const; + + float getProbability(const int index, const int charCode) const; + + float getLineToKeyDistance( + const int from, const int to, const int keyId, const bool extend) const; + + bool isKeyInSerchKeysAfterIndex(const int index, const int keyId) const; private: DISALLOW_COPY_AND_ASSIGN(ProximityInfoState); typedef hash_map_compat NearKeysDistanceMap; @@ -243,7 +253,7 @@ class ProximityInfoState { const int keyIndex, const int inputIndex) const; bool pushTouchPoint(const int inputIndex, const int nodeChar, int x, int y, const int time, - const bool sample, const bool isLastPoint, + const bool sample, const bool isLastPoint, const float sumAngle, NearKeysDistanceMap *const currentNearKeysDistances, const NearKeysDistanceMap *const prevNearKeysDistances, const NearKeysDistanceMap *const prevPrevNearKeysDistances); @@ -267,13 +277,13 @@ class ProximityInfoState { const NearKeysDistanceMap *const prevPrevNearKeysDistances) const; float getPointScore( const int x, const int y, const int time, const bool last, const float nearest, - const NearKeysDistanceMap *const currentNearKeysDistances, + const float sumAngle, const NearKeysDistanceMap *const currentNearKeysDistances, const NearKeysDistanceMap *const prevNearKeysDistances, const NearKeysDistanceMap *const prevPrevNearKeysDistances) const; bool checkAndReturnIsContinuationPossible(const int inputSize, const int *const xCoordinates, const int *const yCoordinates, const int *const times); void popInputData(); - void updateAlignPointProbabilities(); + void updateAlignPointProbabilities(const int start); bool suppressCharProbabilities(const int index1, const int index2); // const @@ -298,7 +308,15 @@ class ProximityInfoState { std::vector mRelativeSpeeds; // probabilities of skipping or mapping to a key for each point. std::vector > mCharProbabilities; + // The vector for the key code set which holds nearby keys for each sampled input point + // 1. Used to calculate the probability of the key + // 2. Used to calculate mSearchKeysVector std::vector mNearKeysVector; + // The vector for the key code set which holds nearby keys of some trailing sampled input points + // for each sampled input point. These nearby keys contain the next characters which can be in + // the dictionary. Specifically, currently we are looking for keys nearby trailing sampled + // inputs including the current input point. + std::vector mSearchKeysVector; 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]; -- cgit v1.2.3-83-g751a From 1e06a4d8e9e71188ed685282155ea52a48ddc050 Mon Sep 17 00:00:00 2001 From: Keisuke Kuroyanagi Date: Thu, 11 Oct 2012 20:24:41 +0900 Subject: Improve gesture input scoring method 3. Change-Id: I3142cb5ec922e661f0d7c1e1706de6015360b2ff --- native/jni/src/proximity_info_state.cpp | 8 ++++++++ native/jni/src/proximity_info_state.h | 8 ++++++-- 2 files changed, 14 insertions(+), 2 deletions(-) (limited to 'native/jni/src') diff --git a/native/jni/src/proximity_info_state.cpp b/native/jni/src/proximity_info_state.cpp index 0f7e4d65f..bbc0deede 100644 --- a/native/jni/src/proximity_info_state.cpp +++ b/native/jni/src/proximity_info_state.cpp @@ -108,6 +108,7 @@ void ProximityInfoState::initInputParams(const int pointerId, const float maxPoi mSearchKeysVector.clear(); mRelativeSpeeds.clear(); mCharProbabilities.clear(); + mDirections.clear(); } if (DEBUG_GEO_FULL) { AKLOGI("Init ProximityInfoState: reused points = %d, last input size = %d", @@ -216,6 +217,13 @@ void ProximityInfoState::initInputParams(const int pointerId, const float maxPoi mRelativeSpeeds[i] = speed / averageSpeed; } } + + // Direction calculation. + mDirections.resize(mInputSize - 1); + for (int i = max(0, lastSavedInputSize - 1); i < mInputSize - 1; ++i) { + mDirections[i] = getDirection(i, i + 1); + } + } if (DEBUG_GEO_FULL) { diff --git a/native/jni/src/proximity_info_state.h b/native/jni/src/proximity_info_state.h index 927244b02..1a3f2869d 100644 --- a/native/jni/src/proximity_info_state.h +++ b/native/jni/src/proximity_info_state.h @@ -55,8 +55,8 @@ class ProximityInfoState { mHasTouchPositionCorrectionData(false), mMostCommonKeyWidthSquare(0), mLocaleStr(), mKeyCount(0), mCellHeight(0), mCellWidth(0), mGridHeight(0), mGridWidth(0), mIsContinuationPossible(false), mInputXs(), mInputYs(), mTimes(), mInputIndice(), - mDistanceCache(), mLengthCache(), mRelativeSpeeds(), mCharProbabilities(), - mNearKeysVector(), mSearchKeysVector(), + mDistanceCache(), mLengthCache(), mRelativeSpeeds(), mDirections(), + mCharProbabilities(), mNearKeysVector(), mSearchKeysVector(), mTouchPositionCorrectionEnabled(false), mInputSize(0) { memset(mInputCodes, 0, sizeof(mInputCodes)); memset(mNormalizedSquaredDistances, 0, sizeof(mNormalizedSquaredDistances)); @@ -226,6 +226,9 @@ class ProximityInfoState { return mRelativeSpeeds[index]; } + float getDirection(const int index) const { + return mDirections[index]; + } // get xy direction float getDirection(const int x, const int y) const; @@ -306,6 +309,7 @@ class ProximityInfoState { std::vector mDistanceCache; std::vector mLengthCache; std::vector mRelativeSpeeds; + std::vector mDirections; // probabilities of skipping or mapping to a key for each point. std::vector > mCharProbabilities; // The vector for the key code set which holds nearby keys for each sampled input point -- cgit v1.2.3-83-g751a From 350309aeb81ad1924af4d2e6d0bceaa6f98e4821 Mon Sep 17 00:00:00 2001 From: Keisuke Kuroyanagi Date: Fri, 12 Oct 2012 19:46:23 +0900 Subject: Evaluate score by alignNextKeyToPath for not in the dictionary word. Change-Id: I68d30e734f8b4f629797d73d6b4745e967bdb09d --- native/jni/src/proximity_info_state.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'native/jni/src') diff --git a/native/jni/src/proximity_info_state.cpp b/native/jni/src/proximity_info_state.cpp index bbc0deede..d41acdace 100644 --- a/native/jni/src/proximity_info_state.cpp +++ b/native/jni/src/proximity_info_state.cpp @@ -963,7 +963,7 @@ bool ProximityInfoState::suppressCharProbabilities(const int index0, const int i // Get a word that is detected by tracing highest probability sequence into charBuf and returns // probability of generating the word. float ProximityInfoState::getHighestProbabilitySequence(uint16_t *const charBuf) const { - static const float LOG_PROBABILITY_MARGIN = 0.2f; + 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. @@ -973,7 +973,7 @@ float ProximityInfoState::getHighestProbabilitySequence(uint16_t *const charBuf) for (hash_map_compat::const_iterator it = mCharProbabilities[i].begin(); it != mCharProbabilities[i].end(); ++it) { const float logProbability = (it->first != NOT_AN_INDEX) - ? it->second + LOG_PROBABILITY_MARGIN : it->second; + ? it->second + DEMOTION_LOG_PROBABILITY : it->second; if (logProbability < minLogProbability) { minLogProbability = logProbability; character = it->first; -- cgit v1.2.3-83-g751a From d03e065b861bd1cdb90bc70f18b7d7a3815b7a4d Mon Sep 17 00:00:00 2001 From: Jean Chalard Date: Thu, 18 Oct 2012 07:28:18 +0900 Subject: Don't consider non-words for split word suggestion Bug: 7368683 Change-Id: Iecd8348be788e5a749dafabdf7eddc4a14d901e0 --- native/jni/src/unigram_dictionary.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'native/jni/src') diff --git a/native/jni/src/unigram_dictionary.cpp b/native/jni/src/unigram_dictionary.cpp index 49d044fbc..e3649bd4b 100644 --- a/native/jni/src/unigram_dictionary.cpp +++ b/native/jni/src/unigram_dictionary.cpp @@ -798,7 +798,8 @@ int UnigramDictionary::getMostFrequentWordLikeInner(const uint16_t *const inWord // into inputIndex if there is a match. const bool isAlike = testCharGroupForContinuedLikeness(flags, root, pos, inWord, inputIndex, inputSize, newWord, &inputIndex, &pos); - if (isAlike && (BinaryFormat::FLAG_IS_TERMINAL & flags) && (inputIndex == inputSize)) { + if (isAlike && (!(BinaryFormat::FLAG_IS_NOT_A_WORD & flags)) + && (BinaryFormat::FLAG_IS_TERMINAL & flags) && (inputIndex == inputSize)) { const int frequency = BinaryFormat::readFrequencyWithoutMovingPointer(root, pos); onTerminalWordLike(frequency, newWord, inputIndex, outWord, &maxFreq); } -- cgit v1.2.3-83-g751a From 1e61493c50082264caaef862df02b1ccc84dc396 Mon Sep 17 00:00:00 2001 From: Ken Wakasa Date: Mon, 29 Oct 2012 18:06:22 +0900 Subject: Use 32-bit code points for suggestions output This is a multi-project commit with Ic43dd666 bug: 6526418 Change-Id: I39c1acb4e91d04cd8a4ec5a943c8cf575da75ebc --- .../inputmethod/latin/BinaryDictionary.java | 36 +++++----- ..._android_inputmethod_latin_BinaryDictionary.cpp | 56 +++++++-------- native/jni/src/bigram_dictionary.cpp | 31 +++++---- native/jni/src/bigram_dictionary.h | 16 ++--- native/jni/src/binary_format.h | 35 +++++----- native/jni/src/char_utils.h | 30 ++++---- native/jni/src/correction.cpp | 75 ++++++++++---------- native/jni/src/correction.h | 45 ++++++------ native/jni/src/defines.h | 43 ++++-------- native/jni/src/dictionary.cpp | 11 ++- native/jni/src/dictionary.h | 12 ++-- native/jni/src/gesture/gesture_decoder_wrapper.h | 11 ++- .../src/gesture/incremental_decoder_interface.h | 7 +- .../jni/src/gesture/incremental_decoder_wrapper.h | 11 ++- native/jni/src/proximity_info_state.cpp | 41 +++++------ native/jni/src/proximity_info_state.h | 61 +++++++++-------- native/jni/src/terminal_attributes.h | 10 ++- native/jni/src/unigram_dictionary.cpp | 80 ++++++++++------------ native/jni/src/unigram_dictionary.h | 23 +++---- native/jni/src/words_priority_queue.h | 58 ++++++++-------- 20 files changed, 329 insertions(+), 363 deletions(-) (limited to 'native/jni/src') diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionary.java b/java/src/com/android/inputmethod/latin/BinaryDictionary.java index 80af4b9fa..a7024d1d8 100644 --- a/java/src/com/android/inputmethod/latin/BinaryDictionary.java +++ b/java/src/com/android/inputmethod/latin/BinaryDictionary.java @@ -51,8 +51,7 @@ public final class BinaryDictionary extends Dictionary { private long mNativeDict; private final Locale mLocale; private final int[] mInputCodePoints = new int[MAX_WORD_LENGTH]; - // TODO: The below should be int[] mOutputCodePoints - private final char[] mOutputChars = new char[MAX_WORD_LENGTH * MAX_RESULTS]; + private final int[] mOutputCodePoints = new int[MAX_WORD_LENGTH * MAX_RESULTS]; private final int[] mSpaceIndices = new int[MAX_SPACES]; private final int[] mOutputScores = new int[MAX_RESULTS]; private final int[] mOutputTypes = new int[MAX_RESULTS]; @@ -88,9 +87,9 @@ public final class BinaryDictionary extends Dictionary { * @param useFullEditDistance whether to use the full edit distance in suggestions * @param dictType the dictionary type, as a human-readable string */ - public BinaryDictionary(final Context context, - final String filename, final long offset, final long length, - final boolean useFullEditDistance, final Locale locale, final String dictType) { + public BinaryDictionary(final Context context, final String filename, final long offset, + final long length, final boolean useFullEditDistance, final Locale locale, + final String dictType) { super(dictType); mLocale = locale; mUseFullEditDistance = useFullEditDistance; @@ -109,10 +108,10 @@ public final class BinaryDictionary extends Dictionary { private native int getSuggestionsNative(long dict, long proximityInfo, long traverseSession, int[] xCoordinates, int[] yCoordinates, int[] times, int[] pointerIds, int[] inputCodePoints, int codesSize, int commitPoint, boolean isGesture, - int[] prevWordCodePointArray, boolean useFullEditDistance, char[] outputChars, + int[] prevWordCodePointArray, boolean useFullEditDistance, int[] outputCodePoints, int[] outputScores, int[] outputIndices, int[] outputTypes); - private static native float calcNormalizedScoreNative(char[] before, char[] after, int score); - private static native int editDistanceNative(char[] before, char[] after); + private static native float calcNormalizedScoreNative(int[] before, int[] after, int score); + private static native int editDistanceNative(int[] before, int[] after); // TODO: Move native dict into session private final void loadDictionary(final String path, final long startOffset, @@ -153,7 +152,8 @@ public final class BinaryDictionary extends Dictionary { proximityInfo.getNativeProximityInfo(), getTraverseSession(sessionId).getSession(), ips.getXCoordinates(), ips.getYCoordinates(), ips.getTimes(), ips.getPointerIds(), mInputCodePoints, codesSize, 0 /* commitPoint */, isGesture, prevWordCodePointArray, - mUseFullEditDistance, mOutputChars, mOutputScores, mSpaceIndices, mOutputTypes); + mUseFullEditDistance, mOutputCodePoints, mOutputScores, mSpaceIndices, + mOutputTypes); final int count = Math.min(tmpCount, MAX_PREDICTIONS); final ArrayList suggestions = CollectionUtils.newArrayList(); @@ -161,14 +161,14 @@ public final class BinaryDictionary extends Dictionary { if (composerSize > 0 && mOutputScores[j] < 1) break; final int start = j * MAX_WORD_LENGTH; int len = 0; - while (len < MAX_WORD_LENGTH && mOutputChars[start + len] != 0) { + while (len < MAX_WORD_LENGTH && mOutputCodePoints[start + len] != 0) { ++len; } if (len > 0) { final int score = SuggestedWordInfo.KIND_WHITELIST == mOutputTypes[j] ? SuggestedWordInfo.MAX_SCORE : mOutputScores[j]; - suggestions.add(new SuggestedWordInfo( - new String(mOutputChars, start, len), score, mOutputTypes[j], mDictType)); + suggestions.add(new SuggestedWordInfo(new String(mOutputCodePoints, start, len), + score, mOutputTypes[j], mDictType)); } } return suggestions; @@ -180,14 +180,16 @@ public final class BinaryDictionary extends Dictionary { public static float calcNormalizedScore(final String before, final String after, final int score) { - return calcNormalizedScoreNative(before.toCharArray(), after.toCharArray(), score); + return calcNormalizedScoreNative(StringUtils.toCodePointArray(before), + StringUtils.toCodePointArray(after), score); } public static int editDistance(final String before, final String after) { if (before == null || after == null) { throw new IllegalArgumentException(); } - return editDistanceNative(before.toCharArray(), after.toCharArray()); + return editDistanceNative(StringUtils.toCodePointArray(before), + StringUtils.toCodePointArray(after)); } @Override @@ -206,9 +208,9 @@ public final class BinaryDictionary extends Dictionary { // calls when checking for changes in an entire dictionary. public boolean isValidBigram(final String word1, final String word2) { if (TextUtils.isEmpty(word1) || TextUtils.isEmpty(word2)) return false; - final int[] chars1 = StringUtils.toCodePointArray(word1); - final int[] chars2 = StringUtils.toCodePointArray(word2); - return isValidBigramNative(mNativeDict, chars1, chars2); + final int[] codePoints1 = StringUtils.toCodePointArray(word1); + final int[] codePoints2 = StringUtils.toCodePointArray(word2); + return isValidBigramNative(mNativeDict, codePoints1, codePoints2); } @Override diff --git a/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp b/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp index 42f7da9d3..5b8d1119d 100644 --- a/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp +++ b/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp @@ -132,7 +132,7 @@ static int latinime_BinaryDictionary_getSuggestions(JNIEnv *env, jobject object, jintArray yCoordinatesArray, jintArray timesArray, jintArray pointerIdsArray, jintArray inputCodePointsArray, jint arraySize, jint commitPoint, jboolean isGesture, jintArray prevWordCodePointsForBigrams, jboolean useFullEditDistance, - jcharArray outputCharsArray, jintArray scoresArray, jintArray spaceIndicesArray, + jintArray outputCodePointsArray, jintArray scoresArray, jintArray spaceIndicesArray, jintArray outputTypesArray) { Dictionary *dictionary = reinterpret_cast(dict); if (!dictionary) return 0; @@ -162,16 +162,15 @@ static int latinime_BinaryDictionary_getSuggestions(JNIEnv *env, jobject object, } // Output values - // TODO: Should be "outputCodePointsLength" and "int outputCodePoints[]" - const jsize outputCharsLength = env->GetArrayLength(outputCharsArray); - unsigned short outputChars[outputCharsLength]; + const jsize outputCodePointsLength = env->GetArrayLength(outputCodePointsArray); + int outputCodePoints[outputCodePointsLength]; const jsize scoresLength = env->GetArrayLength(scoresArray); int scores[scoresLength]; const jsize spaceIndicesLength = env->GetArrayLength(spaceIndicesArray); int spaceIndices[spaceIndicesLength]; const jsize outputTypesLength = env->GetArrayLength(outputTypesArray); int outputTypes[outputTypesLength]; - memset(outputChars, 0, sizeof(outputChars)); + memset(outputCodePoints, 0, sizeof(outputCodePoints)); memset(scores, 0, sizeof(scores)); memset(spaceIndices, 0, sizeof(spaceIndices)); memset(outputTypes, 0, sizeof(outputTypes)); @@ -180,16 +179,15 @@ static int latinime_BinaryDictionary_getSuggestions(JNIEnv *env, jobject object, if (isGesture || arraySize > 0) { count = dictionary->getSuggestions(pInfo, traverseSession, xCoordinates, yCoordinates, times, pointerIds, inputCodePoints, arraySize, prevWordCodePoints, - prevWordCodePointsLength, commitPoint, isGesture, useFullEditDistance, outputChars, - scores, spaceIndices, outputTypes); + prevWordCodePointsLength, commitPoint, isGesture, useFullEditDistance, + outputCodePoints, scores, spaceIndices, outputTypes); } else { count = dictionary->getBigrams(prevWordCodePoints, prevWordCodePointsLength, - inputCodePoints, arraySize, outputChars, scores, outputTypes); + inputCodePoints, arraySize, outputCodePoints, scores, outputTypes); } // Copy back the output values - // TODO: Should be SetIntArrayRegion() - env->SetCharArrayRegion(outputCharsArray, 0, outputCharsLength, outputChars); + env->SetIntArrayRegion(outputCodePointsArray, 0, outputCodePointsLength, outputCodePoints); env->SetIntArrayRegion(scoresArray, 0, scoresLength, scores); env->SetIntArrayRegion(spaceIndicesArray, 0, spaceIndicesLength, spaceIndices); env->SetIntArrayRegion(outputTypesArray, 0, outputTypesLength, outputTypes); @@ -221,29 +219,27 @@ static jboolean latinime_BinaryDictionary_isValidBigram(JNIEnv *env, jobject obj } static jfloat latinime_BinaryDictionary_calcNormalizedScore(JNIEnv *env, jobject object, - jcharArray before, jcharArray after, jint score) { + jintArray before, jintArray after, jint score) { jsize beforeLength = env->GetArrayLength(before); jsize afterLength = env->GetArrayLength(after); - jchar beforeChars[beforeLength]; - jchar afterChars[afterLength]; - env->GetCharArrayRegion(before, 0, beforeLength, beforeChars); - env->GetCharArrayRegion(after, 0, afterLength, afterChars); - return Correction::RankingAlgorithm::calcNormalizedScore( - static_cast(beforeChars), beforeLength, - static_cast(afterChars), afterLength, score); + int beforeCodePoints[beforeLength]; + int afterCodePoints[afterLength]; + env->GetIntArrayRegion(before, 0, beforeLength, beforeCodePoints); + env->GetIntArrayRegion(after, 0, afterLength, afterCodePoints); + return Correction::RankingAlgorithm::calcNormalizedScore(beforeCodePoints, beforeLength, + afterCodePoints, afterLength, score); } -static jint latinime_BinaryDictionary_editDistance(JNIEnv *env, jobject object, - jcharArray before, jcharArray after) { +static jint latinime_BinaryDictionary_editDistance(JNIEnv *env, jobject object, jintArray before, + jintArray after) { jsize beforeLength = env->GetArrayLength(before); jsize afterLength = env->GetArrayLength(after); - jchar beforeChars[beforeLength]; - jchar afterChars[afterLength]; - env->GetCharArrayRegion(before, 0, beforeLength, beforeChars); - env->GetCharArrayRegion(after, 0, afterLength, afterChars); - return Correction::RankingAlgorithm::editDistance( - static_cast(beforeChars), beforeLength, - static_cast(afterChars), afterLength); + int beforeCodePoints[beforeLength]; + int afterCodePoints[afterLength]; + env->GetIntArrayRegion(before, 0, beforeLength, beforeCodePoints); + env->GetIntArrayRegion(after, 0, afterLength, afterCodePoints); + return Correction::RankingAlgorithm::editDistance(beforeCodePoints, beforeLength, + afterCodePoints, afterLength); } static void latinime_BinaryDictionary_close(JNIEnv *env, jobject object, jlong dict) { @@ -279,15 +275,15 @@ static JNINativeMethod sMethods[] = { {"openNative", "(Ljava/lang/String;JJIIII)J", reinterpret_cast(latinime_BinaryDictionary_open)}, {"closeNative", "(J)V", reinterpret_cast(latinime_BinaryDictionary_close)}, - {"getSuggestionsNative", "(JJJ[I[I[I[I[IIIZ[IZ[C[I[I[I)I", + {"getSuggestionsNative", "(JJJ[I[I[I[I[IIIZ[IZ[I[I[I[I)I", reinterpret_cast(latinime_BinaryDictionary_getSuggestions)}, {"getFrequencyNative", "(J[I)I", reinterpret_cast(latinime_BinaryDictionary_getFrequency)}, {"isValidBigramNative", "(J[I[I)Z", reinterpret_cast(latinime_BinaryDictionary_isValidBigram)}, - {"calcNormalizedScoreNative", "([C[CI)F", + {"calcNormalizedScoreNative", "([I[II)F", reinterpret_cast(latinime_BinaryDictionary_calcNormalizedScore)}, - {"editDistanceNative", "([C[C)I", + {"editDistanceNative", "([I[I)I", reinterpret_cast(latinime_BinaryDictionary_editDistance)} }; diff --git a/native/jni/src/bigram_dictionary.cpp b/native/jni/src/bigram_dictionary.cpp index dade4f16b..f89dd1615 100644 --- a/native/jni/src/bigram_dictionary.cpp +++ b/native/jni/src/bigram_dictionary.cpp @@ -36,13 +36,13 @@ BigramDictionary::BigramDictionary(const unsigned char *dict, int maxWordLength, BigramDictionary::~BigramDictionary() { } -bool BigramDictionary::addWordBigram(unsigned short *word, int length, int frequency, - int *bigramFreq, unsigned short *bigramChars, int *outputTypes) const { +bool BigramDictionary::addWordBigram(int *word, int length, int frequency, int *bigramFreq, + int *bigramCodePoints, int *outputTypes) const { word[length] = 0; if (DEBUG_DICT) { #ifdef FLAG_DBG char s[length + 1]; - for (int i = 0; i <= length; i++) s[i] = word[i]; + for (int i = 0; i <= length; i++) s[i] = static_cast(word[i]); AKLOGI("Bigram: Found word = %s, freq = %d :", s, frequency); #endif } @@ -51,7 +51,8 @@ bool BigramDictionary::addWordBigram(unsigned short *word, int length, int frequ int insertAt = 0; while (insertAt < MAX_PREDICTIONS) { if (frequency > bigramFreq[insertAt] || (bigramFreq[insertAt] == frequency - && length < Dictionary::wideStrLen(bigramChars + insertAt * MAX_WORD_LENGTH))) { + && length < Dictionary::wideStrLen( + bigramCodePoints + insertAt * MAX_WORD_LENGTH))) { break; } insertAt++; @@ -65,10 +66,10 @@ bool BigramDictionary::addWordBigram(unsigned short *word, int length, int frequ (MAX_PREDICTIONS - insertAt - 1) * sizeof(bigramFreq[0])); bigramFreq[insertAt] = frequency; outputTypes[insertAt] = Dictionary::KIND_PREDICTION; - memmove(bigramChars + (insertAt + 1) * MAX_WORD_LENGTH, - bigramChars + insertAt * MAX_WORD_LENGTH, - (MAX_PREDICTIONS - insertAt - 1) * sizeof(bigramChars[0]) * MAX_WORD_LENGTH); - unsigned short *dest = bigramChars + insertAt * MAX_WORD_LENGTH; + memmove(bigramCodePoints + (insertAt + 1) * MAX_WORD_LENGTH, + bigramCodePoints + insertAt * MAX_WORD_LENGTH, + (MAX_PREDICTIONS - insertAt - 1) * sizeof(bigramCodePoints[0]) * MAX_WORD_LENGTH); + int *dest = bigramCodePoints + insertAt * MAX_WORD_LENGTH; while (length--) { *dest++ = *word++; } @@ -86,7 +87,7 @@ bool BigramDictionary::addWordBigram(unsigned short *word, int length, int frequ * prevWordLength: its length. * inputCodes: what user typed, in the same format as for UnigramDictionary::getSuggestions. * codesSize: the size of the codes array. - * bigramChars: an array for output, at the same format as outwords for getSuggestions. + * bigramCodePoints: an array for output, at the same format as outwords for getSuggestions. * bigramFreq: an array to output frequencies. * outputTypes: an array to output types. * This method returns the number of bigrams this word has, for backward compatibility. @@ -97,8 +98,8 @@ bool BigramDictionary::addWordBigram(unsigned short *word, int length, int frequ * and the bigrams are used to boost unigram result scores, it makes little sense to * reduce their scope to the ones that match the first letter. */ -int BigramDictionary::getBigrams(const int32_t *prevWord, int prevWordLength, int *inputCodes, - int codesSize, unsigned short *bigramChars, int *bigramFreq, int *outputTypes) const { +int BigramDictionary::getBigrams(const int *prevWord, int prevWordLength, int *inputCodes, + int codesSize, int *bigramCodePoints, int *bigramFreq, int *outputTypes) const { // TODO: remove unused arguments, and refrain from storing stuff in members of this class // TODO: have "in" arguments before "out" ones, and make out args explicit in the name @@ -117,7 +118,7 @@ int BigramDictionary::getBigrams(const int32_t *prevWord, int prevWordLength, in int bigramCount = 0; do { bigramFlags = BinaryFormat::getFlagsAndForwardPointer(root, &pos); - uint16_t bigramBuffer[MAX_WORD_LENGTH]; + int bigramBuffer[MAX_WORD_LENGTH]; int unigramFreq = 0; const int bigramPos = BinaryFormat::getAttributeAddressAndForwardPointer(root, bigramFlags, &pos); @@ -134,7 +135,7 @@ int BigramDictionary::getBigrams(const int32_t *prevWord, int prevWordLength, in // here, but it can't get too bad. const int frequency = BinaryFormat::computeFrequencyForBigram(unigramFreq, bigramFreqTemp); - if (addWordBigram(bigramBuffer, length, frequency, bigramFreq, bigramChars, + if (addWordBigram(bigramBuffer, length, frequency, bigramFreq, bigramCodePoints, outputTypes)) { ++bigramCount; } @@ -190,12 +191,12 @@ void BigramDictionary::fillBigramAddressToFrequencyMapAndFilter(const int32_t *p } while (0 != (BinaryFormat::FLAG_ATTRIBUTE_HAS_NEXT & bigramFlags)); } -bool BigramDictionary::checkFirstCharacter(unsigned short *word, int *inputCodes) const { +bool BigramDictionary::checkFirstCharacter(int *word, int *inputCodes) const { // Checks whether this word starts with same character or neighboring characters of // what user typed. int maxAlt = MAX_ALTERNATIVES; - const unsigned short firstBaseChar = toBaseLowerCase(*word); + const int firstBaseChar = toBaseLowerCase(*word); while (maxAlt > 0) { if (toBaseLowerCase(*inputCodes) == firstBaseChar) { return true; diff --git a/native/jni/src/bigram_dictionary.h b/native/jni/src/bigram_dictionary.h index 5f11ae822..150192de2 100644 --- a/native/jni/src/bigram_dictionary.h +++ b/native/jni/src/bigram_dictionary.h @@ -27,23 +27,23 @@ namespace latinime { class BigramDictionary { public: BigramDictionary(const unsigned char *dict, int maxWordLength, int maxPredictions); - int getBigrams(const int32_t *word, int length, int *inputCodes, int codesSize, - unsigned short *outWords, int *frequencies, int *outputTypes) const; - void fillBigramAddressToFrequencyMapAndFilter(const int32_t *prevWord, const int prevWordLength, + int getBigrams(const int *word, int length, int *inputCodes, int codesSize, int *outWords, + int *frequencies, int *outputTypes) const; + void fillBigramAddressToFrequencyMapAndFilter(const int *prevWord, const int prevWordLength, std::map *map, uint8_t *filter) const; - bool isValidBigram(const int32_t *word1, int length1, const int32_t *word2, int length2) const; + bool isValidBigram(const int *word1, int length1, const int *word2, int length2) const; ~BigramDictionary(); private: DISALLOW_IMPLICIT_CONSTRUCTORS(BigramDictionary); - bool addWordBigram(unsigned short *word, int length, int frequency, - int *bigramFreq, unsigned short *bigramChars, int *outputTypes) const; + bool addWordBigram(int *word, int length, int frequency, int *bigramFreq, int *bigramCodePoints, + int *outputTypes) const; int getBigramAddress(int *pos, bool advance); int getBigramFreq(int *pos); void searchForTerminalNode(int addressLookingFor, int frequency); bool getFirstBitOfByte(int *pos) { return (DICT[*pos] & 0x80) > 0; } bool getSecondBitOfByte(int *pos) { return (DICT[*pos] & 0x40) > 0; } - bool checkFirstCharacter(unsigned short *word, int *inputCodes) const; - int getBigramListPositionForWord(const int32_t *prevWord, const int prevWordLength, + bool checkFirstCharacter(int *word, int *inputCodes) const; + int getBigramListPositionForWord(const int *prevWord, const int prevWordLength, const bool forceLowerCaseSearch) const; const unsigned char *DICT; diff --git a/native/jni/src/binary_format.h b/native/jni/src/binary_format.h index eec52e323..c0aec50d7 100644 --- a/native/jni/src/binary_format.h +++ b/native/jni/src/binary_format.h @@ -84,7 +84,7 @@ class BinaryFormat { static unsigned int getFlags(const uint8_t *const dict); static int getGroupCountAndForwardPointer(const uint8_t *const dict, int *pos); static uint8_t getFlagsAndForwardPointer(const uint8_t *const dict, int *pos); - static int32_t getCodePointAndForwardPointer(const uint8_t *const dict, int *pos); + static int getCodePointAndForwardPointer(const uint8_t *const dict, int *pos); static int readFrequencyWithoutMovingPointer(const uint8_t *const dict, const int pos); static int skipOtherCharacters(const uint8_t *const dict, const int pos); static int skipChildrenPosition(const uint8_t flags, const int pos); @@ -98,10 +98,10 @@ class BinaryFormat { static int getAttributeAddressAndForwardPointer(const uint8_t *const dict, const uint8_t flags, int *pos); static int getAttributeFrequencyFromFlags(const int flags); - static int getTerminalPosition(const uint8_t *const root, const int32_t *const inWord, + static int getTerminalPosition(const uint8_t *const root, const int *const inWord, const int length, const bool forceLowerCaseSearch); static int getWordAtAddress(const uint8_t *const root, const int address, const int maxDepth, - uint16_t *outWord, int *outUnigramFrequency); + int *outWord, int *outUnigramFrequency); static int computeFrequencyForBigram(const int unigramFreq, const int bigramFreq); static int getProbability(const int position, const std::map *bigramMap, const uint8_t *bigramFilter, const int unigramFreq); @@ -176,17 +176,17 @@ inline uint8_t BinaryFormat::getFlagsAndForwardPointer(const uint8_t *const dict return dict[(*pos)++]; } -inline int32_t BinaryFormat::getCodePointAndForwardPointer(const uint8_t *const dict, int *pos) { +inline int BinaryFormat::getCodePointAndForwardPointer(const uint8_t *const dict, int *pos) { const int origin = *pos; - const int32_t codePoint = dict[origin]; + const int codePoint = dict[origin]; if (codePoint < MINIMAL_ONE_BYTE_CHARACTER_VALUE) { if (codePoint == CHARACTER_ARRAY_TERMINATOR) { *pos = origin + 1; return NOT_A_CODE_POINT; } else { *pos = origin + 3; - const int32_t char_1 = codePoint << 16; - const int32_t char_2 = char_1 + (dict[origin + 1] << 8); + const int char_1 = codePoint << 16; + const int char_2 = char_1 + (dict[origin + 1] << 8); return char_2 + dict[origin + 2]; } } else { @@ -202,7 +202,7 @@ inline int BinaryFormat::readFrequencyWithoutMovingPointer(const uint8_t *const inline int BinaryFormat::skipOtherCharacters(const uint8_t *const dict, const int pos) { int currentPos = pos; - int32_t character = dict[currentPos++]; + int character = dict[currentPos++]; while (CHARACTER_ARRAY_TERMINATOR != character) { if (character < MINIMAL_ONE_BYTE_CHARACTER_VALUE) { currentPos += MULTIPLE_BYTE_CHARACTER_ADDITIONAL_SIZE; @@ -352,8 +352,8 @@ inline int BinaryFormat::getAttributeFrequencyFromFlags(const int flags) { // This function gets the byte position of the last chargroup of the exact matching word in the // dictionary. If no match is found, it returns NOT_VALID_WORD. -inline int BinaryFormat::getTerminalPosition(const uint8_t *const root, - const int32_t *const inWord, const int length, const bool forceLowerCaseSearch) { +inline int BinaryFormat::getTerminalPosition(const uint8_t *const root, const int *const inWord, + const int length, const bool forceLowerCaseSearch) { int pos = 0; int wordPos = 0; @@ -362,14 +362,14 @@ inline int BinaryFormat::getTerminalPosition(const uint8_t *const root, // there was no match (or we would have found it). if (wordPos >= length) return NOT_VALID_WORD; int charGroupCount = BinaryFormat::getGroupCountAndForwardPointer(root, &pos); - const int32_t wChar = forceLowerCaseSearch ? toLowerCase(inWord[wordPos]) : inWord[wordPos]; + const int wChar = forceLowerCaseSearch ? toLowerCase(inWord[wordPos]) : inWord[wordPos]; while (true) { // If there are no more character groups in this node, it means we could not // find a matching character for this depth, therefore there is no match. if (0 >= charGroupCount) return NOT_VALID_WORD; const int charGroupPos = pos; const uint8_t flags = BinaryFormat::getFlagsAndForwardPointer(root, &pos); - int32_t character = BinaryFormat::getCodePointAndForwardPointer(root, &pos); + int character = BinaryFormat::getCodePointAndForwardPointer(root, &pos); if (character == wChar) { // This is the correct node. Only one character group may start with the same // char within a node, so either we found our match in this node, or there is @@ -439,7 +439,7 @@ inline int BinaryFormat::getTerminalPosition(const uint8_t *const root, * Return value : the length of the word, of 0 if the word was not found. */ inline int BinaryFormat::getWordAtAddress(const uint8_t *const root, const int address, - const int maxDepth, uint16_t *outWord, int *outUnigramFrequency) { + const int maxDepth, int *outWord, int *outUnigramFrequency) { int pos = 0; int wordPos = 0; @@ -457,13 +457,13 @@ inline int BinaryFormat::getWordAtAddress(const uint8_t *const root, const int a --charGroupCount) { const int startPos = pos; const uint8_t flags = getFlagsAndForwardPointer(root, &pos); - const int32_t character = getCodePointAndForwardPointer(root, &pos); + const int character = getCodePointAndForwardPointer(root, &pos); if (address == startPos) { // We found the address. Copy the rest of the word in the buffer and return // the length. outWord[wordPos] = character; if (FLAG_HAS_MULTIPLE_CHARS & flags) { - int32_t nextChar = getCodePointAndForwardPointer(root, &pos); + int nextChar = getCodePointAndForwardPointer(root, &pos); // We count chars in order to avoid infinite loops if the file is broken or // if there is some other bug int charCount = maxDepth; @@ -522,13 +522,12 @@ inline int BinaryFormat::getWordAtAddress(const uint8_t *const root, const int a if (0 != lastCandidateGroupPos) { const uint8_t lastFlags = getFlagsAndForwardPointer(root, &lastCandidateGroupPos); - const int32_t lastChar = + const int lastChar = getCodePointAndForwardPointer(root, &lastCandidateGroupPos); // We copy all the characters in this group to the buffer outWord[wordPos] = lastChar; if (FLAG_HAS_MULTIPLE_CHARS & lastFlags) { - int32_t nextChar = - getCodePointAndForwardPointer(root, &lastCandidateGroupPos); + int nextChar = getCodePointAndForwardPointer(root, &lastCandidateGroupPos); int charCount = maxDepth; while (-1 != nextChar && --charCount > 0) { outWord[++wordPos] = nextChar; diff --git a/native/jni/src/char_utils.h b/native/jni/src/char_utils.h index 9008e364c..b42de6607 100644 --- a/native/jni/src/char_utils.h +++ b/native/jni/src/char_utils.h @@ -18,22 +18,23 @@ #define LATINIME_CHAR_UTILS_H #include -#include + +#include "defines.h" namespace latinime { -inline static bool isAsciiUpper(unsigned short c) { +inline static bool isAsciiUpper(int c) { // Note: isupper(...) reports false positives for some Cyrillic characters, causing them to // be incorrectly lower-cased using toAsciiLower(...) rather than latin_tolower(...). return (c >= 'A' && c <= 'Z'); } -inline static unsigned short toAsciiLower(unsigned short c) { +inline static int toAsciiLower(int c) { return c - 'A' + 'a'; } -inline static bool isAscii(unsigned short c) { - return isascii(static_cast(c)) != 0; +inline static bool isAscii(int c) { + return isascii(c) != 0; } unsigned short latin_tolower(const unsigned short c); @@ -44,33 +45,32 @@ unsigned short latin_tolower(const unsigned short c); * if c is not a combined character, or the base character if it * is combined. */ - static const int BASE_CHARS_SIZE = 0x0500; -extern const uint16_t BASE_CHARS[BASE_CHARS_SIZE]; +extern const unsigned short BASE_CHARS[BASE_CHARS_SIZE]; -inline static unsigned short toBaseChar(unsigned short c) { +inline static int toBaseCodePoint(int c) { if (c < BASE_CHARS_SIZE) { - return BASE_CHARS[c]; + return static_cast(BASE_CHARS[c]); } return c; } -inline static unsigned short toLowerCase(const unsigned short c) { +inline static int toLowerCase(const int c) { if (isAsciiUpper(c)) { return toAsciiLower(c); } else if (isAscii(c)) { return c; } - return latin_tolower(c); + return static_cast(latin_tolower(static_cast(c))); } -inline static unsigned short toBaseLowerCase(const unsigned short c) { - return toLowerCase(toBaseChar(c)); +inline static int toBaseLowerCase(const int c) { + return toLowerCase(toBaseCodePoint(c)); } -inline static bool isSkippableChar(const uint16_t character) { +inline static bool isSkippableCodePoint(const int codePoint) { // TODO: Do not hardcode here - return character == '\'' || character == '-'; + return codePoint == KEYCODE_SINGLE_QUOTE || codePoint == KEYCODE_HYPHEN_MINUS; } } // namespace latinime diff --git a/native/jni/src/correction.cpp b/native/jni/src/correction.cpp index d57b0e370..949158a0b 100644 --- a/native/jni/src/correction.cpp +++ b/native/jni/src/correction.cpp @@ -60,8 +60,8 @@ inline static void dumpEditDistance10ForDebug(int *editDistanceTable, } } -inline static void calcEditDistanceOneStep(int *editDistanceTable, const unsigned short *input, - const int inputSize, const unsigned short *output, const int outputLength) { +inline static void calcEditDistanceOneStep(int *editDistanceTable, const int *input, + const int inputSize, const int *output, const int outputLength) { // TODO: Make sure that editDistance[0 ~ MAX_WORD_LENGTH_INTERNAL] is not touched. // Let dp[i][j] be editDistanceTable[i * (inputSize + 1) + j]. // Assuming that dp[0][0] ... dp[outputLength - 1][inputSize] are already calculated, @@ -71,10 +71,10 @@ inline static void calcEditDistanceOneStep(int *editDistanceTable, const unsigne const int *const prevprev = outputLength >= 2 ? editDistanceTable + (outputLength - 2) * (inputSize + 1) : 0; current[0] = outputLength; - const uint32_t co = toBaseLowerCase(output[outputLength - 1]); - const uint32_t prevCO = outputLength >= 2 ? toBaseLowerCase(output[outputLength - 2]) : 0; + const int co = toBaseLowerCase(output[outputLength - 1]); + const int prevCO = outputLength >= 2 ? toBaseLowerCase(output[outputLength - 2]) : 0; for (int i = 1; i <= inputSize; ++i) { - const uint32_t ci = toBaseLowerCase(input[i - 1]); + const int ci = toBaseLowerCase(input[i - 1]); const uint16_t cost = (ci == co) ? 0 : 1; current[i] = min(current[i - 1] + 1, min(prev[i] + 1, prev[i - 1] + cost)); if (i >= 2 && prevprev && ci == prevCO && co == toBaseLowerCase(input[i - 2])) { @@ -94,11 +94,9 @@ inline static int getCurrentEditDistance(int *editDistanceTable, const int editD ////////////////////// // inline functions // ////////////////////// -static const char SINGLE_QUOTE = '\''; - -inline bool Correction::isSingleQuote(const unsigned short c) { - const unsigned short userTypedChar = mProximityInfoState.getPrimaryCharAt(mInputIndex); - return (c == SINGLE_QUOTE && userTypedChar != SINGLE_QUOTE); +inline bool Correction::isSingleQuote(const int c) { + const int userTypedChar = mProximityInfoState.getPrimaryCodePointAt(mInputIndex); + return (c == KEYCODE_SINGLE_QUOTE && userTypedChar != KEYCODE_SINGLE_QUOTE); } //////////////// @@ -162,22 +160,22 @@ bool Correction::sameAsTyped() { } int Correction::getFreqForSplitMultipleWords(const int *freqArray, const int *wordLengthArray, - const int wordCount, const bool isSpaceProximity, const unsigned short *word) { + const int wordCount, const bool isSpaceProximity, const int *word) { return Correction::RankingAlgorithm::calcFreqForSplitMultipleWords(freqArray, wordLengthArray, wordCount, this, isSpaceProximity, word); } -int Correction::getFinalProbability(const int probability, unsigned short **word, int *wordLength) { +int Correction::getFinalProbability(const int probability, int **word, int *wordLength) { return getFinalProbabilityInternal(probability, word, wordLength, mInputSize); } -int Correction::getFinalProbabilityForSubQueue(const int probability, unsigned short **word, - int *wordLength, const int inputSize) { +int Correction::getFinalProbabilityForSubQueue(const int probability, int **word, int *wordLength, + const int inputSize) { return getFinalProbabilityInternal(probability, word, wordLength, inputSize); } -int Correction::getFinalProbabilityInternal(const int probability, unsigned short **word, - int *wordLength, const int inputSize) { +int Correction::getFinalProbabilityInternal(const int probability, int **word, int *wordLength, + const int inputSize) { const int outputIndex = mTerminalOutputIndex; const int inputIndex = mTerminalInputIndex; *wordLength = outputIndex + 1; @@ -273,15 +271,15 @@ bool Correction::needsToPrune() const { || (!mDoAutoCompletion && (mOutputIndex > mInputSize)); } -void Correction::addCharToCurrentWord(const int32_t c) { +void Correction::addCharToCurrentWord(const int c) { mWord[mOutputIndex] = c; - const unsigned short *primaryInputWord = mProximityInfoState.getPrimaryInputWord(); - calcEditDistanceOneStep(mEditDistanceTable, primaryInputWord, mInputSize, - mWord, mOutputIndex + 1); + const int *primaryInputWord = mProximityInfoState.getPrimaryInputWord(); + calcEditDistanceOneStep(mEditDistanceTable, primaryInputWord, mInputSize, mWord, + mOutputIndex + 1); } -Correction::CorrectionType Correction::processSkipChar( - const int32_t c, const bool isTerminal, const bool inputIndexIncremented) { +Correction::CorrectionType Correction::processSkipChar(const int c, const bool isTerminal, + const bool inputIndexIncremented) { addCharToCurrentWord(c); mTerminalInputIndex = mInputIndex - (inputIndexIncremented ? 1 : 0); mTerminalOutputIndex = mOutputIndex; @@ -309,8 +307,7 @@ inline bool isProximityCharOrEquivalentChar(ProximityType type) { return type == EQUIVALENT_CHAR || type == NEAR_PROXIMITY_CHAR; } -Correction::CorrectionType Correction::processCharAndCalcState( - const int32_t c, const bool isTerminal) { +Correction::CorrectionType Correction::processCharAndCalcState(const int c, const bool isTerminal) { const int correctionCount = (mSkippedCount + mExcessiveCount + mTransposedCount); if (correctionCount > mMaxErrors) { return processUnrelatedCorrectionType(); @@ -628,10 +625,10 @@ Correction::CorrectionType Correction::processCharAndCalcState( } } -inline static int getQuoteCount(const unsigned short *word, const int length) { +inline static int getQuoteCount(const int *word, const int length) { int quoteCount = 0; for (int i = 0; i < length; ++i) { - if (word[i] == SINGLE_QUOTE) { + if (word[i] == KEYCODE_SINGLE_QUOTE) { ++quoteCount; } } @@ -639,7 +636,7 @@ inline static int getQuoteCount(const unsigned short *word, const int length) { } inline static bool isUpperCase(unsigned short c) { - return isAsciiUpper(toBaseChar(c)); + return isAsciiUpper(toBaseCodePoint(c)); } ////////////////////// @@ -672,7 +669,7 @@ int Correction::RankingAlgorithm::calculateFinalProbability(const int inputIndex // TODO: use mExcessiveCount const int matchCount = inputSize - correction->mProximityCount - excessiveCount; - const unsigned short *word = correction->mWord; + const int *word = correction->mWord; const bool skipped = skippedCount > 0; const int quoteDiffCount = max(0, getQuoteCount(word, outputLength) @@ -911,7 +908,7 @@ int Correction::RankingAlgorithm::calculateFinalProbability(const int inputIndex /* static */ int Correction::RankingAlgorithm::calcFreqForSplitMultipleWords( const int *freqArray, const int *wordLengthArray, const int wordCount, - const Correction *correction, const bool isSpaceProximity, const unsigned short *word) { + const Correction *correction, const bool isSpaceProximity, const int *word) { const int typedLetterMultiplier = correction->TYPED_LETTER_MULTIPLIER; bool firstCapitalizedWordDemotion = false; @@ -1040,9 +1037,8 @@ int Correction::RankingAlgorithm::calcFreqForSplitMultipleWords( } /* Damerau-Levenshtein distance */ -inline static int editDistanceInternal( - int *editDistanceTable, const unsigned short *before, - const int beforeLength, const unsigned short *after, const int afterLength) { +inline static int editDistanceInternal(int *editDistanceTable, const int *before, + const int beforeLength, const int *after, const int afterLength) { // dp[li][lo] dp[a][b] = dp[ a * lo + b] int *dp = editDistanceTable; const int li = beforeLength + 1; @@ -1056,9 +1052,9 @@ inline static int editDistanceInternal( for (int i = 0; i < li - 1; ++i) { for (int j = 0; j < lo - 1; ++j) { - const uint32_t ci = toBaseLowerCase(before[i]); - const uint32_t co = toBaseLowerCase(after[j]); - const uint16_t cost = (ci == co) ? 0 : 1; + const int ci = toBaseLowerCase(before[i]); + const int co = toBaseLowerCase(after[j]); + const int cost = (ci == co) ? 0 : 1; dp[(i + 1) * lo + (j + 1)] = min(dp[i * lo + (j + 1)] + 1, min(dp[(i + 1) * lo + j] + 1, dp[i * lo + j] + cost)); if (i > 0 && j > 0 && ci == toBaseLowerCase(after[j - 1]) @@ -1080,8 +1076,8 @@ inline static int editDistanceInternal( return dp[li * lo - 1]; } -int Correction::RankingAlgorithm::editDistance(const unsigned short *before, - const int beforeLength, const unsigned short *after, const int afterLength) { +int Correction::RankingAlgorithm::editDistance(const int *before, const int beforeLength, + const int *after, const int afterLength) { int table[(beforeLength + 1) * (afterLength + 1)]; return editDistanceInternal(table, before, beforeLength, after, afterLength); } @@ -1109,9 +1105,8 @@ int Correction::RankingAlgorithm::editDistance(const unsigned short *before, // So, we can normalize original score by dividing powf(2, min(b.l(),a.l())) * 255 * 2. /* static */ -float Correction::RankingAlgorithm::calcNormalizedScore(const unsigned short *before, - const int beforeLength, const unsigned short *after, const int afterLength, - const int score) { +float Correction::RankingAlgorithm::calcNormalizedScore(const int *before, const int beforeLength, + const int *after, const int afterLength, const int score) { if (0 == beforeLength || 0 == afterLength) { return 0; } diff --git a/native/jni/src/correction.h b/native/jni/src/correction.h index a099853e6..fff24b048 100644 --- a/native/jni/src/correction.h +++ b/native/jni/src/correction.h @@ -78,14 +78,13 @@ class Correction { return ++mTotalTraverseCount; } - int getFreqForSplitMultipleWords( - const int *freqArray, const int *wordLengthArray, const int wordCount, - const bool isSpaceProximity, const unsigned short *word); - int getFinalProbability(const int probability, unsigned short **word, int *wordLength); - int getFinalProbabilityForSubQueue(const int probability, unsigned short **word, - int *wordLength, const int inputSize); + int getFreqForSplitMultipleWords(const int *freqArray, const int *wordLengthArray, + const int wordCount, const bool isSpaceProximity, const int *word); + int getFinalProbability(const int probability, int **word, int *wordLength); + int getFinalProbabilityForSubQueue(const int probability, int **word, int *wordLength, + const int inputSize); - CorrectionType processCharAndCalcState(const int32_t c, const bool isTerminal); + CorrectionType processCharAndCalcState(const int c, const bool isTerminal); ///////////////////////// // Tree helper methods @@ -110,28 +109,28 @@ class Correction { const int inputSize); static int calcFreqForSplitMultipleWords(const int *freqArray, const int *wordLengthArray, const int wordCount, const Correction *correction, const bool isSpaceProximity, - const unsigned short *word); - static float calcNormalizedScore(const unsigned short *before, const int beforeLength, - const unsigned short *after, const int afterLength, const int score); - static int editDistance(const unsigned short *before, - const int beforeLength, const unsigned short *after, const int afterLength); + const int *word); + static float calcNormalizedScore(const int *before, const int beforeLength, + const int *after, const int afterLength, const int score); + static int editDistance(const int *before, const int beforeLength, const int *after, + const int afterLength); private: static const int MAX_INITIAL_SCORE = 255; }; // proximity info state - void initInputParams(const ProximityInfo *proximityInfo, const int32_t *inputCodes, + void initInputParams(const ProximityInfo *proximityInfo, const int *inputCodes, const int inputSize, const int *xCoordinates, const int *yCoordinates) { mProximityInfoState.initInputParams(0, MAX_POINT_TO_KEY_LENGTH, proximityInfo, inputCodes, inputSize, xCoordinates, yCoordinates, 0, 0, false); } - const unsigned short *getPrimaryInputWord() const { + const int *getPrimaryInputWord() const { return mProximityInfoState.getPrimaryInputWord(); } - unsigned short getPrimaryCharAt(const int index) const { - return mProximityInfoState.getPrimaryCharAt(index); + int getPrimaryCodePointAt(const int index) const { + return mProximityInfoState.getPrimaryCodePointAt(index); } private: @@ -214,13 +213,13 @@ class Correction { inline void incrementInputIndex(); inline void incrementOutputIndex(); inline void startToTraverseAllNodes(); - inline bool isSingleQuote(const unsigned short c); - inline CorrectionType processSkipChar( - const int32_t c, const bool isTerminal, const bool inputIndexIncremented); + inline bool isSingleQuote(const int c); + inline CorrectionType processSkipChar(const int c, const bool isTerminal, + const bool inputIndexIncremented); inline CorrectionType processUnrelatedCorrectionType(); - inline void addCharToCurrentWord(const int32_t c); - inline int getFinalProbabilityInternal(const int probability, unsigned short **word, - int *wordLength, const int inputSize); + inline void addCharToCurrentWord(const int c); + inline int getFinalProbabilityInternal(const int probability, int **word, int *wordLength, + const int inputSize); static const int TYPED_LETTER_MULTIPLIER = 2; static const int FULL_WORD_MULTIPLIER = 2; @@ -240,7 +239,7 @@ class Correction { uint8_t mTotalTraverseCount; // The following arrays are state buffer. - unsigned short mWord[MAX_WORD_LENGTH_INTERNAL]; + int mWord[MAX_WORD_LENGTH_INTERNAL]; int mDistances[MAX_WORD_LENGTH_INTERNAL]; // Edit distance calculation requires a buffer with (N+1)^2 length for the input length N. diff --git a/native/jni/src/defines.h b/native/jni/src/defines.h index 942068a49..095487416 100644 --- a/native/jni/src/defines.h +++ b/native/jni/src/defines.h @@ -30,17 +30,15 @@ #define DUMP_RESULT(words, frequencies, maxWordCount, maxWordLength) do { \ dumpResult(words, frequencies, maxWordCount, maxWordLength); } while (0) #define DUMP_WORD(word, length) do { dumpWord(word, length); } while (0) -#define DUMP_WORD_INT(word, length) do { dumpWordInt(word, length); } while (0) -// TODO: INTS_TO_CHARS -#define SHORTS_TO_CHARS(input, length, output) do { \ - shortArrayToCharArray(input, length, output); } while (0) +#define INTS_TO_CHARS(input, length, output) do { \ + intArrayToCharArray(input, length, output); } while (0) -static inline void dumpWordInfo(const unsigned short *word, const int length, - const int rank, const int frequency) { +static inline void dumpWordInfo(const int *word, const int length, const int rank, + const int frequency) { static char charBuf[50]; int i = 0; for (; i < length; ++i) { - const unsigned short c = word[i]; + const int c = word[i]; if (c == 0) { break; } @@ -53,8 +51,7 @@ static inline void dumpWordInfo(const unsigned short *word, const int length, } } -static inline void dumpResult( - const unsigned short *outWords, const int *frequencies, const int maxWordCounts, +static inline void dumpResult(const int *outWords, const int *frequencies, const int maxWordCounts, const int maxWordLength) { AKLOGI("--- DUMP RESULT ---------"); for (int i = 0; i < maxWordCounts; ++i) { @@ -63,11 +60,11 @@ static inline void dumpResult( AKLOGI("-------------------------"); } -static inline void dumpWord(const unsigned short *word, const int length) { +static inline void dumpWord(const int *word, const int length) { static char charBuf[50]; int i = 0; for (; i < length; ++i) { - const unsigned short c = word[i]; + const int c = word[i]; if (c == 0) { break; } @@ -80,22 +77,10 @@ static inline void dumpWord(const unsigned short *word, const int length) { } } -static inline void dumpWordInt(const int *word, const int length) { - static char charBuf[50]; - - for (int i = 0; i < length; ++i) { - charBuf[i] = word[i]; - } - charBuf[length] = 0; - AKLOGI("i[ %s ]", charBuf); -} - -// TODO: Change this to intArrayToCharArray -static inline void shortArrayToCharArray( - const unsigned short *input, const int length, char *output) { +static inline void intArrayToCharArray(const int *input, const int length, char *output) { int i = 0; - for (;i < length; ++i) { - const unsigned short c = input[i]; + for (; i < length; ++i) { + const int c = input[i]; if (c == 0) { break; } @@ -137,11 +122,9 @@ static inline void showStackTrace() { #define AKLOGI(fmt, ...) #define DUMP_RESULT(words, frequencies, maxWordCount, maxWordLength) #define DUMP_WORD(word, length) -#define DUMP_WORD_INT(word, length) #define ASSERT(success) #define SHOW_STACK_TRACE -// TODO: INTS_TO_CHARS -#define SHORTS_TO_CHARS(input, length, output) +#define INTS_TO_CHARS(input, length, output) #endif #ifdef FLAG_DO_PROFILE @@ -286,6 +269,8 @@ static inline void prof_out(void) { #define NOT_A_PROBABILITY (-1) #define KEYCODE_SPACE ' ' +#define KEYCODE_SINGLE_QUOTE '\'' +#define KEYCODE_HYPHEN_MINUS '-' #define CALIBRATE_SCORE_BY_TOUCH_COORDINATES true diff --git a/native/jni/src/dictionary.cpp b/native/jni/src/dictionary.cpp index 81789ccfc..5fbe0461b 100644 --- a/native/jni/src/dictionary.cpp +++ b/native/jni/src/dictionary.cpp @@ -54,11 +54,10 @@ Dictionary::~Dictionary() { } int Dictionary::getSuggestions(ProximityInfo *proximityInfo, void *traverseSession, - int *xcoordinates, int *ycoordinates, int *times, int *pointerIds, - int *codes, int codesSize, int *prevWordChars, - int prevWordLength, int commitPoint, bool isGesture, - bool useFullEditDistance, unsigned short *outWords, - int *frequencies, int *spaceIndices, int *outputTypes) const { + int *xcoordinates, int *ycoordinates, int *times, int *pointerIds, int *codes, + int codesSize, int *prevWordChars, int prevWordLength, int commitPoint, bool isGesture, + bool useFullEditDistance, int *outWords, int *frequencies, int *spaceIndices, + int *outputTypes) const { int result = 0; if (isGesture) { DicTraverseWrapper::initDicTraverseSession( @@ -83,7 +82,7 @@ int Dictionary::getSuggestions(ProximityInfo *proximityInfo, void *traverseSessi } int Dictionary::getBigrams(const int32_t *word, int length, int *codes, int codesSize, - unsigned short *outWords, int *frequencies, int *outputTypes) const { + int *outWords, int *frequencies, int *outputTypes) const { if (length <= 0) return 0; return mBigramDictionary->getBigrams(word, length, codes, codesSize, outWords, frequencies, outputTypes); diff --git a/native/jni/src/dictionary.h b/native/jni/src/dictionary.h index 120ca5f7f..2ca00ab63 100644 --- a/native/jni/src/dictionary.h +++ b/native/jni/src/dictionary.h @@ -47,11 +47,11 @@ class Dictionary { int getSuggestions(ProximityInfo *proximityInfo, void *traverseSession, int *xcoordinates, int *ycoordinates, int *times, int *pointerIds, int *codes, int codesSize, int *prevWordChars, int prevWordLength, int commitPoint, bool isGesture, - bool useFullEditDistance, unsigned short *outWords, - int *frequencies, int *spaceIndices, int *outputTypes) const; + bool useFullEditDistance, int *outWords, int *frequencies, int *spaceIndices, + int *outputTypes) const; - int getBigrams(const int32_t *word, int length, int *codes, int codesSize, - unsigned short *outWords, int *frequencies, int *outputTypes) const; + int getBigrams(const int32_t *word, int length, int *codes, int codesSize, int *outWords, + int *frequencies, int *outputTypes) const; int getFrequency(const int32_t *word, int length) const; bool isValidBigram(const int32_t *word1, int length1, const int32_t *word2, int length2) const; @@ -68,7 +68,7 @@ class Dictionary { // public static utility methods // static inline methods should be defined in the header file - static int wideStrLen(unsigned short *str); + static int wideStrLen(int *str); private: DISALLOW_IMPLICIT_CONSTRUCTORS(Dictionary); @@ -88,7 +88,7 @@ class Dictionary { // public static utility methods // static inline methods should be defined in the header file -inline int Dictionary::wideStrLen(unsigned short *str) { +inline int Dictionary::wideStrLen(int *str) { if (!str) return 0; int length = 0; while (*str) { diff --git a/native/jni/src/gesture/gesture_decoder_wrapper.h b/native/jni/src/gesture/gesture_decoder_wrapper.h index 92e1ded49..eb80bd2e2 100644 --- a/native/jni/src/gesture/gesture_decoder_wrapper.h +++ b/native/jni/src/gesture/gesture_decoder_wrapper.h @@ -38,15 +38,14 @@ class GestureDecoderWrapper : public IncrementalDecoderInterface { } int getSuggestions(ProximityInfo *pInfo, void *traverseSession, int *inputXs, int *inputYs, - int *times, int *pointerIds, int *codes, int inputSize, int commitPoint, - unsigned short *outWords, int *frequencies, int *outputIndices, - int *outputTypes) const { + int *times, int *pointerIds, int *codes, int inputSize, int commitPoint, int *outWords, + int *frequencies, int *outputIndices, int *outputTypes) const { if (!mIncrementalDecoderInterface) { return 0; } - return mIncrementalDecoderInterface->getSuggestions( - pInfo, traverseSession, inputXs, inputYs, times, pointerIds, codes, - inputSize, commitPoint, outWords, frequencies, outputIndices, outputTypes); + return mIncrementalDecoderInterface->getSuggestions(pInfo, traverseSession, inputXs, + inputYs, times, pointerIds, codes, inputSize, commitPoint, outWords, frequencies, + outputIndices, outputTypes); } static void setGestureDecoderFactoryMethod( diff --git a/native/jni/src/gesture/incremental_decoder_interface.h b/native/jni/src/gesture/incremental_decoder_interface.h index d1395aab9..e41513dbc 100644 --- a/native/jni/src/gesture/incremental_decoder_interface.h +++ b/native/jni/src/gesture/incremental_decoder_interface.h @@ -28,10 +28,9 @@ class ProximityInfo; class IncrementalDecoderInterface { public: - virtual int getSuggestions(ProximityInfo *pInfo, void *traverseSession, - int *inputXs, int *inputYs, int *times, int *pointerIds, int *codes, - int inputSize, int commitPoint, unsigned short *outWords, int *frequencies, - int *outputIndices, int *outputTypes) const = 0; + virtual int getSuggestions(ProximityInfo *pInfo, void *traverseSession, int *inputXs, + int *inputYs, int *times, int *pointerIds, int *codes, int inputSize, int commitPoint, + int *outWords, int *frequencies, int *outputIndices, int *outputTypes) const = 0; IncrementalDecoderInterface() { }; virtual ~IncrementalDecoderInterface() { }; private: diff --git a/native/jni/src/gesture/incremental_decoder_wrapper.h b/native/jni/src/gesture/incremental_decoder_wrapper.h index da7afdb8a..691d4952d 100644 --- a/native/jni/src/gesture/incremental_decoder_wrapper.h +++ b/native/jni/src/gesture/incremental_decoder_wrapper.h @@ -38,15 +38,14 @@ class IncrementalDecoderWrapper : public IncrementalDecoderInterface { } int getSuggestions(ProximityInfo *pInfo, void *traverseSession, int *inputXs, int *inputYs, - int *times, int *pointerIds, int *codes, int inputSize, int commitPoint, - unsigned short *outWords, int *frequencies, int *outputIndices, - int *outputTypes) const { + int *times, int *pointerIds, int *codes, int inputSize, int commitPoint, int *outWords, + int *frequencies, int *outputIndices, int *outputTypes) const { if (!mIncrementalDecoderInterface) { return 0; } - return mIncrementalDecoderInterface->getSuggestions( - pInfo, traverseSession, inputXs, inputYs, times, pointerIds, codes, - inputSize, commitPoint, outWords, frequencies, outputIndices, outputTypes); + return mIncrementalDecoderInterface->getSuggestions(pInfo, traverseSession, inputXs, + inputYs, times, pointerIds, codes, inputSize, commitPoint, outWords, frequencies, + outputIndices, outputTypes); } static void setIncrementalDecoderFactoryMethod( diff --git a/native/jni/src/proximity_info_state.cpp b/native/jni/src/proximity_info_state.cpp index d41acdace..987a27b80 100644 --- a/native/jni/src/proximity_info_state.cpp +++ b/native/jni/src/proximity_info_state.cpp @@ -34,7 +34,7 @@ const float ProximityInfoState::NOT_A_DISTANCE_FLOAT = -1.0f; const int ProximityInfoState::NOT_A_CODE = -1; void ProximityInfoState::initInputParams(const int pointerId, const float maxPointToKeyLength, - const ProximityInfo *proximityInfo, const int32_t *const inputCodes, const int inputSize, + 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) { @@ -63,7 +63,7 @@ void ProximityInfoState::initInputParams(const int pointerId, const float maxPoi // - mNormalizedSquaredDistances // TODO: Merge for (int i = 0; i < inputSize; ++i) { - const int32_t primaryKey = inputCodes[i]; + const int primaryKey = inputCodes[i]; const int x = xCoordinates[i]; const int y = yCoordinates[i]; int *proximities = &mInputCodes[i * MAX_PROXIMITY_CHARS_SIZE_INTERNAL]; @@ -146,7 +146,7 @@ void ProximityInfoState::initInputParams(const int pointerId, const float maxPoi AKLOGI("Init ProximityInfoState: (%d)PID = %d", i, pid); } if (pointerId == pid) { - const int c = isGeometric ? NOT_A_COORDINATE : getPrimaryCharAt(i); + const int c = isGeometric ? NOT_A_COORDINATE : getPrimaryCodePointAt(i); const int x = proximityOnly ? NOT_A_COORDINATE : xCoordinates[i]; const int y = proximityOnly ? NOT_A_COORDINATE : yCoordinates[i]; const int time = times ? times[i] : -1; @@ -306,12 +306,12 @@ void ProximityInfoState::initInputParams(const int pointerId, const float maxPoi && xCoordinates && yCoordinates; if (!isGeometric && pointerId == 0) { for (int i = 0; i < inputSize; ++i) { - mPrimaryInputWord[i] = getPrimaryCharAt(i); + mPrimaryInputWord[i] = getPrimaryCodePointAt(i); } for (int i = 0; i < mInputSize && mTouchPositionCorrectionEnabled; ++i) { - const int *proximityChars = getProximityCharsAt(i); - const int primaryKey = proximityChars[0]; + const int *proximityCodePoints = getProximityCodePointsAt(i); + const int primaryKey = proximityCodePoints[0]; const int x = xCoordinates[i]; const int y = yCoordinates[i]; if (DEBUG_PROXIMITY_CHARS) { @@ -319,11 +319,12 @@ void ProximityInfoState::initInputParams(const int pointerId, const float maxPoi 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]; + for (int j = 0; j < MAX_PROXIMITY_CHARS_SIZE_INTERNAL && proximityCodePoints[j] > 0; + ++j) { + const int currentCodePoint = proximityCodePoints[j]; const float squaredDistance = hasInputCoordinates() ? calculateNormalizedSquaredDistance( - mProximityInfo->getKeyIndexOf(currentChar), i) : + mProximityInfo->getKeyIndexOf(currentCodePoint), i) : NOT_A_DISTANCE_FLOAT; if (squaredDistance >= 0.0f) { mNormalizedSquaredDistances[i * MAX_PROXIMITY_CHARS_SIZE_INTERNAL + j] = @@ -334,7 +335,7 @@ void ProximityInfoState::initInputParams(const int pointerId, const float maxPoi PROXIMITY_CHAR_WITHOUT_DISTANCE_INFO; } if (DEBUG_PROXIMITY_CHARS) { - AKLOGI("--- Proximity (%d) = %c", j, currentChar); + AKLOGI("--- Proximity (%d) = %c", j, currentCodePoint); } } } @@ -449,7 +450,7 @@ float ProximityInfoState::getPointScore( // Sampling touch point and pushing information to vectors. // Returning if previous point is popped or not. -bool ProximityInfoState::pushTouchPoint(const int inputIndex, const int nodeChar, int x, int y, +bool ProximityInfoState::pushTouchPoint(const int inputIndex, const int nodeCodePoint, int x, int y, const int time, const bool sample, const bool isLastPoint, const float sumAngle, NearKeysDistanceMap *const currentNearKeysDistances, const NearKeysDistanceMap *const prevNearKeysDistances, @@ -458,7 +459,7 @@ bool ProximityInfoState::pushTouchPoint(const int inputIndex, const int nodeChar size_t size = mInputXs.size(); bool popped = false; - if (nodeChar < 0 && sample) { + if (nodeCodePoint < 0 && sample) { const float nearest = updateNearKeysDistances(x, y, currentNearKeysDistances); const float score = getPointScore(x, y, time, isLastPoint, nearest, sumAngle, currentNearKeysDistances, prevNearKeysDistances, prevPrevNearKeysDistances); @@ -487,8 +488,8 @@ bool ProximityInfoState::pushTouchPoint(const int inputIndex, const int nodeChar } } - if (nodeChar >= 0 && (x < 0 || y < 0)) { - const int keyId = mProximityInfo->getKeyIndexOf(nodeChar); + if (nodeCodePoint >= 0 && (x < 0 || y < 0)) { + const int keyId = mProximityInfo->getKeyIndexOf(nodeCodePoint); if (keyId >= 0) { x = mProximityInfo->getKeyCenterXOfKeyIdG(keyId); y = mProximityInfo->getKeyCenterYOfKeyIdG(keyId); @@ -543,7 +544,7 @@ float ProximityInfoState::getPointToKeyLength(const int inputIndex, const int co const int index = inputIndex * mProximityInfo->getKeyCount() + keyId; return min(mDistanceCache[index], mMaxPointToKeyLength); } - if (isSkippableChar(codePoint)) { + if (isSkippableCodePoint(codePoint)) { return 0.0f; } // If the char is not a key on the keyboard then return the max length. @@ -960,9 +961,9 @@ bool ProximityInfoState::suppressCharProbabilities(const int index0, const int i return true; } -// Get a word that is detected by tracing highest probability sequence into charBuf and returns -// probability of generating the word. -float ProximityInfoState::getHighestProbabilitySequence(uint16_t *const charBuf) const { +// Get a word that is detected by tracing highest probability sequence into codePointBuf and +// returns probability of generating the word. +float ProximityInfoState::getHighestProbabilitySequence(int *const codePointBuf) const { static const float DEMOTION_LOG_PROBABILITY = 0.3f; int index = 0; float sumLogProbability = 0.0f; @@ -980,12 +981,12 @@ float ProximityInfoState::getHighestProbabilitySequence(uint16_t *const charBuf) } } if (character != NOT_AN_INDEX) { - charBuf[index] = mProximityInfo->getCodePointOf(character); + codePointBuf[index] = mProximityInfo->getCodePointOf(character); index++; } sumLogProbability += minLogProbability; } - charBuf[index] = '\0'; + codePointBuf[index] = '\0'; return sumLogProbability; } diff --git a/native/jni/src/proximity_info_state.h b/native/jni/src/proximity_info_state.h index 1a3f2869d..14fe2d3f5 100644 --- a/native/jni/src/proximity_info_state.h +++ b/native/jni/src/proximity_info_state.h @@ -43,7 +43,7 @@ class ProximityInfoState { // Defined in proximity_info_state.cpp // ///////////////////////////////////////// void initInputParams(const int pointerId, const float maxPointToKeyLength, - const ProximityInfo *proximityInfo, const int32_t *const inputCodes, + const ProximityInfo *proximityInfo, const int *const inputCodes, const int inputSize, const int *xCoordinates, const int *yCoordinates, const int *const times, const int *const pointerIds, const bool isGeometric); @@ -65,15 +65,15 @@ class ProximityInfoState { virtual ~ProximityInfoState() {} - inline unsigned short getPrimaryCharAt(const int index) const { - return getProximityCharsAt(index)[0]; + inline int getPrimaryCodePointAt(const int index) const { + return getProximityCodePointsAt(index)[0]; } - inline bool existsCharInProximityAt(const int index, const int c) const { - const int *chars = getProximityCharsAt(index); + inline bool existsCodePointInProximityAt(const int index, const int c) const { + const int *codePoints = getProximityCodePointsAt(index); int i = 0; - while (chars[i] > 0 && i < MAX_PROXIMITY_CHARS_SIZE_INTERNAL) { - if (chars[i++] == c) { + while (codePoints[i] > 0 && i < MAX_PROXIMITY_CHARS_SIZE_INTERNAL) { + if (codePoints[i++] == c) { return true; } } @@ -82,13 +82,13 @@ class ProximityInfoState { inline bool existsAdjacentProximityChars(const int index) const { if (index < 0 || index >= mInputSize) return false; - const int currentChar = getPrimaryCharAt(index); + const int currentCodePoint = getPrimaryCodePointAt(index); const int leftIndex = index - 1; - if (leftIndex >= 0 && existsCharInProximityAt(leftIndex, currentChar)) { + if (leftIndex >= 0 && existsCodePointInProximityAt(leftIndex, currentCodePoint)) { return true; } const int rightIndex = index + 1; - if (rightIndex < mInputSize && existsCharInProximityAt(rightIndex, currentChar)) { + if (rightIndex < mInputSize && existsCodePointInProximityAt(rightIndex, currentCodePoint)) { return true; } return false; @@ -106,15 +106,15 @@ class ProximityInfoState { // 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); + inline ProximityType getMatchedProximityId(const int index, const int c, + const bool checkProximityChars, int *proximityIndex = 0) const { + const int *currentCodePoints = getProximityCodePointsAt(index); + const int firstCodePoint = currentCodePoints[0]; + const int 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) { + if (firstCodePoint == baseLowerC || firstCodePoint == c) { return EQUIVALENT_CHAR; } @@ -123,14 +123,14 @@ class ProximityInfoState { // 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) + if (toBaseLowerCase(firstCodePoint) == 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); + && currentCodePoints[j] > ADDITIONAL_PROXIMITY_CHAR_DELIMITER_CODE) { + const bool matched = (currentCodePoints[j] == baseLowerC || currentCodePoints[j] == c); if (matched) { if (proximityIndex) { *proximityIndex = j; @@ -140,11 +140,12 @@ class ProximityInfoState { ++j; } if (j < MAX_PROXIMITY_CHARS_SIZE_INTERNAL - && currentChars[j] == ADDITIONAL_PROXIMITY_CHAR_DELIMITER_CODE) { + && currentCodePoints[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); + && currentCodePoints[j] > ADDITIONAL_PROXIMITY_CHAR_DELIMITER_CODE) { + const bool matched = + (currentCodePoints[j] == baseLowerC || currentCodePoints[j] == c); if (matched) { if (proximityIndex) { *proximityIndex = j; @@ -165,7 +166,7 @@ class ProximityInfoState { inputIndex * MAX_PROXIMITY_CHARS_SIZE_INTERNAL + proximityIndex]; } - inline const unsigned short *getPrimaryInputWord() const { + inline const int *getPrimaryInputWord() const { return mPrimaryInputWord; } @@ -173,13 +174,13 @@ class ProximityInfoState { return mTouchPositionCorrectionEnabled; } - inline bool sameAsTyped(const unsigned short *word, int length) const { + inline bool sameAsTyped(const int *word, int length) const { if (length != mInputSize) { return false; } const int *inputCodes = mInputCodes; while (length--) { - if (static_cast(*inputCodes) != static_cast(*word)) { + if (*inputCodes != *word) { return false; } inputCodes += MAX_PROXIMITY_CHARS_SIZE_INTERNAL; @@ -236,7 +237,7 @@ class ProximityInfoState { // Returns angle of three points. x, y, and z are indices. float getPointsAngle(const int index0, const int index1, const int index2) const; - float getHighestProbabilitySequence(uint16_t *const charBuf) const; + float getHighestProbabilitySequence(int *const codePointBuf) const; float getProbability(const int index, const int charCode) const; @@ -255,7 +256,7 @@ class ProximityInfoState { float calculateSquaredDistanceFromSweetSpotCenter( const int keyIndex, const int inputIndex) const; - bool pushTouchPoint(const int inputIndex, const int nodeChar, int x, int y, const int time, + bool pushTouchPoint(const int inputIndex, const int nodeCodePoint, int x, int y, const int time, const bool sample, const bool isLastPoint, const float sumAngle, NearKeysDistanceMap *const currentNearKeysDistances, const NearKeysDistanceMap *const prevNearKeysDistances, @@ -269,7 +270,7 @@ class ProximityInfoState { return mInputXs.size() > 0 && mInputYs.size() > 0; } - inline const int *getProximityCharsAt(const int index) const { + inline const int *getProximityCodePointsAt(const int index) const { return mInputCodes + (index * MAX_PROXIMITY_CHARS_SIZE_INTERNAL); } @@ -322,10 +323,10 @@ class ProximityInfoState { // inputs including the current input point. std::vector mSearchKeysVector; bool mTouchPositionCorrectionEnabled; - int32_t mInputCodes[MAX_PROXIMITY_CHARS_SIZE_INTERNAL * MAX_WORD_LENGTH_INTERNAL]; + int mInputCodes[MAX_PROXIMITY_CHARS_SIZE_INTERNAL * MAX_WORD_LENGTH_INTERNAL]; int mNormalizedSquaredDistances[MAX_PROXIMITY_CHARS_SIZE_INTERNAL * MAX_WORD_LENGTH_INTERNAL]; int mInputSize; - unsigned short mPrimaryInputWord[MAX_WORD_LENGTH_INTERNAL]; + int mPrimaryInputWord[MAX_WORD_LENGTH_INTERNAL]; }; } // namespace latinime #endif // LATINIME_PROXIMITY_INFO_STATE_H diff --git a/native/jni/src/terminal_attributes.h b/native/jni/src/terminal_attributes.h index e72e7e3be..fed3c7251 100644 --- a/native/jni/src/terminal_attributes.h +++ b/native/jni/src/terminal_attributes.h @@ -43,18 +43,16 @@ class TerminalAttributes { return mHasNextShortcutTarget; } - // Gets the shortcut target itself as a uint16_t string. For parameters and return value + // Gets the shortcut target itself as an int string. For parameters and return value // see BinaryFormat::getWordAtAddress. - // TODO: make the output an uint32_t* to handle the whole unicode range. - inline int getNextShortcutTarget(const int maxDepth, uint16_t *outWord, int *outFreq) { + inline int getNextShortcutTarget(const int maxDepth, int *outWord, int *outFreq) { const int shortcutFlags = BinaryFormat::getFlagsAndForwardPointer(mDict, &mPos); - mHasNextShortcutTarget = - 0 != (shortcutFlags & BinaryFormat::FLAG_ATTRIBUTE_HAS_NEXT); + mHasNextShortcutTarget = 0 != (shortcutFlags & BinaryFormat::FLAG_ATTRIBUTE_HAS_NEXT); unsigned int i; for (i = 0; i < MAX_WORD_LENGTH_INTERNAL; ++i) { const int codePoint = BinaryFormat::getCodePointAndForwardPointer(mDict, &mPos); if (NOT_A_CODE_POINT == codePoint) break; - outWord[i] = (uint16_t)codePoint; + outWord[i] = codePoint; } *outFreq = BinaryFormat::getAttributeFrequencyFromFlags(shortcutFlags); return i; diff --git a/native/jni/src/unigram_dictionary.cpp b/native/jni/src/unigram_dictionary.cpp index f1fd1389a..dadc9c897 100644 --- a/native/jni/src/unigram_dictionary.cpp +++ b/native/jni/src/unigram_dictionary.cpp @@ -55,13 +55,13 @@ UnigramDictionary::UnigramDictionary(const uint8_t *const streamStart, int fullW UnigramDictionary::~UnigramDictionary() { } -static inline unsigned int getCodesBufferSize(const int *codes, const int codesSize) { - return static_cast(sizeof(*codes)) * codesSize; +static inline int getCodesBufferSize(const int *codes, const int codesSize) { + return sizeof(*codes) * codesSize; } -// TODO: This needs to take a const unsigned short* and not tinker with its contents -static inline void addWord(unsigned short *word, int length, int frequency, - WordsPriorityQueue *queue, int type) { +// TODO: This needs to take a const int* and not tinker with its contents +static inline void addWord(int *word, int length, int frequency, WordsPriorityQueue *queue, + int type) { queue->push(frequency, word, length, type); } @@ -171,9 +171,7 @@ void UnigramDictionary::getWordWithDigraphSuggestionsRec(ProximityInfo *proximit int UnigramDictionary::getSuggestions(ProximityInfo *proximityInfo, const int *xcoordinates, const int *ycoordinates, const int *codes, const int codesSize, const std::map *bigramMap, const uint8_t *bigramFilter, - const bool useFullEditDistance, unsigned short *outWords, int *frequencies, - int *outputTypes) const { - + const bool useFullEditDistance, int *outWords, int *frequencies, int *outputTypes) const { WordsPriorityQueuePool queuePool(MAX_WORDS, SUB_QUEUE_MAX_WORDS, MAX_WORD_LENGTH); queuePool.clearAll(); Correction masterCorrection; @@ -218,7 +216,7 @@ int UnigramDictionary::getSuggestions(ProximityInfo *proximityInfo, const int *x AKLOGI("Returning %d words", suggestedWordsCount); /// Print the returned words for (int j = 0; j < suggestedWordsCount; ++j) { - short unsigned int *w = outWords + j * MAX_WORD_LENGTH; + int *w = outWords + j * MAX_WORD_LENGTH; char s[MAX_WORD_LENGTH]; for (int i = 0; i <= MAX_WORD_LENGTH; i++) s[i] = w[i]; (void)s; // To suppress compiler warning @@ -230,12 +228,11 @@ int UnigramDictionary::getSuggestions(ProximityInfo *proximityInfo, const int *x return suggestedWordsCount; } -void UnigramDictionary::getWordSuggestions(ProximityInfo *proximityInfo, - const int *xcoordinates, const int *ycoordinates, const int *codes, - const int inputSize, const std::map *bigramMap, const uint8_t *bigramFilter, - const bool useFullEditDistance, Correction *correction, - WordsPriorityQueuePool *queuePool) const { - +void UnigramDictionary::getWordSuggestions(ProximityInfo *proximityInfo, const int *xcoordinates, + const int *ycoordinates, const int *codes, const int inputSize, + const std::map *bigramMap, const uint8_t *bigramFilter, + const bool useFullEditDistance, Correction *correction, WordsPriorityQueuePool *queuePool) + const { PROF_OPEN; PROF_START(0); PROF_END(0); @@ -284,7 +281,7 @@ void UnigramDictionary::getWordSuggestions(ProximityInfo *proximityInfo, if (queue->size() > 0) { WordsPriorityQueue::SuggestedWord *sw = queue->top(); const int score = sw->mScore; - const unsigned short *word = sw->mWord; + const int *word = sw->mWord; const int wordLength = sw->mWordLength; float ns = Correction::RankingAlgorithm::calcNormalizedScore( correction->getPrimaryInputWord(), i, word, wordLength, score); @@ -303,7 +300,7 @@ void UnigramDictionary::initSuggestions(ProximityInfo *proximityInfo, const int Correction *correction) const { if (DEBUG_DICT) { AKLOGI("initSuggest"); - DUMP_WORD_INT(codes, inputSize); + DUMP_WORD(codes, inputSize); } correction->initInputParams(proximityInfo, codes, inputSize, xCoordinates, yCoordinates); const int maxDepth = min(inputSize * MAX_DEPTH_MULTIPLIER, MAX_WORD_LENGTH); @@ -376,7 +373,7 @@ inline void UnigramDictionary::onTerminal(const int probability, const bool addToSubQueue = inputIndex < SUB_QUEUE_MAX_COUNT; int wordLength; - unsigned short *wordPointer; + int *wordPointer; if ((currentWordIndex == FIRST_WORD_INDEX) && addToMasterQueue) { WordsPriorityQueue *masterQueue = queuePool->getMasterQueue(); @@ -404,7 +401,7 @@ inline void UnigramDictionary::onTerminal(const int probability, // so that the insert order is protected inside the queue for words // with the same score. For the moment we use -1 to make sure the shortcut will // never be in front of the word. - uint16_t shortcutTarget[MAX_WORD_LENGTH_INTERNAL]; + int shortcutTarget[MAX_WORD_LENGTH_INTERNAL]; int shortcutFrequency; const int shortcutTargetStringLength = iterator.getNextShortcutTarget( MAX_WORD_LENGTH_INTERNAL, shortcutTarget, &shortcutFrequency); @@ -444,7 +441,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) const { + int *wordLengthArray, int *outputWord, int *outputWordLength) const { if (inputWordLength > MULTIPLE_WORDS_SUGGESTION_MAX_WORD_LENGTH) { return FLAG_MULTIPLE_SUGGEST_ABORT; } @@ -487,13 +484,13 @@ int UnigramDictionary::getSubStringSuggestion( // TODO: Remove the safety net above // ////////////////////////////////////////////// - unsigned short *tempOutputWord = 0; + int *tempOutputWord = 0; int nextWordLength = 0; // TODO: Optimize init suggestion initSuggestions(proximityInfo, xcoordinates, ycoordinates, codes, inputSize, correction); - unsigned short word[MAX_WORD_LENGTH_INTERNAL]; + int word[MAX_WORD_LENGTH_INTERNAL]; int freq = getMostFrequentWordLike( inputWordStartPos, inputWordLength, correction, word); if (freq > 0) { @@ -592,7 +589,7 @@ void UnigramDictionary::getMultiWordsSuggestionRec(ProximityInfo *proximityInfo, const bool useFullEditDistance, const int inputSize, Correction *correction, WordsPriorityQueuePool *queuePool, const bool hasAutoCorrectionCandidate, const int startInputPos, const int startWordIndex, const int outputWordLength, - int *freqArray, int *wordLengthArray, unsigned short *outputWord) const { + int *freqArray, int *wordLengthArray, int *outputWord) const { if (startWordIndex >= (MULTIPLE_WORDS_SUGGESTION_MAX_WORDS - 1)) { // Return if the last word index return; @@ -678,7 +675,7 @@ void UnigramDictionary::getSplitMultipleWordsSuggestions(ProximityInfo *proximit } // Allocating fixed length array on stack - unsigned short outputWord[MAX_WORD_LENGTH]; + int outputWord[MAX_WORD_LENGTH]; int freqArray[MULTIPLE_WORDS_SUGGESTION_MAX_WORDS]; int wordLengthArray[MULTIPLE_WORDS_SUGGESTION_MAX_WORDS]; const int outputWordLength = 0; @@ -693,11 +690,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 inputSize, Correction *correction, unsigned short *word) const { - uint16_t inWord[inputSize]; + const int inputSize, Correction *correction, int *word) const { + int inWord[inputSize]; for (int i = 0; i < inputSize; ++i) { - inWord[i] = (uint16_t)correction->getPrimaryCharAt(startInputIndex + i); + inWord[i] = correction->getPrimaryCodePointAt(startInputIndex + i); } return getMostFrequentWordLikeInner(inWord, inputSize, word); } @@ -715,14 +712,14 @@ inline int UnigramDictionary::getMostFrequentWordLike(const int startInputIndex, // In and out parameters may point to the same location. This function takes care // not to use any input parameters after it wrote into its outputs. static inline bool testCharGroupForContinuedLikeness(const uint8_t flags, - const uint8_t *const root, const int startPos, const uint16_t *const inWord, - const int startInputIndex, const int inputSize, int32_t *outNewWord, int *outInputIndex, + const uint8_t *const root, const int startPos, const int *const inWord, + const int startInputIndex, const int inputSize, int *outNewWord, int *outInputIndex, int *outPos) { const bool hasMultipleChars = (0 != (BinaryFormat::FLAG_HAS_MULTIPLE_CHARS & flags)); int pos = startPos; - int32_t codePoint = BinaryFormat::getCodePointAndForwardPointer(root, &pos); - int32_t baseChar = toBaseLowerCase(codePoint); - const uint16_t wChar = toBaseLowerCase(inWord[startInputIndex]); + int codePoint = BinaryFormat::getCodePointAndForwardPointer(root, &pos); + int baseChar = toBaseLowerCase(codePoint); + const int wChar = toBaseLowerCase(inWord[startInputIndex]); if (baseChar != wChar) { *outPos = hasMultipleChars ? BinaryFormat::skipOtherCharacters(root, pos) : pos; @@ -753,8 +750,8 @@ static inline bool testCharGroupForContinuedLikeness(const uint8_t flags, // It will compare the frequency to the max frequency, and if greater, will // copy the word into the output buffer. In output value maxFreq, it will // write the new maximum frequency if it changed. -static inline void onTerminalWordLike(const int freq, int32_t *newWord, const int length, - short unsigned int *outWord, int *maxFreq) { +static inline void onTerminalWordLike(const int freq, int *newWord, const int length, int *outWord, + int *maxFreq) { if (freq > *maxFreq) { for (int q = 0; q < length; ++q) { outWord[q] = newWord[q]; @@ -766,9 +763,9 @@ 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 inputSize, short unsigned int *outWord) const { - int32_t newWord[MAX_WORD_LENGTH_INTERNAL]; +int UnigramDictionary::getMostFrequentWordLikeInner(const int *const inWord, const int inputSize, + int *outWord) const { + int newWord[MAX_WORD_LENGTH_INTERNAL]; int depth = 0; int maxFreq = -1; const uint8_t *const root = DICT_ROOT; @@ -828,7 +825,7 @@ int UnigramDictionary::getMostFrequentWordLikeInner(const uint16_t *const inWord return maxFreq; } -int UnigramDictionary::getFrequency(const int32_t *const inWord, const int length) const { +int UnigramDictionary::getFrequency(const int *const inWord, const int length) const { const uint8_t *const root = DICT_ROOT; int pos = BinaryFormat::getTerminalPosition(root, inWord, length, false /* forceLowerCaseSearch */); @@ -853,8 +850,7 @@ int UnigramDictionary::getFrequency(const int32_t *const inWord, const int lengt } // TODO: remove this function. -int UnigramDictionary::getBigramPosition(int pos, unsigned short *word, int offset, - int length) const { +int UnigramDictionary::getBigramPosition(int pos, int *word, int offset, int length) const { return -1; } @@ -900,7 +896,7 @@ inline bool UnigramDictionary::processCurrentNode(const int initialPos, // else if FLAG_IS_TERMINAL: the frequency // else if MASK_GROUP_ADDRESS_TYPE is not NONE: the children address // Note that you can't have a node that both is not a terminal and has no children. - int32_t c = BinaryFormat::getCodePointAndForwardPointer(DICT_ROOT, &pos); + int c = BinaryFormat::getCodePointAndForwardPointer(DICT_ROOT, &pos); assert(NOT_A_CODE_POINT != c); // We are going to loop through each character and make it look like it's a different @@ -914,7 +910,7 @@ inline bool UnigramDictionary::processCurrentNode(const int initialPos, // We prefetch the next char. If 'c' is the last char of this node, we will have // NOT_A_CODE_POINT in the next char. From this we can decide whether this virtual node // should behave as a terminal or not and whether we have children. - const int32_t nextc = hasMultipleChars + const int nextc = hasMultipleChars ? BinaryFormat::getCodePointAndForwardPointer(DICT_ROOT, &pos) : NOT_A_CODE_POINT; const bool isLastChar = (NOT_A_CODE_POINT == nextc); // If there are more chars in this nodes, then this virtual node is not a terminal. diff --git a/native/jni/src/unigram_dictionary.h b/native/jni/src/unigram_dictionary.h index 244d78d8c..764900739 100644 --- a/native/jni/src/unigram_dictionary.h +++ b/native/jni/src/unigram_dictionary.h @@ -41,12 +41,12 @@ class UnigramDictionary { static const int FLAG_MULTIPLE_SUGGEST_CONTINUE = 2; UnigramDictionary(const uint8_t *const streamStart, int fullWordMultiplier, int maxWordLength, int maxWords, const unsigned int flags); - int getFrequency(const int32_t *const inWord, const int length) const; - int getBigramPosition(int pos, unsigned short *word, int offset, int length) const; + int getFrequency(const int *const inWord, const int length) const; + int getBigramPosition(int pos, int *word, int offset, int length) const; int getSuggestions(ProximityInfo *proximityInfo, const int *xcoordinates, const int *ycoordinates, const int *codes, const int codesSize, const std::map *bigramMap, const uint8_t *bigramFilter, - const bool useFullEditDistance, unsigned short *outWords, int *frequencies, + const bool useFullEditDistance, int *outWords, int *frequencies, int *outputTypes) const; virtual ~UnigramDictionary(); @@ -93,9 +93,9 @@ class UnigramDictionary { int *newChildPosition, int *nextSiblingPosition, WordsPriorityQueuePool *queuePool, const int currentWordIndex) const; int getMostFrequentWordLike(const int startInputIndex, const int inputSize, - Correction *correction, unsigned short *word) const; - int getMostFrequentWordLikeInner(const uint16_t *const inWord, const int inputSize, - short unsigned int *outWord) const; + Correction *correction, int *word) const; + int getMostFrequentWordLikeInner(const int *const inWord, const int inputSize, + int *outWord) const; int getSubStringSuggestion( ProximityInfo *proximityInfo, const int *xcoordinates, const int *ycoordinates, const int *codes, const bool useFullEditDistance, Correction *correction, @@ -103,14 +103,13 @@ 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) const; - void getMultiWordsSuggestionRec(ProximityInfo *proximityInfo, - const int *xcoordinates, const int *ycoordinates, const int *codes, - const bool useFullEditDistance, const int inputSize, - Correction *correction, WordsPriorityQueuePool *queuePool, + int *wordLengthArray, int *outputWord, int *outputWordLength) const; + void getMultiWordsSuggestionRec(ProximityInfo *proximityInfo, const int *xcoordinates, + const int *ycoordinates, const int *codes, const bool useFullEditDistance, + const int inputSize, Correction *correction, WordsPriorityQueuePool *queuePool, const bool hasAutoCorrectionCandidate, const int startPos, const int startWordIndex, const int outputWordLength, int *freqArray, int *wordLengthArray, - unsigned short *outputWord) const; + int *outputWord) const; const uint8_t *const DICT_ROOT; const int MAX_WORD_LENGTH; diff --git a/native/jni/src/words_priority_queue.h b/native/jni/src/words_priority_queue.h index 19efa5da3..ac384dd69 100644 --- a/native/jni/src/words_priority_queue.h +++ b/native/jni/src/words_priority_queue.h @@ -30,15 +30,15 @@ class WordsPriorityQueue { class SuggestedWord { public: int mScore; - unsigned short mWord[MAX_WORD_LENGTH_INTERNAL]; + int mWord[MAX_WORD_LENGTH_INTERNAL]; int mWordLength; bool mUsed; int mType; - void setParams(int score, unsigned short *word, int wordLength, int type) { + void setParams(int score, int *word, int wordLength, int type) { mScore = score; mWordLength = wordLength; - memcpy(mWord, word, sizeof(unsigned short) * wordLength); + memcpy(mWord, word, sizeof(int) * wordLength); mUsed = true; mType = type; } @@ -57,9 +57,9 @@ class WordsPriorityQueue { delete[] mSuggestedWords; } - void push(int score, unsigned short *word, int wordLength, int type) { + void push(int score, int *word, int wordLength, int type) { SuggestedWord *sw = 0; - if (mSuggestions.size() >= MAX_WORDS) { + if (size() >= MAX_WORDS) { sw = mSuggestions.top(); const int minScore = sw->mScore; if (minScore >= score) { @@ -94,11 +94,10 @@ class WordsPriorityQueue { return sw; } - int outputSuggestions(const unsigned short *before, const int beforeLength, - int *frequencies, unsigned short *outputChars, int* outputTypes) { + int outputSuggestions(const int *before, const int beforeLength, int *frequencies, + int *outputCodePoints, int* outputTypes) { mHighestSuggestedWord = 0; - const unsigned int size = min( - MAX_WORDS, static_cast(mSuggestions.size())); + const int size = min(MAX_WORDS, static_cast(mSuggestions.size())); SuggestedWord *swBuffer[size]; int index = size - 1; while (!mSuggestions.empty() && index >= 0) { @@ -113,9 +112,9 @@ class WordsPriorityQueue { } if (size >= 2) { SuggestedWord *nsMaxSw = 0; - unsigned int maxIndex = 0; + int maxIndex = 0; float maxNs = 0; - for (unsigned int i = 0; i < size; ++i) { + for (int i = 0; i < size; ++i) { SuggestedWord *tempSw = swBuffer[i]; if (!tempSw) { continue; @@ -132,17 +131,17 @@ class WordsPriorityQueue { swBuffer[0] = nsMaxSw; } } - for (unsigned int i = 0; i < size; ++i) { + for (int i = 0; i < size; ++i) { SuggestedWord *sw = swBuffer[i]; if (!sw) { AKLOGE("SuggestedWord is null %d", i); continue; } - const unsigned int wordLength = sw->mWordLength; - unsigned short *targetAddress = outputChars + i * MAX_WORD_LENGTH; + const int wordLength = sw->mWordLength; + int *targetAddress = outputCodePoints + i * MAX_WORD_LENGTH; frequencies[i] = sw->mScore; outputTypes[i] = sw->mType; - memcpy(targetAddress, sw->mWord, wordLength * sizeof(unsigned short)); + memcpy(targetAddress, sw->mWord, wordLength * sizeof(int)); if (wordLength < MAX_WORD_LENGTH) { targetAddress[wordLength] = 0; } @@ -152,7 +151,7 @@ class WordsPriorityQueue { } int size() const { - return mSuggestions.size(); + return static_cast(mSuggestions.size()); } void clear() { @@ -175,13 +174,13 @@ class WordsPriorityQueue { DUMP_WORD(mHighestSuggestedWord->mWord, mHighestSuggestedWord->mWordLength); } - float getHighestNormalizedScore(const unsigned short *before, const int beforeLength, - unsigned short **outWord, int *outScore, int *outLength) { + float getHighestNormalizedScore(const int *before, const int beforeLength, int **outWord, + int *outScore, int *outLength) { if (!mHighestSuggestedWord) { return 0.0; } - return getNormalizedScore( - mHighestSuggestedWord, before, beforeLength, outWord, outScore, outLength); + return getNormalizedScore(mHighestSuggestedWord, before, beforeLength, outWord, outScore, + outLength); } private: @@ -192,9 +191,8 @@ class WordsPriorityQueue { } }; - SuggestedWord *getFreeSuggestedWord(int score, unsigned short *word, - int wordLength, int type) { - for (unsigned int i = 0; i < MAX_WORD_LENGTH; ++i) { + SuggestedWord *getFreeSuggestedWord(int score, int *word, int wordLength, int type) { + for (int i = 0; i < MAX_WORD_LENGTH; ++i) { if (!mSuggestedWords[i].mUsed) { mSuggestedWords[i].setParams(score, word, wordLength, type); return &mSuggestedWords[i]; @@ -203,10 +201,10 @@ class WordsPriorityQueue { return 0; } - static float getNormalizedScore(SuggestedWord *sw, const unsigned short *before, - const int beforeLength, unsigned short **outWord, int *outScore, int *outLength) { + static float getNormalizedScore(SuggestedWord *sw, const int *before, const int beforeLength, + int **outWord, int *outScore, int *outLength) { const int score = sw->mScore; - unsigned short *word = sw->mWord; + int *word = sw->mWord; const int wordLength = sw->mWordLength; if (outScore) { *outScore = score; @@ -217,15 +215,15 @@ class WordsPriorityQueue { if (outLength) { *outLength = wordLength; } - return Correction::RankingAlgorithm::calcNormalizedScore( - before, beforeLength, word, wordLength, score); + return Correction::RankingAlgorithm::calcNormalizedScore(before, beforeLength, word, + wordLength, score); } typedef std::priority_queue, wordComparator> Suggestions; Suggestions mSuggestions; - const unsigned int MAX_WORDS; - const unsigned int MAX_WORD_LENGTH; + const int MAX_WORDS; + const int MAX_WORD_LENGTH; SuggestedWord *mSuggestedWords; SuggestedWord *mHighestSuggestedWord; }; -- cgit v1.2.3-83-g751a From 44d9c1ebfc2a847233190f6201ae97b22df30ae7 Mon Sep 17 00:00:00 2001 From: Ken Wakasa Date: Thu, 1 Nov 2012 17:05:08 +0900 Subject: Use sizeof() more safely. Change-Id: I7cffb4d8da847b483cf4bb482508e3c88c4903be --- ...com_android_inputmethod_latin_BinaryDictionary.cpp | 6 +++--- native/jni/src/proximity_info.cpp | 4 ++-- native/jni/src/unigram_dictionary.cpp | 19 ++++++++++--------- native/jni/src/unigram_dictionary.h | 1 - native/jni/src/words_priority_queue.h | 6 +++--- 5 files changed, 18 insertions(+), 18 deletions(-) (limited to 'native/jni/src') diff --git a/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp b/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp index 5b8d1119d..004665a3b 100644 --- a/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp +++ b/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp @@ -70,7 +70,7 @@ static jlong latinime_BinaryDictionary_open(JNIEnv *env, jobject object, adjust = static_cast(dictOffset) % pagesize; int adjDictOffset = static_cast(dictOffset) - adjust; int adjDictSize = static_cast(dictSize) + adjust; - dictBuf = mmap(0, sizeof(char) * adjDictSize, PROT_READ, MAP_PRIVATE, fd, adjDictOffset); + dictBuf = mmap(0, adjDictSize, PROT_READ, MAP_PRIVATE, fd, adjDictOffset); if (dictBuf == MAP_FAILED) { AKLOGE("DICT: Can't mmap dictionary. errno=%d", errno); return 0; @@ -84,7 +84,7 @@ static jlong latinime_BinaryDictionary_open(JNIEnv *env, jobject object, AKLOGE("DICT: Can't fopen sourceDir. sourceDirChars=%s errno=%d", sourceDirChars, errno); return 0; } - dictBuf = malloc(sizeof(char) * dictSize); + dictBuf = malloc(dictSize); if (!dictBuf) { AKLOGE("DICT: Can't allocate memory region for dictionary. errno=%d", errno); return 0; @@ -94,7 +94,7 @@ static jlong latinime_BinaryDictionary_open(JNIEnv *env, jobject object, AKLOGE("DICT: Failure in fseek. ret=%d errno=%d", ret, errno); return 0; } - ret = fread(dictBuf, sizeof(char) * dictSize, 1, file); + ret = fread(dictBuf, dictSize, 1, file); if (ret != 1) { AKLOGE("DICT: Failure in fread. ret=%d errno=%d", ret, errno); return 0; diff --git a/native/jni/src/proximity_info.cpp b/native/jni/src/proximity_info.cpp index e2aa15674..aadaae47e 100644 --- a/native/jni/src/proximity_info.cpp +++ b/native/jni/src/proximity_info.cpp @@ -36,7 +36,7 @@ static inline void safeGetOrFillZeroIntArrayRegion(JNIEnv *env, jintArray jArray if (jArray && buffer) { env->GetIntArrayRegion(jArray, 0, len, buffer); } else if (buffer) { - memset(buffer, 0, len * sizeof(jint)); + memset(buffer, 0, len * sizeof(buffer[0])); } } @@ -45,7 +45,7 @@ static inline void safeGetOrFillZeroFloatArrayRegion(JNIEnv *env, jfloatArray jA if (jArray && buffer) { env->GetFloatArrayRegion(jArray, 0, len, buffer); } else if (buffer) { - memset(buffer, 0, len * sizeof(jfloat)); + memset(buffer, 0, len * sizeof(buffer[0])); } } diff --git a/native/jni/src/unigram_dictionary.cpp b/native/jni/src/unigram_dictionary.cpp index dadc9c897..6cde06bfa 100644 --- a/native/jni/src/unigram_dictionary.cpp +++ b/native/jni/src/unigram_dictionary.cpp @@ -45,8 +45,7 @@ UnigramDictionary::UnigramDictionary(const uint8_t *const streamStart, int fullW int maxWordLength, int maxWords, const unsigned int flags) : DICT_ROOT(streamStart), MAX_WORD_LENGTH(maxWordLength), MAX_WORDS(maxWords), FULL_WORD_MULTIPLIER(fullWordMultiplier), // TODO : remove this variable. - ROOT_POS(0), BYTES_IN_ONE_CHAR(sizeof(int)), - MAX_DIGRAPH_SEARCH_DEPTH(DEFAULT_MAX_DIGRAPH_SEARCH_DEPTH), FLAGS(flags) { + ROOT_POS(0), MAX_DIGRAPH_SEARCH_DEPTH(DEFAULT_MAX_DIGRAPH_SEARCH_DEPTH), FLAGS(flags) { if (DEBUG_DICT) { AKLOGI("UnigramDictionary - constructor"); } @@ -103,6 +102,9 @@ void UnigramDictionary::getWordWithDigraphSuggestionsRec(ProximityInfo *proximit const int codesRemain, const int currentDepth, int *codesDest, Correction *correction, WordsPriorityQueuePool *queuePool, const digraph_t *const digraphs, const unsigned int digraphsSize) const { + assert(sizeof(codesDest[0]) == sizeof(codesSrc[0])); + assert(sizeof(xCoordinatesBuffer[0]) == sizeof(xcoordinates[0])); + assert(sizeof(yCoordinatesBuffer[0]) == sizeof(ycoordinates[0])); const int startIndex = static_cast(codesDest - codesBuffer); if (currentDepth < MAX_DIGRAPH_SEARCH_DEPTH) { @@ -123,9 +125,8 @@ void UnigramDictionary::getWordWithDigraphSuggestionsRec(ProximityInfo *proximit // Make i the index of the second char of the digraph for simplicity. Forgetting // to do that results in an infinite recursion so take care! ++i; - memcpy(codesDest, codesSrc, i * BYTES_IN_ONE_CHAR); - codesDest[(i - 1) * (BYTES_IN_ONE_CHAR / sizeof(codesDest[0]))] = - replacementCodePoint; + memcpy(codesDest, codesSrc, i * sizeof(codesDest[0])); + codesDest[i - 1] = replacementCodePoint; getWordWithDigraphSuggestionsRec(proximityInfo, xcoordinates, ycoordinates, codesBuffer, xCoordinatesBuffer, yCoordinatesBuffer, codesBufferSize, bigramMap, bigramFilter, useFullEditDistance, codesSrc + i + 1, @@ -135,7 +136,7 @@ void UnigramDictionary::getWordWithDigraphSuggestionsRec(ProximityInfo *proximit // Copy the second char of the digraph in place, then continue processing on // the remaining part of the word. // In our example, after "pru" in the buffer copy the "e", and continue on "fen" - memcpy(codesDest + i, codesSrc + i, BYTES_IN_ONE_CHAR); + memcpy(codesDest + i, codesSrc + i, sizeof(codesDest[0])); getWordWithDigraphSuggestionsRec(proximityInfo, xcoordinates, ycoordinates, codesBuffer, xCoordinatesBuffer, yCoordinatesBuffer, codesBufferSize, bigramMap, bigramFilter, useFullEditDistance, codesSrc + i, codesRemain - i, @@ -151,13 +152,13 @@ void UnigramDictionary::getWordWithDigraphSuggestionsRec(ProximityInfo *proximit // If the word contains several digraphs, we'll come it for the product of them. // eg. if the word is "ueberpruefen" we'll test, in order, against // "uberprufen", "uberpruefen", "ueberprufen", "ueberpruefen". - const unsigned int remainingBytes = BYTES_IN_ONE_CHAR * codesRemain; + const unsigned int remainingBytes = sizeof(codesDest[0]) * codesRemain; if (0 != remainingBytes) { memcpy(codesDest, codesSrc, remainingBytes); memcpy(&xCoordinatesBuffer[startIndex], &xcoordinates[codesBufferSize - codesRemain], - sizeof(int) * codesRemain); + sizeof(xCoordinatesBuffer[0]) * codesRemain); memcpy(&yCoordinatesBuffer[startIndex], &ycoordinates[codesBufferSize - codesRemain], - sizeof(int) * codesRemain); + sizeof(yCoordinatesBuffer[0]) * codesRemain); } getWordSuggestions(proximityInfo, xCoordinatesBuffer, yCoordinatesBuffer, codesBuffer, diff --git a/native/jni/src/unigram_dictionary.h b/native/jni/src/unigram_dictionary.h index 764900739..248b09db1 100644 --- a/native/jni/src/unigram_dictionary.h +++ b/native/jni/src/unigram_dictionary.h @@ -116,7 +116,6 @@ class UnigramDictionary { const int MAX_WORDS; const int FULL_WORD_MULTIPLIER; const int ROOT_POS; - const unsigned int BYTES_IN_ONE_CHAR; const int MAX_DIGRAPH_SEARCH_DEPTH; const int FLAGS; diff --git a/native/jni/src/words_priority_queue.h b/native/jni/src/words_priority_queue.h index ac384dd69..c4ee07f32 100644 --- a/native/jni/src/words_priority_queue.h +++ b/native/jni/src/words_priority_queue.h @@ -38,7 +38,7 @@ class WordsPriorityQueue { void setParams(int score, int *word, int wordLength, int type) { mScore = score; mWordLength = wordLength; - memcpy(mWord, word, sizeof(int) * wordLength); + memcpy(mWord, word, sizeof(mWord[0]) * wordLength); mUsed = true; mType = type; } @@ -127,7 +127,7 @@ class WordsPriorityQueue { } } if (maxIndex > 0 && nsMaxSw) { - memmove(&swBuffer[1], &swBuffer[0], maxIndex * sizeof(SuggestedWord *)); + memmove(&swBuffer[1], &swBuffer[0], maxIndex * sizeof(swBuffer[0])); swBuffer[0] = nsMaxSw; } } @@ -141,7 +141,7 @@ class WordsPriorityQueue { int *targetAddress = outputCodePoints + i * MAX_WORD_LENGTH; frequencies[i] = sw->mScore; outputTypes[i] = sw->mType; - memcpy(targetAddress, sw->mWord, wordLength * sizeof(int)); + memcpy(targetAddress, sw->mWord, wordLength * sizeof(targetAddress[0])); if (wordLength < MAX_WORD_LENGTH) { targetAddress[wordLength] = 0; } -- cgit v1.2.3-83-g751a From a323fa6746b60955e52e96856837dc4e90425f76 Mon Sep 17 00:00:00 2001 From: Ken Wakasa Date: Fri, 2 Nov 2012 12:14:34 +0900 Subject: A small code cleanup in geometry_utils.h Change-Id: Ie9ff77c661693a1e21d0aa4cfc079bfbf3171f49 --- native/jni/src/geometry_utils.h | 33 ++++++++++++++++++++------------- native/jni/src/proximity_info.cpp | 7 ------- 2 files changed, 20 insertions(+), 20 deletions(-) (limited to 'native/jni/src') diff --git a/native/jni/src/geometry_utils.h b/native/jni/src/geometry_utils.h index ee7c98562..927b44f96 100644 --- a/native/jni/src/geometry_utils.h +++ b/native/jni/src/geometry_utils.h @@ -24,33 +24,39 @@ #define M_PI_F 3.14159265f #define ROUND_FLOAT_10000(f) ((f) < 1000.0f && (f) > 0.001f) \ ? (floorf((f) * 10000.0f) / 10000.0f) : (f) -#define SQUARE_FLOAT(x) ((x) * (x)) namespace latinime { -static inline float getSquaredDistanceFloat(float x1, float y1, float x2, float y2) { - const float deltaX = x1 - x2; - const float deltaY = y1 - y2; - return SQUARE_FLOAT(deltaX) + SQUARE_FLOAT(deltaY); +static inline float SQUARE_FLOAT(const float x) { return x * x; } + +static inline float getSquaredDistanceFloat(const float x1, const float y1, const float x2, + const float y2) { + return SQUARE_FLOAT(x1 - x2) + SQUARE_FLOAT(y1 - y2); +} + +static inline float getNormalizedSquaredDistanceFloat(const float x1, const float y1, + const float x2, const float y2, const float scale) { + return getSquaredDistanceFloat(x1, y1, x2, y2) / SQUARE_FLOAT(scale); } -static inline float getDistanceFloat(float x1, float y1, float x2, float y2) { +static inline float getDistanceFloat(const float x1, const float y1, const float x2, + const float y2) { return hypotf(x1 - x2, y1 - y2); } -static inline int getDistanceInt(int x1, int y1, int x2, int y2) { +static inline int getDistanceInt(const int x1, const int y1, const int x2, const int y2) { return static_cast(getDistanceFloat(static_cast(x1), static_cast(y1), static_cast(x2), static_cast(y2))); } -static inline float getAngle(int x1, int y1, int x2, int y2) { +static inline float getAngle(const int x1, const int y1, const int x2, const int y2) { const int dx = x1 - x2; const int dy = y1 - y2; if (dx == 0 && dy == 0) return 0; return atan2f(static_cast(dy), static_cast(dx)); } -static inline float getAngleDiff(float a1, float a2) { +static inline float getAngleDiff(const float a1, const float a2) { const float deltaA = fabsf(a1 - a2); const float diff = ROUND_FLOAT_10000(deltaA); if (diff > M_PI_F) { @@ -60,8 +66,8 @@ static inline float getAngleDiff(float a1, float a2) { return diff; } -static inline float pointToLineSegSquaredDistanceFloat( - float x, float y, float x1, float y1, float x2, float y2, bool extend) { +static inline float pointToLineSegSquaredDistanceFloat(const float x, const float y, const float x1, + const float y1, const float x2, const float y2, const bool extend) { const float ray1x = x - x1; const float ray1y = y - y1; const float ray2x = x2 - x1; @@ -93,16 +99,17 @@ struct NormalDistribution { mPreComputedNonExpPart(1.0f / sqrtf(2.0f * M_PI_F * SQUARE_FLOAT(sigma))), mPreComputedExponentPart(-1.0f / (2.0f * SQUARE_FLOAT(sigma))) {} - float getProbabilityDensity(const float x) { + float getProbabilityDensity(const float x) const { const float shiftedX = x - mU; return mPreComputedNonExpPart * expf(mPreComputedExponentPart * SQUARE_FLOAT(shiftedX)); } + private: DISALLOW_IMPLICIT_CONSTRUCTORS(NormalDistribution); float mU; // mean value float mSigma; // standard deviation float mPreComputedNonExpPart; // = 1 / sqrt(2 * PI * sigma^2) float mPreComputedExponentPart; // = -1 / (2 * sigma^2) -}; +}; // struct NormalDistribution } // namespace latinime #endif // LATINIME_GEOMETRY_UTILS_H diff --git a/native/jni/src/proximity_info.cpp b/native/jni/src/proximity_info.cpp index aadaae47e..a12d43acc 100644 --- a/native/jni/src/proximity_info.cpp +++ b/native/jni/src/proximity_info.cpp @@ -127,13 +127,6 @@ bool ProximityInfo::hasSpaceProximity(const int x, const int y) const { return false; } -static inline float getNormalizedSquaredDistanceFloat(float x1, float y1, float x2, float y2, - float scale) { - const float deltaX = x1 - x2; - const float deltaY = y1 - y2; - return (SQUARE_FLOAT(deltaX) + SQUARE_FLOAT(deltaY)) / SQUARE_FLOAT(scale); -} - float ProximityInfo::getNormalizedSquaredDistanceFromCenterFloatG( const int keyId, const int x, const int y) const { const static float verticalSweetSpotScaleForGeometric = 1.1f; -- cgit v1.2.3-83-g751a From 2c2f3a90d8115777adbe9ffd597f344aede84276 Mon Sep 17 00:00:00 2001 From: Ken Wakasa Date: Fri, 2 Nov 2012 18:29:03 +0900 Subject: Add more compiler warning flags Change-Id: Ic6af0c596374d936d2b9b31e626fb62bd265ce64 --- native/jni/Android.mk | 1 + native/jni/src/correction.cpp | 23 ++++++++++ native/jni/src/correction.h | 29 +++---------- native/jni/src/dic_traverse_wrapper.h | 1 - native/jni/src/proximity_info_state.cpp | 62 +++++++++++++++++++++++++++ native/jni/src/proximity_info_state.h | 69 ++---------------------------- native/jni/src/unigram_dictionary.cpp | 10 ++--- native/jni/src/words_priority_queue.cpp | 76 +++++++++++++++++++++++++++++++++ native/jni/src/words_priority_queue.h | 59 ++----------------------- 9 files changed, 177 insertions(+), 153 deletions(-) create mode 100644 native/jni/src/words_priority_queue.cpp (limited to 'native/jni/src') diff --git a/native/jni/Android.mk b/native/jni/Android.mk index bd769d2fc..69a9aa970 100644 --- a/native/jni/Android.mk +++ b/native/jni/Android.mk @@ -50,6 +50,7 @@ LATIN_IME_CORE_SRC_FILES := \ proximity_info.cpp \ proximity_info_state.cpp \ unigram_dictionary.cpp \ + words_priority_queue.cpp \ gesture/gesture_decoder_wrapper.cpp \ gesture/incremental_decoder_wrapper.cpp diff --git a/native/jni/src/correction.cpp b/native/jni/src/correction.cpp index 949158a0b..d7b67c98b 100644 --- a/native/jni/src/correction.cpp +++ b/native/jni/src/correction.cpp @@ -625,6 +625,29 @@ Correction::CorrectionType Correction::processCharAndCalcState(const int c, cons } } +/* static */ int Correction::powerIntCapped(const int base, const int n) { + if (n <= 0) return 1; + if (base == 2) { + return n < 31 ? 1 << n : S_INT_MAX; + } else { + int ret = base; + for (int i = 1; i < n; ++i) multiplyIntCapped(base, &ret); + return ret; + } +} + +/* static */ void Correction::multiplyRate(const int rate, int *freq) { + if (*freq != S_INT_MAX) { + if (*freq > 1000000) { + *freq /= 100; + multiplyIntCapped(rate, freq); + } else { + multiplyIntCapped(rate, freq); + *freq /= 100; + } + } +} + inline static int getQuoteCount(const int *word, const int length) { int quoteCount = 0; for (int i = 0; i < length; ++i) { diff --git a/native/jni/src/correction.h b/native/jni/src/correction.h index fff24b048..d0b196cf2 100644 --- a/native/jni/src/correction.h +++ b/native/jni/src/correction.h @@ -168,28 +168,8 @@ class Correction { } } - inline static int powerIntCapped(const int base, const int n) { - if (n <= 0) return 1; - if (base == 2) { - return n < 31 ? 1 << n : S_INT_MAX; - } else { - int ret = base; - for (int i = 1; i < n; ++i) multiplyIntCapped(base, &ret); - return ret; - } - } - - inline static void multiplyRate(const int rate, int *freq) { - if (*freq != S_INT_MAX) { - if (*freq > 1000000) { - *freq /= 100; - multiplyIntCapped(rate, freq); - } else { - multiplyIntCapped(rate, freq); - *freq /= 100; - } - } - } + static int powerIntCapped(const int base, const int n); + static void multiplyRate(const int rate, int *freq); inline int getSpaceProximityPos() const { return mSpaceProximityPos; @@ -214,8 +194,6 @@ class Correction { inline void incrementOutputIndex(); inline void startToTraverseAllNodes(); inline bool isSingleQuote(const int c); - inline CorrectionType processSkipChar(const int c, const bool isTerminal, - const bool inputIndexIncremented); inline CorrectionType processUnrelatedCorrectionType(); inline void addCharToCurrentWord(const int c); inline int getFinalProbabilityInternal(const int probability, int **word, int *wordLength, @@ -246,6 +224,9 @@ class Correction { // Caveat: Do not create multiple tables per thread as this table eats up RAM a lot. int mEditDistanceTable[(MAX_WORD_LENGTH_INTERNAL + 1) * (MAX_WORD_LENGTH_INTERNAL + 1)]; + CorrectionType processSkipChar(const int c, const bool isTerminal, + const bool inputIndexIncremented); + CorrectionState mCorrectionStates[MAX_WORD_LENGTH_INTERNAL]; // The following member variables are being used as cache values of the correction state. diff --git a/native/jni/src/dic_traverse_wrapper.h b/native/jni/src/dic_traverse_wrapper.h index 292382487..3fe3d5b74 100644 --- a/native/jni/src/dic_traverse_wrapper.h +++ b/native/jni/src/dic_traverse_wrapper.h @@ -62,6 +62,5 @@ class DicTraverseWrapper { void *, const Dictionary *const, const int *, const int); static void (*sDicTraverseSessionReleaseMethod)(void *); }; -int register_DicTraverseSession(JNIEnv *env); } // namespace latinime #endif // LATINIME_DIC_TRAVERSE_WRAPPER_H diff --git a/native/jni/src/proximity_info_state.cpp b/native/jni/src/proximity_info_state.cpp index 987a27b80..db79bb616 100644 --- a/native/jni/src/proximity_info_state.cpp +++ b/native/jni/src/proximity_info_state.cpp @@ -560,6 +560,68 @@ float ProximityInfoState::getPointToKeyByIdLength(const int inputIndex, const in return static_cast(MAX_POINT_TO_KEY_LENGTH); } +// 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. +ProximityType ProximityInfoState::getMatchedProximityId(const int index, const int c, + const bool checkProximityChars, int *proximityIndex) const { + const int *currentCodePoints = getProximityCodePointsAt(index); + const int firstCodePoint = currentCodePoints[0]; + const int 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 (firstCodePoint == baseLowerC || firstCodePoint == 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(firstCodePoint) == 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 + && currentCodePoints[j] > ADDITIONAL_PROXIMITY_CHAR_DELIMITER_CODE) { + const bool matched = (currentCodePoints[j] == baseLowerC || currentCodePoints[j] == c); + if (matched) { + if (proximityIndex) { + *proximityIndex = j; + } + return NEAR_PROXIMITY_CHAR; + } + ++j; + } + if (j < MAX_PROXIMITY_CHARS_SIZE_INTERNAL + && currentCodePoints[j] == ADDITIONAL_PROXIMITY_CHAR_DELIMITER_CODE) { + ++j; + while (j < MAX_PROXIMITY_CHARS_SIZE_INTERNAL + && currentCodePoints[j] > ADDITIONAL_PROXIMITY_CHAR_DELIMITER_CODE) { + const bool matched = (currentCodePoints[j] == baseLowerC || currentCodePoints[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; +} + int ProximityInfoState::getSpaceY() const { const int keyId = mProximityInfo->getKeyIndexOf(KEYCODE_SPACE); return mProximityInfo->getKeyCenterYOfKeyIdG(keyId); diff --git a/native/jni/src/proximity_info_state.h b/native/jni/src/proximity_info_state.h index 14fe2d3f5..9b859606d 100644 --- a/native/jni/src/proximity_info_state.h +++ b/native/jni/src/proximity_info_state.h @@ -94,72 +94,6 @@ class ProximityInfoState { 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 int c, - const bool checkProximityChars, int *proximityIndex = 0) const { - const int *currentCodePoints = getProximityCodePointsAt(index); - const int firstCodePoint = currentCodePoints[0]; - const int 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 (firstCodePoint == baseLowerC || firstCodePoint == 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(firstCodePoint) == 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 - && currentCodePoints[j] > ADDITIONAL_PROXIMITY_CHAR_DELIMITER_CODE) { - const bool matched = (currentCodePoints[j] == baseLowerC || currentCodePoints[j] == c); - if (matched) { - if (proximityIndex) { - *proximityIndex = j; - } - return NEAR_PROXIMITY_CHAR; - } - ++j; - } - if (j < MAX_PROXIMITY_CHARS_SIZE_INTERNAL - && currentCodePoints[j] == ADDITIONAL_PROXIMITY_CHAR_DELIMITER_CODE) { - ++j; - while (j < MAX_PROXIMITY_CHARS_SIZE_INTERNAL - && currentCodePoints[j] > ADDITIONAL_PROXIMITY_CHAR_DELIMITER_CODE) { - const bool matched = - (currentCodePoints[j] == baseLowerC || currentCodePoints[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[ @@ -218,6 +152,9 @@ class ProximityInfoState { float getPointToKeyLength(const int inputIndex, const int charCode) const; float getPointToKeyByIdLength(const int inputIndex, const int keyId) const; + ProximityType getMatchedProximityId(const int index, const int c, + const bool checkProximityChars, int *proximityIndex = 0) const; + int getSpaceY() const; int32_t getAllPossibleChars( diff --git a/native/jni/src/unigram_dictionary.cpp b/native/jni/src/unigram_dictionary.cpp index 6cde06bfa..820f9ab12 100644 --- a/native/jni/src/unigram_dictionary.cpp +++ b/native/jni/src/unigram_dictionary.cpp @@ -59,8 +59,7 @@ static inline int getCodesBufferSize(const int *codes, const int codesSize) { } // TODO: This needs to take a const int* and not tinker with its contents -static inline void addWord(int *word, int length, int frequency, WordsPriorityQueue *queue, - int type) { +static void addWord(int *word, int length, int frequency, WordsPriorityQueue *queue, int type) { queue->push(frequency, word, length, type); } @@ -690,10 +689,9 @@ void UnigramDictionary::getSplitMultipleWordsSuggestions(ProximityInfo *proximit // Wrapper for getMostFrequentWordLikeInner, which matches it to the previous // interface. -inline int UnigramDictionary::getMostFrequentWordLike(const int startInputIndex, - const int inputSize, Correction *correction, int *word) const { +int UnigramDictionary::getMostFrequentWordLike(const int startInputIndex, const int inputSize, + Correction *correction, int *word) const { int inWord[inputSize]; - for (int i = 0; i < inputSize; ++i) { inWord[i] = correction->getPrimaryCodePointAt(startInputIndex + i); } @@ -869,7 +867,7 @@ int UnigramDictionary::getBigramPosition(int pos, int *word, int offset, int len // there aren't any more nodes at this level, it merely returns the address of the first byte after // the current node in nextSiblingPosition. Thus, the caller must keep count of the nodes at any // given level, as output into newCount when traversing this level's parent. -inline bool UnigramDictionary::processCurrentNode(const int initialPos, +bool UnigramDictionary::processCurrentNode(const int initialPos, const std::map *bigramMap, const uint8_t *bigramFilter, Correction *correction, int *newCount, int *newChildrenPosition, int *nextSiblingPosition, WordsPriorityQueuePool *queuePool, const int currentWordIndex) const { diff --git a/native/jni/src/words_priority_queue.cpp b/native/jni/src/words_priority_queue.cpp new file mode 100644 index 000000000..7e18d0f87 --- /dev/null +++ b/native/jni/src/words_priority_queue.cpp @@ -0,0 +1,76 @@ +/* + * 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 "words_priority_queue.h" + +namespace latinime { + +int WordsPriorityQueue::outputSuggestions(const int *before, const int beforeLength, + int *frequencies, int *outputCodePoints, int* outputTypes) { + mHighestSuggestedWord = 0; + const int size = min(MAX_WORDS, static_cast(mSuggestions.size())); + SuggestedWord *swBuffer[size]; + int index = size - 1; + while (!mSuggestions.empty() && index >= 0) { + SuggestedWord *sw = mSuggestions.top(); + if (DEBUG_WORDS_PRIORITY_QUEUE) { + AKLOGI("dump word. %d", sw->mScore); + DUMP_WORD(sw->mWord, sw->mWordLength); + } + swBuffer[index] = sw; + mSuggestions.pop(); + --index; + } + if (size >= 2) { + SuggestedWord *nsMaxSw = 0; + int maxIndex = 0; + float maxNs = 0; + for (int i = 0; i < size; ++i) { + SuggestedWord *tempSw = swBuffer[i]; + if (!tempSw) { + continue; + } + const float tempNs = getNormalizedScore(tempSw, before, beforeLength, 0, 0, 0); + if (tempNs >= maxNs) { + maxNs = tempNs; + maxIndex = i; + nsMaxSw = tempSw; + } + } + if (maxIndex > 0 && nsMaxSw) { + memmove(&swBuffer[1], &swBuffer[0], maxIndex * sizeof(swBuffer[0])); + swBuffer[0] = nsMaxSw; + } + } + for (int i = 0; i < size; ++i) { + SuggestedWord *sw = swBuffer[i]; + if (!sw) { + AKLOGE("SuggestedWord is null %d", i); + continue; + } + const int wordLength = sw->mWordLength; + int *targetAddress = outputCodePoints + i * MAX_WORD_LENGTH; + frequencies[i] = sw->mScore; + outputTypes[i] = sw->mType; + memcpy(targetAddress, sw->mWord, wordLength * sizeof(targetAddress[0])); + if (wordLength < MAX_WORD_LENGTH) { + targetAddress[wordLength] = 0; + } + sw->mUsed = false; + } + return size; +} +} // namespace latinime diff --git a/native/jni/src/words_priority_queue.h b/native/jni/src/words_priority_queue.h index c4ee07f32..b0cc92e2f 100644 --- a/native/jni/src/words_priority_queue.h +++ b/native/jni/src/words_priority_queue.h @@ -94,62 +94,6 @@ class WordsPriorityQueue { return sw; } - int outputSuggestions(const int *before, const int beforeLength, int *frequencies, - int *outputCodePoints, int* outputTypes) { - mHighestSuggestedWord = 0; - const int size = min(MAX_WORDS, static_cast(mSuggestions.size())); - SuggestedWord *swBuffer[size]; - int index = size - 1; - while (!mSuggestions.empty() && index >= 0) { - SuggestedWord *sw = mSuggestions.top(); - if (DEBUG_WORDS_PRIORITY_QUEUE) { - AKLOGI("dump word. %d", sw->mScore); - DUMP_WORD(sw->mWord, sw->mWordLength); - } - swBuffer[index] = sw; - mSuggestions.pop(); - --index; - } - if (size >= 2) { - SuggestedWord *nsMaxSw = 0; - int maxIndex = 0; - float maxNs = 0; - for (int i = 0; i < size; ++i) { - SuggestedWord *tempSw = swBuffer[i]; - if (!tempSw) { - continue; - } - const float tempNs = getNormalizedScore(tempSw, before, beforeLength, 0, 0, 0); - if (tempNs >= maxNs) { - maxNs = tempNs; - maxIndex = i; - nsMaxSw = tempSw; - } - } - if (maxIndex > 0 && nsMaxSw) { - memmove(&swBuffer[1], &swBuffer[0], maxIndex * sizeof(swBuffer[0])); - swBuffer[0] = nsMaxSw; - } - } - for (int i = 0; i < size; ++i) { - SuggestedWord *sw = swBuffer[i]; - if (!sw) { - AKLOGE("SuggestedWord is null %d", i); - continue; - } - const int wordLength = sw->mWordLength; - int *targetAddress = outputCodePoints + i * MAX_WORD_LENGTH; - frequencies[i] = sw->mScore; - outputTypes[i] = sw->mType; - memcpy(targetAddress, sw->mWord, wordLength * sizeof(targetAddress[0])); - if (wordLength < MAX_WORD_LENGTH) { - targetAddress[wordLength] = 0; - } - sw->mUsed = false; - } - return size; - } - int size() const { return static_cast(mSuggestions.size()); } @@ -183,6 +127,9 @@ class WordsPriorityQueue { outLength); } + int outputSuggestions(const int *before, const int beforeLength, int *frequencies, + int *outputCodePoints, int* outputTypes); + private: DISALLOW_IMPLICIT_CONSTRUCTORS(WordsPriorityQueue); struct wordComparator { -- cgit v1.2.3-83-g751a From 19d844c7a7dccf2b4f03003f1fae65496526999f Mon Sep 17 00:00:00 2001 From: Ken Wakasa Date: Fri, 2 Nov 2012 23:57:13 +0900 Subject: Follow up to Ic6af0c596374d936d2b9b31e626fb62bd265ce64 Tidy up inline functions with AK_FORCE_INLINE. Moved back some inline methods to header files. Change-Id: Ibd37b595666ebddda198d9237f19f6712653a8e8 --- native/jni/src/char_utils.h | 4 +- native/jni/src/correction.cpp | 133 +-------------------------------- native/jni/src/correction.h | 135 ++++++++++++++++++++++++++++++++-- native/jni/src/defines.h | 6 ++ native/jni/src/unigram_dictionary.cpp | 2 +- 5 files changed, 140 insertions(+), 140 deletions(-) (limited to 'native/jni/src') diff --git a/native/jni/src/char_utils.h b/native/jni/src/char_utils.h index b42de6607..c632b79b8 100644 --- a/native/jni/src/char_utils.h +++ b/native/jni/src/char_utils.h @@ -55,7 +55,7 @@ inline static int toBaseCodePoint(int c) { return c; } -inline static int toLowerCase(const int c) { +AK_FORCE_INLINE static int toLowerCase(const int c) { if (isAsciiUpper(c)) { return toAsciiLower(c); } else if (isAscii(c)) { @@ -64,7 +64,7 @@ inline static int toLowerCase(const int c) { return static_cast(latin_tolower(static_cast(c))); } -inline static int toBaseLowerCase(const int c) { +AK_FORCE_INLINE static int toBaseLowerCase(const int c) { return toLowerCase(toBaseCodePoint(c)); } diff --git a/native/jni/src/correction.cpp b/native/jni/src/correction.cpp index d7b67c98b..50f33fe23 100644 --- a/native/jni/src/correction.cpp +++ b/native/jni/src/correction.cpp @@ -60,29 +60,6 @@ inline static void dumpEditDistance10ForDebug(int *editDistanceTable, } } -inline static void calcEditDistanceOneStep(int *editDistanceTable, const int *input, - const int inputSize, const int *output, const int outputLength) { - // TODO: Make sure that editDistance[0 ~ MAX_WORD_LENGTH_INTERNAL] is not touched. - // Let dp[i][j] be editDistanceTable[i * (inputSize + 1) + j]. - // Assuming that dp[0][0] ... dp[outputLength - 1][inputSize] are already calculated, - // and calculate dp[ouputLength][0] ... dp[outputLength][inputSize]. - int *const current = editDistanceTable + outputLength * (inputSize + 1); - const int *const prev = editDistanceTable + (outputLength - 1) * (inputSize + 1); - const int *const prevprev = - outputLength >= 2 ? editDistanceTable + (outputLength - 2) * (inputSize + 1) : 0; - current[0] = outputLength; - const int co = toBaseLowerCase(output[outputLength - 1]); - const int prevCO = outputLength >= 2 ? toBaseLowerCase(output[outputLength - 2]) : 0; - for (int i = 1; i <= inputSize; ++i) { - const int ci = toBaseLowerCase(input[i - 1]); - const uint16_t cost = (ci == co) ? 0 : 1; - current[i] = min(current[i - 1] + 1, min(prev[i] + 1, prev[i - 1] + cost)); - if (i >= 2 && prevprev && ci == prevCO && co == toBaseLowerCase(input[i - 2])) { - current[i] = min(current[i], prevprev[i - 2] + 1); - } - } -} - inline static int getCurrentEditDistance(int *editDistanceTable, const int editDistanceTableWidth, const int outputLength, const int inputSize) { if (DEBUG_EDIT_DISTANCE) { @@ -91,14 +68,6 @@ inline static int getCurrentEditDistance(int *editDistanceTable, const int editD return editDistanceTable[(editDistanceTableWidth + 1) * (outputLength) + inputSize]; } -////////////////////// -// inline functions // -////////////////////// -inline bool Correction::isSingleQuote(const int c) { - const int userTypedChar = mProximityInfoState.getPrimaryCodePointAt(mInputIndex); - return (c == KEYCODE_SINGLE_QUOTE && userTypedChar != KEYCODE_SINGLE_QUOTE); -} - //////////////// // Correction // //////////////// @@ -174,17 +143,6 @@ int Correction::getFinalProbabilityForSubQueue(const int probability, int **word return getFinalProbabilityInternal(probability, word, wordLength, inputSize); } -int Correction::getFinalProbabilityInternal(const int probability, int **word, int *wordLength, - const int inputSize) { - const int outputIndex = mTerminalOutputIndex; - const int inputIndex = mTerminalInputIndex; - *wordLength = outputIndex + 1; - *word = mWord; - int finalProbability= Correction::RankingAlgorithm::calculateFinalProbability( - inputIndex, outputIndex, probability, mEditDistanceTable, this, inputSize); - return finalProbability; -} - bool Correction::initProcessState(const int outputIndex) { if (mCorrectionStates[outputIndex].mChildCount <= 0) { return false; @@ -228,42 +186,6 @@ int Correction::getInputIndex() const { return mInputIndex; } -void Correction::incrementInputIndex() { - ++mInputIndex; -} - -void Correction::incrementOutputIndex() { - ++mOutputIndex; - mCorrectionStates[mOutputIndex].mParentIndex = mCorrectionStates[mOutputIndex - 1].mParentIndex; - mCorrectionStates[mOutputIndex].mChildCount = mCorrectionStates[mOutputIndex - 1].mChildCount; - mCorrectionStates[mOutputIndex].mSiblingPos = mCorrectionStates[mOutputIndex - 1].mSiblingPos; - mCorrectionStates[mOutputIndex].mInputIndex = mInputIndex; - mCorrectionStates[mOutputIndex].mNeedsToTraverseAllNodes = mNeedsToTraverseAllNodes; - - mCorrectionStates[mOutputIndex].mEquivalentCharCount = mEquivalentCharCount; - mCorrectionStates[mOutputIndex].mProximityCount = mProximityCount; - mCorrectionStates[mOutputIndex].mTransposedCount = mTransposedCount; - mCorrectionStates[mOutputIndex].mExcessiveCount = mExcessiveCount; - mCorrectionStates[mOutputIndex].mSkippedCount = mSkippedCount; - - mCorrectionStates[mOutputIndex].mSkipPos = mSkipPos; - mCorrectionStates[mOutputIndex].mTransposedPos = mTransposedPos; - mCorrectionStates[mOutputIndex].mExcessivePos = mExcessivePos; - - mCorrectionStates[mOutputIndex].mLastCharExceeded = mLastCharExceeded; - - mCorrectionStates[mOutputIndex].mMatching = mMatching; - mCorrectionStates[mOutputIndex].mProximityMatching = mProximityMatching; - mCorrectionStates[mOutputIndex].mAdditionalProximityMatching = mAdditionalProximityMatching; - mCorrectionStates[mOutputIndex].mTransposing = mTransposing; - mCorrectionStates[mOutputIndex].mExceeding = mExceeding; - mCorrectionStates[mOutputIndex].mSkipping = mSkipping; -} - -void Correction::startToTraverseAllNodes() { - mNeedsToTraverseAllNodes = true; -} - bool Correction::needsToPrune() const { // TODO: use edit distance here return mOutputIndex - 1 >= mMaxDepth || mProximityCount > mMaxEditDistance @@ -271,39 +193,11 @@ bool Correction::needsToPrune() const { || (!mDoAutoCompletion && (mOutputIndex > mInputSize)); } -void Correction::addCharToCurrentWord(const int c) { - mWord[mOutputIndex] = c; - const int *primaryInputWord = mProximityInfoState.getPrimaryInputWord(); - calcEditDistanceOneStep(mEditDistanceTable, primaryInputWord, mInputSize, mWord, - mOutputIndex + 1); -} - -Correction::CorrectionType Correction::processSkipChar(const int c, const bool isTerminal, - const bool inputIndexIncremented) { - addCharToCurrentWord(c); - mTerminalInputIndex = mInputIndex - (inputIndexIncremented ? 1 : 0); - mTerminalOutputIndex = mOutputIndex; - if (mNeedsToTraverseAllNodes && isTerminal) { - incrementOutputIndex(); - return TRAVERSE_ALL_ON_TERMINAL; - } else { - incrementOutputIndex(); - return TRAVERSE_ALL_NOT_ON_TERMINAL; - } -} - -Correction::CorrectionType Correction::processUnrelatedCorrectionType() { - // Needs to set mTerminalInputIndex and mTerminalOutputIndex before returning any CorrectionType - mTerminalInputIndex = mInputIndex; - mTerminalOutputIndex = mOutputIndex; - return UNRELATED; -} - -inline bool isEquivalentChar(ProximityType type) { +inline static bool isEquivalentChar(ProximityType type) { return type == EQUIVALENT_CHAR; } -inline bool isProximityCharOrEquivalentChar(ProximityType type) { +inline static bool isProximityCharOrEquivalentChar(ProximityType type) { return type == EQUIVALENT_CHAR || type == NEAR_PROXIMITY_CHAR; } @@ -625,29 +519,6 @@ Correction::CorrectionType Correction::processCharAndCalcState(const int c, cons } } -/* static */ int Correction::powerIntCapped(const int base, const int n) { - if (n <= 0) return 1; - if (base == 2) { - return n < 31 ? 1 << n : S_INT_MAX; - } else { - int ret = base; - for (int i = 1; i < n; ++i) multiplyIntCapped(base, &ret); - return ret; - } -} - -/* static */ void Correction::multiplyRate(const int rate, int *freq) { - if (*freq != S_INT_MAX) { - if (*freq > 1000000) { - *freq /= 100; - multiplyIntCapped(rate, freq); - } else { - multiplyIntCapped(rate, freq); - *freq /= 100; - } - } -} - inline static int getQuoteCount(const int *word, const int length) { int quoteCount = 0; for (int i = 0; i < length; ++i) { diff --git a/native/jni/src/correction.h b/native/jni/src/correction.h index d0b196cf2..105a95f38 100644 --- a/native/jni/src/correction.h +++ b/native/jni/src/correction.h @@ -145,7 +145,7 @@ class Correction { } static const int TWO_31ST_DIV_2 = S_INT_MAX / 2; - inline static void multiplyIntCapped(const int multiplier, int *base) { + AK_FORCE_INLINE static void multiplyIntCapped(const int multiplier, int *base) { const int temp = *base; if (temp != S_INT_MAX) { // Branch if multiplier == 2 for the optimization @@ -168,8 +168,28 @@ class Correction { } } - static int powerIntCapped(const int base, const int n); - static void multiplyRate(const int rate, int *freq); + AK_FORCE_INLINE static int powerIntCapped(const int base, const int n) { + if (n <= 0) return 1; + if (base == 2) { + return n < 31 ? 1 << n : S_INT_MAX; + } else { + int ret = base; + for (int i = 1; i < n; ++i) multiplyIntCapped(base, &ret); + return ret; + } + } + + AK_FORCE_INLINE static void multiplyRate(const int rate, int *freq) { + if (*freq != S_INT_MAX) { + if (*freq > 1000000) { + *freq /= 100; + multiplyIntCapped(rate, freq); + } else { + multiplyIntCapped(rate, freq); + *freq /= 100; + } + } + } inline int getSpaceProximityPos() const { return mSpaceProximityPos; @@ -194,6 +214,8 @@ class Correction { inline void incrementOutputIndex(); inline void startToTraverseAllNodes(); inline bool isSingleQuote(const int c); + inline CorrectionType processSkipChar(const int c, const bool isTerminal, + const bool inputIndexIncremented); inline CorrectionType processUnrelatedCorrectionType(); inline void addCharToCurrentWord(const int c); inline int getFinalProbabilityInternal(const int probability, int **word, int *wordLength, @@ -224,9 +246,6 @@ class Correction { // Caveat: Do not create multiple tables per thread as this table eats up RAM a lot. int mEditDistanceTable[(MAX_WORD_LENGTH_INTERNAL + 1) * (MAX_WORD_LENGTH_INTERNAL + 1)]; - CorrectionType processSkipChar(const int c, const bool isTerminal, - const bool inputIndexIncremented); - CorrectionState mCorrectionStates[MAX_WORD_LENGTH_INTERNAL]; // The following member variables are being used as cache values of the correction state. @@ -254,5 +273,109 @@ class Correction { bool mSkipping; ProximityInfoState mProximityInfoState; }; + +inline void Correction::incrementInputIndex() { + ++mInputIndex; +} + +AK_FORCE_INLINE void Correction::incrementOutputIndex() { + ++mOutputIndex; + mCorrectionStates[mOutputIndex].mParentIndex = mCorrectionStates[mOutputIndex - 1].mParentIndex; + mCorrectionStates[mOutputIndex].mChildCount = mCorrectionStates[mOutputIndex - 1].mChildCount; + mCorrectionStates[mOutputIndex].mSiblingPos = mCorrectionStates[mOutputIndex - 1].mSiblingPos; + mCorrectionStates[mOutputIndex].mInputIndex = mInputIndex; + mCorrectionStates[mOutputIndex].mNeedsToTraverseAllNodes = mNeedsToTraverseAllNodes; + + mCorrectionStates[mOutputIndex].mEquivalentCharCount = mEquivalentCharCount; + mCorrectionStates[mOutputIndex].mProximityCount = mProximityCount; + mCorrectionStates[mOutputIndex].mTransposedCount = mTransposedCount; + mCorrectionStates[mOutputIndex].mExcessiveCount = mExcessiveCount; + mCorrectionStates[mOutputIndex].mSkippedCount = mSkippedCount; + + mCorrectionStates[mOutputIndex].mSkipPos = mSkipPos; + mCorrectionStates[mOutputIndex].mTransposedPos = mTransposedPos; + mCorrectionStates[mOutputIndex].mExcessivePos = mExcessivePos; + + mCorrectionStates[mOutputIndex].mLastCharExceeded = mLastCharExceeded; + + mCorrectionStates[mOutputIndex].mMatching = mMatching; + mCorrectionStates[mOutputIndex].mProximityMatching = mProximityMatching; + mCorrectionStates[mOutputIndex].mAdditionalProximityMatching = mAdditionalProximityMatching; + mCorrectionStates[mOutputIndex].mTransposing = mTransposing; + mCorrectionStates[mOutputIndex].mExceeding = mExceeding; + mCorrectionStates[mOutputIndex].mSkipping = mSkipping; +} + +inline void Correction::startToTraverseAllNodes() { + mNeedsToTraverseAllNodes = true; +} + +inline bool Correction::isSingleQuote(const int c) { + const int userTypedChar = mProximityInfoState.getPrimaryCodePointAt(mInputIndex); + return (c == KEYCODE_SINGLE_QUOTE && userTypedChar != KEYCODE_SINGLE_QUOTE); +} + +AK_FORCE_INLINE Correction::CorrectionType Correction::processSkipChar(const int c, + const bool isTerminal, const bool inputIndexIncremented) { + addCharToCurrentWord(c); + mTerminalInputIndex = mInputIndex - (inputIndexIncremented ? 1 : 0); + mTerminalOutputIndex = mOutputIndex; + if (mNeedsToTraverseAllNodes && isTerminal) { + incrementOutputIndex(); + return TRAVERSE_ALL_ON_TERMINAL; + } else { + incrementOutputIndex(); + return TRAVERSE_ALL_NOT_ON_TERMINAL; + } +} + +inline Correction::CorrectionType Correction::processUnrelatedCorrectionType() { + // Needs to set mTerminalInputIndex and mTerminalOutputIndex before returning any CorrectionType + mTerminalInputIndex = mInputIndex; + mTerminalOutputIndex = mOutputIndex; + return UNRELATED; +} + +AK_FORCE_INLINE static void calcEditDistanceOneStep(int *editDistanceTable, const int *input, + const int inputSize, const int *output, const int outputLength) { + // TODO: Make sure that editDistance[0 ~ MAX_WORD_LENGTH_INTERNAL] is not touched. + // Let dp[i][j] be editDistanceTable[i * (inputSize + 1) + j]. + // Assuming that dp[0][0] ... dp[outputLength - 1][inputSize] are already calculated, + // and calculate dp[ouputLength][0] ... dp[outputLength][inputSize]. + int *const current = editDistanceTable + outputLength * (inputSize + 1); + const int *const prev = editDistanceTable + (outputLength - 1) * (inputSize + 1); + const int *const prevprev = + outputLength >= 2 ? editDistanceTable + (outputLength - 2) * (inputSize + 1) : 0; + current[0] = outputLength; + const int co = toBaseLowerCase(output[outputLength - 1]); + const int prevCO = outputLength >= 2 ? toBaseLowerCase(output[outputLength - 2]) : 0; + for (int i = 1; i <= inputSize; ++i) { + const int ci = toBaseLowerCase(input[i - 1]); + const uint16_t cost = (ci == co) ? 0 : 1; + current[i] = min(current[i - 1] + 1, min(prev[i] + 1, prev[i - 1] + cost)); + if (i >= 2 && prevprev && ci == prevCO && co == toBaseLowerCase(input[i - 2])) { + current[i] = min(current[i], prevprev[i - 2] + 1); + } + } +} + +AK_FORCE_INLINE void Correction::addCharToCurrentWord(const int c) { + mWord[mOutputIndex] = c; + const int *primaryInputWord = mProximityInfoState.getPrimaryInputWord(); + calcEditDistanceOneStep(mEditDistanceTable, primaryInputWord, mInputSize, mWord, + mOutputIndex + 1); +} + +inline int Correction::getFinalProbabilityInternal(const int probability, int **word, + int *wordLength, const int inputSize) { + const int outputIndex = mTerminalOutputIndex; + const int inputIndex = mTerminalInputIndex; + *wordLength = outputIndex + 1; + *word = mWord; + int finalProbability= Correction::RankingAlgorithm::calculateFinalProbability( + inputIndex, outputIndex, probability, mEditDistanceTable, this, inputSize); + return finalProbability; +} + } // namespace latinime #endif // LATINIME_CORRECTION_H diff --git a/native/jni/src/defines.h b/native/jni/src/defines.h index 095487416..40bc958d1 100644 --- a/native/jni/src/defines.h +++ b/native/jni/src/defines.h @@ -383,6 +383,12 @@ template inline T max(T a, T b) { return a > b ? a : b; } #define NELEMS(x) (sizeof(x) / sizeof((x)[0])) +#ifdef __GNUC__ +#define AK_FORCE_INLINE __attribute__((always_inline)) __inline__ +#else // __GNUC__ +#define AK_FORCE_INLINE inline +#endif // __GNUC__ + // The ratio of neutral area radius to sweet spot radius. #define NEUTRAL_AREA_RADIUS_RATIO 1.3f diff --git a/native/jni/src/unigram_dictionary.cpp b/native/jni/src/unigram_dictionary.cpp index 820f9ab12..d134a47e6 100644 --- a/native/jni/src/unigram_dictionary.cpp +++ b/native/jni/src/unigram_dictionary.cpp @@ -365,7 +365,7 @@ void UnigramDictionary::getSuggestionCandidates(const bool useFullEditDistance, } } -inline void UnigramDictionary::onTerminal(const int probability, +void UnigramDictionary::onTerminal(const int probability, const TerminalAttributes& terminalAttributes, Correction *correction, WordsPriorityQueuePool *queuePool, const bool addToMasterQueue, const int currentWordIndex) const { -- cgit v1.2.3-83-g751a From 6e66349ed1d37c24a1a23bf117df6750ad53d322 Mon Sep 17 00:00:00 2001 From: Ken Wakasa Date: Sat, 3 Nov 2012 02:50:47 +0900 Subject: Adjust compiler warning options with the offdevice Makefile Make use of AK_FORCE_INLINE for -Winline and better performance Change-Id: If0016e2ef61c1fe007c83bb1a5133a6b6bde568e --- native/jni/Android.mk | 4 ++- native/jni/src/additional_proximity_chars.h | 2 +- native/jni/src/binary_format.h | 32 ++++++++++++---------- native/jni/src/correction.h | 3 +- native/jni/src/geometry_utils.h | 8 ++++-- native/jni/src/gesture/gesture_decoder_wrapper.cpp | 4 +++ native/jni/src/gesture/gesture_decoder_wrapper.h | 4 +-- .../src/gesture/incremental_decoder_wrapper.cpp | 4 +++ .../jni/src/gesture/incremental_decoder_wrapper.h | 4 +-- native/jni/src/proximity_info.cpp | 8 +++--- native/jni/src/proximity_info_state.h | 7 +++-- native/jni/src/words_priority_queue.h | 5 ++-- native/jni/src/words_priority_queue_pool.h | 5 ++-- 13 files changed, 52 insertions(+), 38 deletions(-) (limited to 'native/jni/src') diff --git a/native/jni/Android.mk b/native/jni/Android.mk index 69a9aa970..da05894f5 100644 --- a/native/jni/Android.mk +++ b/native/jni/Android.mk @@ -28,7 +28,9 @@ LATIN_IME_SRC_FULLPATH_DIR := $(LOCAL_PATH)/$(LATIN_IME_SRC_DIR) LOCAL_C_INCLUDES += $(LATIN_IME_SRC_FULLPATH_DIR) $(LATIN_IME_SRC_FULLPATH_DIR)/gesture -LOCAL_CFLAGS += -Werror -Wall -Wextra -Weffc++ -Wno-system-headers +LOCAL_CFLAGS += -Werror -Wall -Wextra -Weffc++ -Wformat=2 -Wcast-qual -Wcast-align \ + -Wwrite-strings -Wfloat-equal -Wpointer-arith -Winit-self -Wredundant-decls \ + -Winline -Wno-system-headers # To suppress compiler warnings for unused variables/functions used for debug features etc. LOCAL_CFLAGS += -Wno-unused-parameter -Wno-unused-function diff --git a/native/jni/src/additional_proximity_chars.h b/native/jni/src/additional_proximity_chars.h index d420c4664..0333c2dbd 100644 --- a/native/jni/src/additional_proximity_chars.h +++ b/native/jni/src/additional_proximity_chars.h @@ -39,7 +39,7 @@ class AdditionalProximityChars { static const int EN_US_ADDITIONAL_U_SIZE = 4; static const int32_t EN_US_ADDITIONAL_U[]; - static bool isEnLocale(const char *localeStr) { + AK_FORCE_INLINE static bool isEnLocale(const char *localeStr) { const size_t LOCALE_EN_US_SIZE = strlen(LOCALE_EN_US); return localeStr && strlen(localeStr) >= LOCALE_EN_US_SIZE && strncmp(localeStr, LOCALE_EN_US, LOCALE_EN_US_SIZE) == 0; diff --git a/native/jni/src/binary_format.h b/native/jni/src/binary_format.h index c0aec50d7..7bb976097 100644 --- a/native/jni/src/binary_format.h +++ b/native/jni/src/binary_format.h @@ -123,7 +123,7 @@ class BinaryFormat { static int skipAllAttributes(const uint8_t *const dict, const uint8_t flags, const int pos); }; -inline int BinaryFormat::detectFormat(const uint8_t *const dict) { +AK_FORCE_INLINE int BinaryFormat::detectFormat(const uint8_t *const dict) { // The magic number is stored big-endian. const uint32_t magicNumber = (dict[0] << 24) + (dict[1] << 16) + (dict[2] << 8) + dict[3]; switch (magicNumber) { @@ -166,7 +166,8 @@ inline unsigned int BinaryFormat::getHeaderSize(const uint8_t *const dict) { } } -inline int BinaryFormat::getGroupCountAndForwardPointer(const uint8_t *const dict, int *pos) { +AK_FORCE_INLINE int BinaryFormat::getGroupCountAndForwardPointer(const uint8_t *const dict, + int *pos) { const int msb = dict[(*pos)++]; if (msb < 0x80) return msb; return ((msb & 0x7F) << 8) | dict[(*pos)++]; @@ -176,7 +177,8 @@ inline uint8_t BinaryFormat::getFlagsAndForwardPointer(const uint8_t *const dict return dict[(*pos)++]; } -inline int BinaryFormat::getCodePointAndForwardPointer(const uint8_t *const dict, int *pos) { +AK_FORCE_INLINE int BinaryFormat::getCodePointAndForwardPointer(const uint8_t *const dict, + int *pos) { const int origin = *pos; const int codePoint = dict[origin]; if (codePoint < MINIMAL_ONE_BYTE_CHARACTER_VALUE) { @@ -200,7 +202,7 @@ inline int BinaryFormat::readFrequencyWithoutMovingPointer(const uint8_t *const return dict[pos]; } -inline int BinaryFormat::skipOtherCharacters(const uint8_t *const dict, const int pos) { +AK_FORCE_INLINE int BinaryFormat::skipOtherCharacters(const uint8_t *const dict, const int pos) { int currentPos = pos; int character = dict[currentPos++]; while (CHARACTER_ARRAY_TERMINATOR != character) { @@ -226,7 +228,7 @@ static inline int attributeAddressSize(const uint8_t flags) { */ } -static inline int skipExistingBigrams(const uint8_t *const dict, const int pos) { +static AK_FORCE_INLINE int skipExistingBigrams(const uint8_t *const dict, const int pos) { int currentPos = pos; uint8_t flags = BinaryFormat::getFlagsAndForwardPointer(dict, ¤tPos); while (flags & BinaryFormat::FLAG_ATTRIBUTE_HAS_NEXT) { @@ -255,7 +257,7 @@ inline int BinaryFormat::skipFrequency(const uint8_t flags, const int pos) { return FLAG_IS_TERMINAL & flags ? pos + 1 : pos; } -inline int BinaryFormat::skipShortcuts(const uint8_t *const dict, const uint8_t flags, +AK_FORCE_INLINE int BinaryFormat::skipShortcuts(const uint8_t *const dict, const uint8_t flags, const int pos) { if (FLAG_HAS_SHORTCUT_TARGETS & flags) { return pos + shortcutByteSize(dict, pos); @@ -264,7 +266,7 @@ inline int BinaryFormat::skipShortcuts(const uint8_t *const dict, const uint8_t } } -inline int BinaryFormat::skipBigrams(const uint8_t *const dict, const uint8_t flags, +AK_FORCE_INLINE int BinaryFormat::skipBigrams(const uint8_t *const dict, const uint8_t flags, const int pos) { if (FLAG_HAS_BIGRAMS & flags) { return skipExistingBigrams(dict, pos); @@ -273,7 +275,7 @@ inline int BinaryFormat::skipBigrams(const uint8_t *const dict, const uint8_t fl } } -inline int BinaryFormat::skipAllAttributes(const uint8_t *const dict, const uint8_t flags, +AK_FORCE_INLINE int BinaryFormat::skipAllAttributes(const uint8_t *const dict, const uint8_t flags, const int pos) { // This function skips all attributes: shortcuts and bigrams. int newPos = pos; @@ -282,7 +284,7 @@ inline int BinaryFormat::skipAllAttributes(const uint8_t *const dict, const uint return newPos; } -inline int BinaryFormat::skipChildrenPosAndAttributes(const uint8_t *const dict, +AK_FORCE_INLINE int BinaryFormat::skipChildrenPosAndAttributes(const uint8_t *const dict, const uint8_t flags, const int pos) { int currentPos = pos; currentPos = skipChildrenPosition(flags, currentPos); @@ -290,8 +292,8 @@ inline int BinaryFormat::skipChildrenPosAndAttributes(const uint8_t *const dict, return currentPos; } -inline int BinaryFormat::readChildrenPosition(const uint8_t *const dict, const uint8_t flags, - const int pos) { +AK_FORCE_INLINE int BinaryFormat::readChildrenPosition(const uint8_t *const dict, + const uint8_t flags, const int pos) { int offset = 0; switch (MASK_GROUP_ADDRESS_TYPE & flags) { case FLAG_GROUP_ADDRESS_TYPE_ONEBYTE: @@ -318,7 +320,7 @@ inline bool BinaryFormat::hasChildrenInFlags(const uint8_t flags) { return (FLAG_GROUP_ADDRESS_TYPE_NOADDRESS != (MASK_GROUP_ADDRESS_TYPE & flags)); } -inline int BinaryFormat::getAttributeAddressAndForwardPointer(const uint8_t *const dict, +AK_FORCE_INLINE int BinaryFormat::getAttributeAddressAndForwardPointer(const uint8_t *const dict, const uint8_t flags, int *pos) { int offset = 0; const int origin = *pos; @@ -352,8 +354,8 @@ inline int BinaryFormat::getAttributeFrequencyFromFlags(const int flags) { // This function gets the byte position of the last chargroup of the exact matching word in the // dictionary. If no match is found, it returns NOT_VALID_WORD. -inline int BinaryFormat::getTerminalPosition(const uint8_t *const root, const int *const inWord, - const int length, const bool forceLowerCaseSearch) { +AK_FORCE_INLINE int BinaryFormat::getTerminalPosition(const uint8_t *const root, + const int *const inWord, const int length, const bool forceLowerCaseSearch) { int pos = 0; int wordPos = 0; @@ -438,7 +440,7 @@ inline int BinaryFormat::getTerminalPosition(const uint8_t *const root, const in * outUnigramFrequency: a pointer to an int to write the frequency into. * Return value : the length of the word, of 0 if the word was not found. */ -inline int BinaryFormat::getWordAtAddress(const uint8_t *const root, const int address, +AK_FORCE_INLINE int BinaryFormat::getWordAtAddress(const uint8_t *const root, const int address, const int maxDepth, int *outWord, int *outUnigramFrequency) { int pos = 0; int wordPos = 0; diff --git a/native/jni/src/correction.h b/native/jni/src/correction.h index 105a95f38..912cd838e 100644 --- a/native/jni/src/correction.h +++ b/native/jni/src/correction.h @@ -56,7 +56,8 @@ class Correction { // No need to initialize it explicitly here. } - virtual ~Correction() {} + // Non virtual inline destructor -- never inherit this class + ~Correction() {} void resetCorrection(); void initCorrection( const ProximityInfo *pi, const int inputSize, const int maxWordLength); diff --git a/native/jni/src/geometry_utils.h b/native/jni/src/geometry_utils.h index 927b44f96..38b91cc50 100644 --- a/native/jni/src/geometry_utils.h +++ b/native/jni/src/geometry_utils.h @@ -19,6 +19,8 @@ #include +#include "defines.h" + #define DEBUG_DECODER false #define M_PI_F 3.14159265f @@ -44,19 +46,19 @@ static inline float getDistanceFloat(const float x1, const float y1, const float return hypotf(x1 - x2, y1 - y2); } -static inline int getDistanceInt(const int x1, const int y1, const int x2, const int y2) { +static AK_FORCE_INLINE int getDistanceInt(const int x1, const int y1, const int x2, const int y2) { return static_cast(getDistanceFloat(static_cast(x1), static_cast(y1), static_cast(x2), static_cast(y2))); } -static inline float getAngle(const int x1, const int y1, const int x2, const int y2) { +static AK_FORCE_INLINE float getAngle(const int x1, const int y1, const int x2, const int y2) { const int dx = x1 - x2; const int dy = y1 - y2; if (dx == 0 && dy == 0) return 0; return atan2f(static_cast(dy), static_cast(dx)); } -static inline float getAngleDiff(const float a1, const float a2) { +static AK_FORCE_INLINE float getAngleDiff(const float a1, const float a2) { const float deltaA = fabsf(a1 - a2); const float diff = ROUND_FLOAT_10000(deltaA); if (diff > M_PI_F) { diff --git a/native/jni/src/gesture/gesture_decoder_wrapper.cpp b/native/jni/src/gesture/gesture_decoder_wrapper.cpp index afbe0c5c3..20ad4a58c 100644 --- a/native/jni/src/gesture/gesture_decoder_wrapper.cpp +++ b/native/jni/src/gesture/gesture_decoder_wrapper.cpp @@ -19,4 +19,8 @@ namespace latinime { IncrementalDecoderInterface * (*GestureDecoderWrapper::sGestureDecoderFactoryMethod)(int, int) = 0; + + GestureDecoderWrapper::~GestureDecoderWrapper() { + delete mIncrementalDecoderInterface; + } } // namespace latinime diff --git a/native/jni/src/gesture/gesture_decoder_wrapper.h b/native/jni/src/gesture/gesture_decoder_wrapper.h index eb80bd2e2..5b056b647 100644 --- a/native/jni/src/gesture/gesture_decoder_wrapper.h +++ b/native/jni/src/gesture/gesture_decoder_wrapper.h @@ -33,9 +33,7 @@ class GestureDecoderWrapper : public IncrementalDecoderInterface { : mIncrementalDecoderInterface(getGestureDecoderInstance(maxWordLength, maxWords)) { } - virtual ~GestureDecoderWrapper() { - delete mIncrementalDecoderInterface; - } + virtual ~GestureDecoderWrapper(); int getSuggestions(ProximityInfo *pInfo, void *traverseSession, int *inputXs, int *inputYs, int *times, int *pointerIds, int *codes, int inputSize, int commitPoint, int *outWords, diff --git a/native/jni/src/gesture/incremental_decoder_wrapper.cpp b/native/jni/src/gesture/incremental_decoder_wrapper.cpp index 8fcda6c9e..f6e45623a 100644 --- a/native/jni/src/gesture/incremental_decoder_wrapper.cpp +++ b/native/jni/src/gesture/incremental_decoder_wrapper.cpp @@ -19,4 +19,8 @@ namespace latinime { IncrementalDecoderInterface * (*IncrementalDecoderWrapper::sIncrementalDecoderFactoryMethod)(int, int) = 0; + + IncrementalDecoderWrapper::~IncrementalDecoderWrapper() { + delete mIncrementalDecoderInterface; + } } // namespace latinime diff --git a/native/jni/src/gesture/incremental_decoder_wrapper.h b/native/jni/src/gesture/incremental_decoder_wrapper.h index 691d4952d..7d16560ef 100644 --- a/native/jni/src/gesture/incremental_decoder_wrapper.h +++ b/native/jni/src/gesture/incremental_decoder_wrapper.h @@ -33,9 +33,7 @@ class IncrementalDecoderWrapper : public IncrementalDecoderInterface { : mIncrementalDecoderInterface(getIncrementalDecoderInstance(maxWordLength, maxWords)) { } - virtual ~IncrementalDecoderWrapper() { - delete mIncrementalDecoderInterface; - } + virtual ~IncrementalDecoderWrapper(); int getSuggestions(ProximityInfo *pInfo, void *traverseSession, int *inputXs, int *inputYs, int *times, int *pointerIds, int *codes, int inputSize, int commitPoint, int *outWords, diff --git a/native/jni/src/proximity_info.cpp b/native/jni/src/proximity_info.cpp index a12d43acc..84db7c196 100644 --- a/native/jni/src/proximity_info.cpp +++ b/native/jni/src/proximity_info.cpp @@ -31,8 +31,8 @@ namespace latinime { /* static */ const float ProximityInfo::NOT_A_DISTANCE_FLOAT = -1.0f; -static inline void safeGetOrFillZeroIntArrayRegion(JNIEnv *env, jintArray jArray, jsize len, - jint *buffer) { +static AK_FORCE_INLINE void safeGetOrFillZeroIntArrayRegion(JNIEnv *env, jintArray jArray, + jsize len, jint *buffer) { if (jArray && buffer) { env->GetIntArrayRegion(jArray, 0, len, buffer); } else if (buffer) { @@ -40,8 +40,8 @@ static inline void safeGetOrFillZeroIntArrayRegion(JNIEnv *env, jintArray jArray } } -static inline void safeGetOrFillZeroFloatArrayRegion(JNIEnv *env, jfloatArray jArray, jsize len, - jfloat *buffer) { +static AK_FORCE_INLINE void safeGetOrFillZeroFloatArrayRegion(JNIEnv *env, jfloatArray jArray, + jsize len, jfloat *buffer) { if (jArray && buffer) { env->GetFloatArrayRegion(jArray, 0, len, buffer); } else if (buffer) { diff --git a/native/jni/src/proximity_info_state.h b/native/jni/src/proximity_info_state.h index 9b859606d..39a238889 100644 --- a/native/jni/src/proximity_info_state.h +++ b/native/jni/src/proximity_info_state.h @@ -50,7 +50,7 @@ class ProximityInfoState { ///////////////////////////////////////// // Defined here // ///////////////////////////////////////// - ProximityInfoState() + AK_FORCE_INLINE ProximityInfoState() : mProximityInfo(0), mMaxPointToKeyLength(0), mHasTouchPositionCorrectionData(false), mMostCommonKeyWidthSquare(0), mLocaleStr(), mKeyCount(0), mCellHeight(0), mCellWidth(0), mGridHeight(0), mGridWidth(0), @@ -63,13 +63,14 @@ class ProximityInfoState { memset(mPrimaryInputWord, 0, sizeof(mPrimaryInputWord)); } - virtual ~ProximityInfoState() {} + // Non virtual inline destructor -- never inherit this class + AK_FORCE_INLINE ~ProximityInfoState() {} inline int getPrimaryCodePointAt(const int index) const { return getProximityCodePointsAt(index)[0]; } - inline bool existsCodePointInProximityAt(const int index, const int c) const { + AK_FORCE_INLINE bool existsCodePointInProximityAt(const int index, const int c) const { const int *codePoints = getProximityCodePointsAt(index); int i = 0; while (codePoints[i] > 0 && i < MAX_PROXIMITY_CHARS_SIZE_INTERNAL) { diff --git a/native/jni/src/words_priority_queue.h b/native/jni/src/words_priority_queue.h index b0cc92e2f..7d0c4d17d 100644 --- a/native/jni/src/words_priority_queue.h +++ b/native/jni/src/words_priority_queue.h @@ -53,7 +53,8 @@ class WordsPriorityQueue { } } - virtual ~WordsPriorityQueue() { + // Non virtual inline destructor -- never inherit this class + AK_FORCE_INLINE ~WordsPriorityQueue() { delete[] mSuggestedWords; } @@ -98,7 +99,7 @@ class WordsPriorityQueue { return static_cast(mSuggestions.size()); } - void clear() { + AK_FORCE_INLINE void clear() { mHighestSuggestedWord = 0; while (!mSuggestions.empty()) { SuggestedWord *sw = mSuggestions.top(); diff --git a/native/jni/src/words_priority_queue_pool.h b/native/jni/src/words_priority_queue_pool.h index 2d52903e0..c14afa07b 100644 --- a/native/jni/src/words_priority_queue_pool.h +++ b/native/jni/src/words_priority_queue_pool.h @@ -36,7 +36,8 @@ class WordsPriorityQueuePool { } } - virtual ~WordsPriorityQueuePool() { + // Non virtual inline destructor -- never inherit this class + ~WordsPriorityQueuePool() { // Note: these explicit calls to the destructor match the calls to placement new() above. if (mMasterQueue) mMasterQueue->~WordsPriorityQueue(); for (int i = 0; i < MULTIPLE_WORDS_SUGGESTION_MAX_WORDS * SUB_QUEUE_MAX_COUNT; ++i) { @@ -68,7 +69,7 @@ class WordsPriorityQueuePool { } } - inline void clearSubQueue(const int wordIndex) { + AK_FORCE_INLINE void clearSubQueue(const int wordIndex) { for (int i = 0; i < SUB_QUEUE_MAX_COUNT; ++i) { WordsPriorityQueue *queue = getSubQueue(wordIndex, i); if (queue) { -- cgit v1.2.3-83-g751a From 5f2fa6b82cbb6714ab2996aebc16f10c62d0e673 Mon Sep 17 00:00:00 2001 From: Ken Wakasa Date: Mon, 5 Nov 2012 20:16:52 +0900 Subject: Tidy up visibility of members of BinaryFormat. Change-Id: I38a00076b82de8e1a19209c67954fe01585f7943 --- native/jni/src/binary_format.h | 53 +++++++++++++++++++++--------------------- 1 file changed, 27 insertions(+), 26 deletions(-) (limited to 'native/jni/src') diff --git a/native/jni/src/binary_format.h b/native/jni/src/binary_format.h index 7bb976097..9a8c315f7 100644 --- a/native/jni/src/binary_format.h +++ b/native/jni/src/binary_format.h @@ -28,10 +28,6 @@ class BinaryFormat { public: // Mask and flags for children address type selection. static const int MASK_GROUP_ADDRESS_TYPE = 0xC0; - static const int FLAG_GROUP_ADDRESS_TYPE_NOADDRESS = 0x00; - static const int FLAG_GROUP_ADDRESS_TYPE_ONEBYTE = 0x40; - static const int FLAG_GROUP_ADDRESS_TYPE_TWOBYTES = 0x80; - static const int FLAG_GROUP_ADDRESS_TYPE_THREEBYTES = 0xC0; // Flag for single/multiple char group static const int FLAG_HAS_MULTIPLE_CHARS = 0x20; @@ -61,23 +57,9 @@ class BinaryFormat { // Mask and flags for attribute address type selection. static const int MASK_ATTRIBUTE_ADDRESS_TYPE = 0x30; - static const int FLAG_ATTRIBUTE_ADDRESS_TYPE_ONEBYTE = 0x10; - static const int FLAG_ATTRIBUTE_ADDRESS_TYPE_TWOBYTES = 0x20; - static const int FLAG_ATTRIBUTE_ADDRESS_TYPE_THREEBYTES = 0x30; - - const static int UNKNOWN_FORMAT = -1; - // Originally, format version 1 had a 16-bit magic number, then the version number `01' - // then options that must be 0. Hence the first 32-bits of the format are always as follow - // and it's okay to consider them a magic number as a whole. - const static uint32_t FORMAT_VERSION_1_MAGIC_NUMBER = 0x78B10100; - const static unsigned int FORMAT_VERSION_1_HEADER_SIZE = 5; - // The versions of Latin IME that only handle format version 1 only test for the magic - // number, so we had to change it so that version 2 files would be rejected by older - // implementations. On this occasion, we made the magic number 32 bits long. - const static uint32_t FORMAT_VERSION_2_MAGIC_NUMBER = 0x9BC13AFE; - const static int CHARACTER_ARRAY_TERMINATOR_SIZE = 1; - const static int SHORTCUT_LIST_SIZE_SIZE = 2; + static const int UNKNOWN_FORMAT = -1; + static const int SHORTCUT_LIST_SIZE_SIZE = 2; static int detectFormat(const uint8_t *const dict); static unsigned int getHeaderSize(const uint8_t *const dict); @@ -90,7 +72,6 @@ class BinaryFormat { static int skipChildrenPosition(const uint8_t flags, const int pos); static int skipFrequency(const uint8_t flags, const int pos); static int skipShortcuts(const uint8_t *const dict, const uint8_t flags, const int pos); - static int skipBigrams(const uint8_t *const dict, const uint8_t flags, const int pos); static int skipChildrenPosAndAttributes(const uint8_t *const dict, const uint8_t flags, const int pos); static int readChildrenPosition(const uint8_t *const dict, const uint8_t flags, const int pos); @@ -113,14 +94,34 @@ class BinaryFormat { REQUIRES_GERMAN_UMLAUT_PROCESSING = 0x1, REQUIRES_FRENCH_LIGATURES_PROCESSING = 0x4 }; - const static unsigned int NO_FLAGS = 0; private: DISALLOW_IMPLICIT_CONSTRUCTORS(BinaryFormat); - const static int32_t MINIMAL_ONE_BYTE_CHARACTER_VALUE = 0x20; - const static int32_t CHARACTER_ARRAY_TERMINATOR = 0x1F; - const static int MULTIPLE_BYTE_CHARACTER_ADDITIONAL_SIZE = 2; + static const int FLAG_GROUP_ADDRESS_TYPE_NOADDRESS = 0x00; + static const int FLAG_GROUP_ADDRESS_TYPE_ONEBYTE = 0x40; + static const int FLAG_GROUP_ADDRESS_TYPE_TWOBYTES = 0x80; + static const int FLAG_GROUP_ADDRESS_TYPE_THREEBYTES = 0xC0; + static const int FLAG_ATTRIBUTE_ADDRESS_TYPE_ONEBYTE = 0x10; + static const int FLAG_ATTRIBUTE_ADDRESS_TYPE_TWOBYTES = 0x20; + static const int FLAG_ATTRIBUTE_ADDRESS_TYPE_THREEBYTES = 0x30; + + // Originally, format version 1 had a 16-bit magic number, then the version number `01' + // then options that must be 0. Hence the first 32-bits of the format are always as follow + // and it's okay to consider them a magic number as a whole. + static const uint32_t FORMAT_VERSION_1_MAGIC_NUMBER = 0x78B10100; + static const unsigned int FORMAT_VERSION_1_HEADER_SIZE = 5; + // The versions of Latin IME that only handle format version 1 only test for the magic + // number, so we had to change it so that version 2 files would be rejected by older + // implementations. On this occasion, we made the magic number 32 bits long. + static const uint32_t FORMAT_VERSION_2_MAGIC_NUMBER = 0x9BC13AFE; + + static const int CHARACTER_ARRAY_TERMINATOR_SIZE = 1; + static const int32_t MINIMAL_ONE_BYTE_CHARACTER_VALUE = 0x20; + static const int32_t CHARACTER_ARRAY_TERMINATOR = 0x1F; + static const int MULTIPLE_BYTE_CHARACTER_ADDITIONAL_SIZE = 2; + static const unsigned int NO_FLAGS = 0; static int skipAllAttributes(const uint8_t *const dict, const uint8_t flags, const int pos); + static int skipBigrams(const uint8_t *const dict, const uint8_t flags, const int pos); }; AK_FORCE_INLINE int BinaryFormat::detectFormat(const uint8_t *const dict) { @@ -148,7 +149,7 @@ AK_FORCE_INLINE int BinaryFormat::detectFormat(const uint8_t *const dict) { inline unsigned int BinaryFormat::getFlags(const uint8_t *const dict) { switch (detectFormat(dict)) { case 1: - return NO_FLAGS; + return NO_FLAGS; // TODO: NO_FLAGS is unused anywhere else? default: return (dict[6] << 8) + dict[7]; } -- cgit v1.2.3-83-g751a