13e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka/* 23e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka * Copyright (C) 2012 The Android Open Source Project 33e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka * 43e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka * Licensed under the Apache License, Version 2.0 (the "License"); 53e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka * you may not use this file except in compliance with the License. 63e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka * You may obtain a copy of the License at 73e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka * 83e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka * http://www.apache.org/licenses/LICENSE-2.0 93e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka * 103e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka * Unless required by applicable law or agreed to in writing, software 113e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka * distributed under the License is distributed on an "AS IS" BASIS, 123e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 133e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka * See the License for the specific language governing permissions and 143e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka * limitations under the License. 153e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka */ 163e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka 17f88f9dbbdec309c01feda06edc142470ba13cb2fKeisuke Kuroyanagi#define LOG_TAG "LatinIME: proximity_info_state.cpp" 18f88f9dbbdec309c01feda06edc142470ba13cb2fKeisuke Kuroyanagi 1929432f843a8cd6ffb2be286104964592e80d77c9Ken Wakasa#include "suggest/core/layout/proximity_info_state.h" 2029432f843a8cd6ffb2be286104964592e80d77c9Ken Wakasa 21865e6cf49764f3a411ee32861d927b15653ee398Keisuke Kuroyanagi#include <algorithm> 223e0777e726ce40b4c4b65174a21db41c19f04602Keisuke Kuroyanagi#include <cstring> // for memset() and memmove() 23806eba452423e5e5971ef096dfae3fed180db665Keisuke Kuroyanagi#include <sstream> // for debug prints 248ca9be17db2f1845c7c7a3b584507cf60c9ca53dKen Wakasa#include <unordered_map> 25e5cdd21102e4e49b18c696261a084783eb6d7e7aSatoshi Kataoka#include <vector> 263e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka 273e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka#include "defines.h" 2829432f843a8cd6ffb2be286104964592e80d77c9Ken Wakasa#include "suggest/core/layout/geometry_utils.h" 2929432f843a8cd6ffb2be286104964592e80d77c9Ken Wakasa#include "suggest/core/layout/proximity_info.h" 3029432f843a8cd6ffb2be286104964592e80d77c9Ken Wakasa#include "suggest/core/layout/proximity_info_state_utils.h" 31addea83bad5751308fef508d79c6989b8872f050Ken Wakasa#include "utils/char_utils.h" 323e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka 333e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataokanamespace latinime { 34764dd712032d7b8012797b1116b523bef7b907f3Ken Wakasa 352fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasaint ProximityInfoState::getPrimaryOriginalCodePointAt(const int index) const { 362fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa const int primaryCodePoint = getPrimaryCodePointAt(index); 372fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa const int keyIndex = mProximityInfo->getKeyIndexOf(primaryCodePoint); 382fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa return mProximityInfo->getOriginalCodePointOf(keyIndex); 392fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa} 402fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa 41a1d84bcf8ffd031c135b6f3f8c94b6732071849bSatoshi Kataoka// TODO: Remove the dependency of "isGeometric" 42233aad5e5c7567a97af30f38f50a65365f729dfeSatoshi Kataokavoid ProximityInfoState::initInputParams(const int pointerId, const float maxPointToKeyLength, 431e61493c50082264caaef862df02b1ccc84dc396Ken Wakasa const ProximityInfo *proximityInfo, const int *const inputCodes, const int inputSize, 44687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka const int *const xCoordinates, const int *const yCoordinates, const int *const times, 45687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka const int *const pointerIds, const bool isGeometric) { 469d18c6dd38c4d5632a5d5a5c26f567b9f6f7f969Satoshi Kataoka ASSERT(isGeometric || (inputSize < MAX_WORD_LENGTH)); 47f1233b58c2d81b575c92339f146cfe0f73a992faKeisuke Kuroyanagi mIsContinuousSuggestionPossible = (mHasBeenUpdatedByGeometricInput != isGeometric) ? 48f1233b58c2d81b575c92339f146cfe0f73a992faKeisuke Kuroyanagi false : ProximityInfoStateUtils::checkAndReturnIsContinuousSuggestionPossible( 49394b0bd345f33b1314613a433478fd0bb711e0f7Satoshi Kataoka inputSize, xCoordinates, yCoordinates, times, mSampledInputSize, 50394b0bd345f33b1314613a433478fd0bb711e0f7Satoshi Kataoka &mSampledInputXs, &mSampledInputYs, &mSampledTimes, &mSampledInputIndice); 51d1fff1adcc0693286ace156eaf467ccccbc0a719Satoshi Kataoka if (DEBUG_DICT) { 52394b0bd345f33b1314613a433478fd0bb711e0f7Satoshi Kataoka AKLOGI("isContinuousSuggestionPossible = %s", 53394b0bd345f33b1314613a433478fd0bb711e0f7Satoshi Kataoka (mIsContinuousSuggestionPossible ? "true" : "false")); 54d1fff1adcc0693286ace156eaf467ccccbc0a719Satoshi Kataoka } 55096f35ff4b5413906e2a339663baf16e5dabaf64Keisuke Kuroyanagi 564a3db7057f77dc85311fb1f94934b5a004ab613eSatoshi Kataoka mProximityInfo = proximityInfo; 574a3db7057f77dc85311fb1f94934b5a004ab613eSatoshi Kataoka mHasTouchPositionCorrectionData = proximityInfo->hasTouchPositionCorrectionData(); 584a3db7057f77dc85311fb1f94934b5a004ab613eSatoshi Kataoka mMostCommonKeyWidthSquare = proximityInfo->getMostCommonKeyWidthSquare(); 594a3db7057f77dc85311fb1f94934b5a004ab613eSatoshi Kataoka mKeyCount = proximityInfo->getKeyCount(); 604a3db7057f77dc85311fb1f94934b5a004ab613eSatoshi Kataoka mCellHeight = proximityInfo->getCellHeight(); 614a3db7057f77dc85311fb1f94934b5a004ab613eSatoshi Kataoka mCellWidth = proximityInfo->getCellWidth(); 624a3db7057f77dc85311fb1f94934b5a004ab613eSatoshi Kataoka mGridHeight = proximityInfo->getGridWidth(); 634a3db7057f77dc85311fb1f94934b5a004ab613eSatoshi Kataoka mGridWidth = proximityInfo->getGridHeight(); 643e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka 65bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka memset(mInputProximities, 0, sizeof(mInputProximities)); 663e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka 6708f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka if (!isGeometric && pointerId == 0) { 68bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka mProximityInfo->initializeProximities(inputCodes, xCoordinates, yCoordinates, 69bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka inputSize, mInputProximities); 703e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka } 71687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka 72687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka /////////////////////// 73687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka // Setup touch points 74096f35ff4b5413906e2a339663baf16e5dabaf64Keisuke Kuroyanagi int pushTouchPointStartIndex = 0; 75096f35ff4b5413906e2a339663baf16e5dabaf64Keisuke Kuroyanagi int lastSavedInputSize = 0; 7608f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka mMaxPointToKeyLength = maxPointToKeyLength; 7720b6775acc957896bdb038dfd99794d6cd7cea5aSatoshi Kataoka mSampledInputSize = 0; 7820b6775acc957896bdb038dfd99794d6cd7cea5aSatoshi Kataoka mMostProbableStringProbability = 0.0f; 7920b6775acc957896bdb038dfd99794d6cd7cea5aSatoshi Kataoka 80394b0bd345f33b1314613a433478fd0bb711e0f7Satoshi Kataoka if (mIsContinuousSuggestionPossible && mSampledInputIndice.size() > 1) { 81096f35ff4b5413906e2a339663baf16e5dabaf64Keisuke Kuroyanagi // Just update difference. 8220b6775acc957896bdb038dfd99794d6cd7cea5aSatoshi Kataoka // Previous two points are never skipped. Thus, we pop 2 input point data here. 8320b6775acc957896bdb038dfd99794d6cd7cea5aSatoshi Kataoka pushTouchPointStartIndex = ProximityInfoStateUtils::trimLastTwoTouchPoints( 8420b6775acc957896bdb038dfd99794d6cd7cea5aSatoshi Kataoka &mSampledInputXs, &mSampledInputYs, &mSampledTimes, &mSampledLengthCache, 8520b6775acc957896bdb038dfd99794d6cd7cea5aSatoshi Kataoka &mSampledInputIndice); 86feec20a692c9ffdecf7855a45531a12f129086caSatoshi Kataoka lastSavedInputSize = mSampledInputXs.size(); 87096f35ff4b5413906e2a339663baf16e5dabaf64Keisuke Kuroyanagi } else { 88096f35ff4b5413906e2a339663baf16e5dabaf64Keisuke Kuroyanagi // Clear all data. 89feec20a692c9ffdecf7855a45531a12f129086caSatoshi Kataoka mSampledInputXs.clear(); 90feec20a692c9ffdecf7855a45531a12f129086caSatoshi Kataoka mSampledInputYs.clear(); 91d7a8fbf6a9ec8828d4b6d1c615a6c605bbe5b72eSatoshi Kataoka mSampledTimes.clear(); 92d7a8fbf6a9ec8828d4b6d1c615a6c605bbe5b72eSatoshi Kataoka mSampledInputIndice.clear(); 93d7a8fbf6a9ec8828d4b6d1c615a6c605bbe5b72eSatoshi Kataoka mSampledLengthCache.clear(); 94837f46dcb35a8f42a6bd5bc5fc6395d7386acb81Satoshi Kataoka mSampledNormalizedSquaredLengthCache.clear(); 95e5cdd21102e4e49b18c696261a084783eb6d7e7aSatoshi Kataoka mSampledSearchKeySets.clear(); 969af533538ea749d7c930bb3125fa4d3e4feb8478Satoshi Kataoka mSpeedRates.clear(); 976ae8dd4343445d2df4444388b605d2aa930fa2a0Satoshi Kataoka mBeelineSpeedPercentiles.clear(); 98806eba452423e5e5971ef096dfae3fed180db665Keisuke Kuroyanagi mCharProbabilities.clear(); 991e06a4d8e9e71188ed685282155ea52a48ddc050Keisuke Kuroyanagi mDirections.clear(); 100096f35ff4b5413906e2a339663baf16e5dabaf64Keisuke Kuroyanagi } 10120b6775acc957896bdb038dfd99794d6cd7cea5aSatoshi Kataoka 1029182daf98c0d1db897e82b77c2196b7f9aad6f01Satoshi Kataoka if (DEBUG_GEO_FULL) { 1039182daf98c0d1db897e82b77c2196b7f9aad6f01Satoshi Kataoka AKLOGI("Init ProximityInfoState: reused points = %d, last input size = %d", 1049182daf98c0d1db897e82b77c2196b7f9aad6f01Satoshi Kataoka pushTouchPointStartIndex, lastSavedInputSize); 1059182daf98c0d1db897e82b77c2196b7f9aad6f01Satoshi Kataoka } 106d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi 107687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka if (xCoordinates && yCoordinates) { 10828c008421cc5d97da8e470dbc934a2891daf9997Ken Wakasa mSampledInputSize = ProximityInfoStateUtils::updateTouchPoints(mProximityInfo, 10928c008421cc5d97da8e470dbc934a2891daf9997Ken Wakasa mMaxPointToKeyLength, mInputProximities, xCoordinates, yCoordinates, times, 1100052dbda762b1871c3214a6abeb5e89f11e091cdKeisuke Kuroynagi pointerIds, inputSize, isGeometric, pointerId, 111a1d84bcf8ffd031c135b6f3f8c94b6732071849bSatoshi Kataoka pushTouchPointStartIndex, &mSampledInputXs, &mSampledInputYs, &mSampledTimes, 112a1d84bcf8ffd031c135b6f3f8c94b6732071849bSatoshi Kataoka &mSampledLengthCache, &mSampledInputIndice); 1133e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka } 114687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka 115feec20a692c9ffdecf7855a45531a12f129086caSatoshi Kataoka if (mSampledInputSize > 0 && isGeometric) { 11628c008421cc5d97da8e470dbc934a2891daf9997Ken Wakasa mAverageSpeed = ProximityInfoStateUtils::refreshSpeedRates(inputSize, xCoordinates, 11728c008421cc5d97da8e470dbc934a2891daf9997Ken Wakasa yCoordinates, times, lastSavedInputSize, mSampledInputSize, &mSampledInputXs, 11828c008421cc5d97da8e470dbc934a2891daf9997Ken Wakasa &mSampledInputYs, &mSampledTimes, &mSampledLengthCache, &mSampledInputIndice, 11928c008421cc5d97da8e470dbc934a2891daf9997Ken Wakasa &mSpeedRates, &mDirections); 12028c008421cc5d97da8e470dbc934a2891daf9997Ken Wakasa ProximityInfoStateUtils::refreshBeelineSpeedRates(mProximityInfo->getMostCommonKeyWidth(), 12128c008421cc5d97da8e470dbc934a2891daf9997Ken Wakasa mAverageSpeed, inputSize, xCoordinates, yCoordinates, times, mSampledInputSize, 12228c008421cc5d97da8e470dbc934a2891daf9997Ken Wakasa &mSampledInputXs, &mSampledInputYs, &mSampledInputIndice, 12328c008421cc5d97da8e470dbc934a2891daf9997Ken Wakasa &mBeelineSpeedPercentiles); 124ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi } 125ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi 126feec20a692c9ffdecf7855a45531a12f129086caSatoshi Kataoka if (mSampledInputSize > 0) { 12728c008421cc5d97da8e470dbc934a2891daf9997Ken Wakasa ProximityInfoStateUtils::initGeometricDistanceInfos(mProximityInfo, mSampledInputSize, 1280052dbda762b1871c3214a6abeb5e89f11e091cdKeisuke Kuroynagi lastSavedInputSize, isGeometric, &mSampledInputXs, &mSampledInputYs, 129bc9500fb14622f8b185e30a10a7c0b4c5a29930aKeisuke Kuroyanagi &mSampledNormalizedSquaredLengthCache); 130ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi if (isGeometric) { 131ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi // updates probabilities of skipping or mapping each key for all points. 132d4828d5053ac30476b884c177235be0cac982c92Satoshi Kataoka ProximityInfoStateUtils::updateAlignPointProbabilities( 133d4828d5053ac30476b884c177235be0cac982c92Satoshi Kataoka mMaxPointToKeyLength, mProximityInfo->getMostCommonKeyWidth(), 134d7a8fbf6a9ec8828d4b6d1c615a6c605bbe5b72eSatoshi Kataoka mProximityInfo->getKeyCount(), lastSavedInputSize, mSampledInputSize, 135d7a8fbf6a9ec8828d4b6d1c615a6c605bbe5b72eSatoshi Kataoka &mSampledInputXs, &mSampledInputYs, &mSpeedRates, &mSampledLengthCache, 136bc9500fb14622f8b185e30a10a7c0b4c5a29930aKeisuke Kuroyanagi &mSampledNormalizedSquaredLengthCache, mProximityInfo, &mCharProbabilities); 137e5cdd21102e4e49b18c696261a084783eb6d7e7aSatoshi Kataoka ProximityInfoStateUtils::updateSampledSearchKeySets(mProximityInfo, 138e5aad5646309e80e1cd71533fb47a6be43f3aa2fSatoshi Kataoka mSampledInputSize, lastSavedInputSize, &mSampledLengthCache, 139bc9500fb14622f8b185e30a10a7c0b4c5a29930aKeisuke Kuroyanagi &mCharProbabilities, &mSampledSearchKeySets, 140e5cdd21102e4e49b18c696261a084783eb6d7e7aSatoshi Kataoka &mSampledSearchKeyVectors); 14120b6775acc957896bdb038dfd99794d6cd7cea5aSatoshi Kataoka mMostProbableStringProbability = ProximityInfoStateUtils::getMostProbableString( 14220b6775acc957896bdb038dfd99794d6cd7cea5aSatoshi Kataoka mProximityInfo, mSampledInputSize, &mCharProbabilities, mMostProbableString); 14320b6775acc957896bdb038dfd99794d6cd7cea5aSatoshi Kataoka 144687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka } 145687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka } 14608f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka 147806eba452423e5e5971ef096dfae3fed180db665Keisuke Kuroyanagi if (DEBUG_SAMPLING_POINTS) { 148d7a8fbf6a9ec8828d4b6d1c615a6c605bbe5b72eSatoshi Kataoka ProximityInfoStateUtils::dump(isGeometric, inputSize, xCoordinates, yCoordinates, 149e2912d17e4dab75b81f4c9e41a539e491ac059caSatoshi Kataoka mSampledInputSize, &mSampledInputXs, &mSampledInputYs, &mSampledTimes, &mSpeedRates, 150d7a8fbf6a9ec8828d4b6d1c615a6c605bbe5b72eSatoshi Kataoka &mBeelineSpeedPercentiles); 151806eba452423e5e5971ef096dfae3fed180db665Keisuke Kuroyanagi } 152687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka // end 153687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka /////////////////////// 154687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka 155feec20a692c9ffdecf7855a45531a12f129086caSatoshi Kataoka mTouchPositionCorrectionEnabled = mSampledInputSize > 0 && mHasTouchPositionCorrectionData 1560edab9d2fcc30667c79aa9221dbb27f042d8b455Satoshi Kataoka && xCoordinates && yCoordinates; 15708f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka if (!isGeometric && pointerId == 0) { 158d7a8fbf6a9ec8828d4b6d1c615a6c605bbe5b72eSatoshi Kataoka ProximityInfoStateUtils::initPrimaryInputWord( 159d7a8fbf6a9ec8828d4b6d1c615a6c605bbe5b72eSatoshi Kataoka inputSize, mInputProximities, mPrimaryInputWord); 1603e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka } 161952ec4977d772607140773ae7d8868f86a7e0097Satoshi Kataoka if (DEBUG_GEO_FULL) { 162feec20a692c9ffdecf7855a45531a12f129086caSatoshi Kataoka AKLOGI("ProximityState init finished: %d points out of %d", mSampledInputSize, inputSize); 163feec20a692c9ffdecf7855a45531a12f129086caSatoshi Kataoka } 164f1233b58c2d81b575c92339f146cfe0f73a992faKeisuke Kuroyanagi mHasBeenUpdatedByGeometricInput = isGeometric; 165feec20a692c9ffdecf7855a45531a12f129086caSatoshi Kataoka} 166feec20a692c9ffdecf7855a45531a12f129086caSatoshi Kataoka 1670519fdd18ac4414b8298d3338db1c8ccce032170Satoshi Kataoka// This function basically converts from a length to an edit distance. Accordingly, it's obviously 1680519fdd18ac4414b8298d3338db1c8ccce032170Satoshi Kataoka// wrong to compare with mMaxPointToKeyLength. 1690519fdd18ac4414b8298d3338db1c8ccce032170Satoshi Kataokafloat ProximityInfoState::getPointToKeyLength( 1702192d08b9cca6a40d834d6a5001d19b5845ed8a0Tom Ouyang const int inputIndex, const int codePoint) const { 171ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi const int keyId = mProximityInfo->getKeyIndexOf(codePoint); 172ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi if (keyId != NOT_AN_INDEX) { 173ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi const int index = inputIndex * mProximityInfo->getKeyCount() + keyId; 174865e6cf49764f3a411ee32861d927b15653ee398Keisuke Kuroyanagi return std::min(mSampledNormalizedSquaredLengthCache[index], mMaxPointToKeyLength); 175ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi } 176464d3ba43257da34ab165da8ba0af11e928aae5cKen Wakasa if (CharUtils::isIntentionalOmissionCodePoint(codePoint)) { 177806eba452423e5e5971ef096dfae3fed180db665Keisuke Kuroyanagi return 0.0f; 178806eba452423e5e5971ef096dfae3fed180db665Keisuke Kuroyanagi } 179ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi // If the char is not a key on the keyboard then return the max length. 180830ba67498c6da53b38212dd9ac5ba318a00de11Satoshi Kataoka return static_cast<float>(MAX_VALUE_FOR_WEIGHTING); 181806eba452423e5e5971ef096dfae3fed180db665Keisuke Kuroyanagi} 182806eba452423e5e5971ef096dfae3fed180db665Keisuke Kuroyanagi 1830519fdd18ac4414b8298d3338db1c8ccce032170Satoshi Kataokafloat ProximityInfoState::getPointToKeyByIdLength( 1842192d08b9cca6a40d834d6a5001d19b5845ed8a0Tom Ouyang const int inputIndex, const int keyId) const { 185d4828d5053ac30476b884c177235be0cac982c92Satoshi Kataoka return ProximityInfoStateUtils::getPointToKeyByIdLength(mMaxPointToKeyLength, 186837f46dcb35a8f42a6bd5bc5fc6395d7386acb81Satoshi Kataoka &mSampledNormalizedSquaredLengthCache, mProximityInfo->getKeyCount(), inputIndex, 187837f46dcb35a8f42a6bd5bc5fc6395d7386acb81Satoshi Kataoka keyId); 1880519fdd18ac4414b8298d3338db1c8ccce032170Satoshi Kataoka} 1890519fdd18ac4414b8298d3338db1c8ccce032170Satoshi Kataoka 1902c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa// In the following function, c is the current character of the dictionary word currently examined. 1912c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa// currentChars is an array containing the keys close to the character the user actually typed at 1922c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa// the same position. We want to see if c is in it: if so, then the word contains at that position 1932c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa// a character close to what the user typed. 1942c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa// What the user typed is actually the first character of the array. 195697a9d3541dd5b643664fc1af9b3265267370127Satoshi Kataoka// proximityIndex is a pointer to the variable where getProximityType returns the index of c 1962c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa// in the proximity chars of the input index. 1972c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa// Notice : accented characters do not have a proximity list, so they are alone in their list. The 1982c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa// non-accented version of the character should be considered "close", but not the other keys close 1992c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa// to the non-accented version. 200697a9d3541dd5b643664fc1af9b3265267370127Satoshi KataokaProximityType ProximityInfoState::getProximityType(const int index, const int codePoint, 2012c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa const bool checkProximityChars, int *proximityIndex) const { 2022c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa const int *currentCodePoints = getProximityCodePointsAt(index); 2032c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa const int firstCodePoint = currentCodePoints[0]; 204464d3ba43257da34ab165da8ba0af11e928aae5cKen Wakasa const int baseLowerC = CharUtils::toBaseLowerCase(codePoint); 2052c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa 2062c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa // The first char in the array is what user typed. If it matches right away, that means the 2072c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa // user typed that same char for this pos. 208697a9d3541dd5b643664fc1af9b3265267370127Satoshi Kataoka if (firstCodePoint == baseLowerC || firstCodePoint == codePoint) { 209f4425aaae971fe78d44530ebe01cf7a59b2e47aaSatoshi Kataoka return MATCH_CHAR; 2102c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa } 2112c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa 212f4425aaae971fe78d44530ebe01cf7a59b2e47aaSatoshi Kataoka if (!checkProximityChars) return SUBSTITUTION_CHAR; 2132c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa 2142c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa // If the non-accented, lowercased version of that first character matches c, then we have a 2152c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa // non-accented version of the accented character the user typed. Treat it as a close char. 216464d3ba43257da34ab165da8ba0af11e928aae5cKen Wakasa if (CharUtils::toBaseLowerCase(firstCodePoint) == baseLowerC) { 217f4425aaae971fe78d44530ebe01cf7a59b2e47aaSatoshi Kataoka return PROXIMITY_CHAR; 2182c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa } 2192c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa 2202c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa // Not an exact nor an accent-alike match: search the list of close keys 2212c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa int j = 1; 2226c22439bf80da08576e86c1282afc5cfa431e235Ken Wakasa while (j < MAX_PROXIMITY_CHARS_SIZE 2232c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa && currentCodePoints[j] > ADDITIONAL_PROXIMITY_CHAR_DELIMITER_CODE) { 224697a9d3541dd5b643664fc1af9b3265267370127Satoshi Kataoka const bool matched = (currentCodePoints[j] == baseLowerC 225697a9d3541dd5b643664fc1af9b3265267370127Satoshi Kataoka || currentCodePoints[j] == codePoint); 2262c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa if (matched) { 2272c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa if (proximityIndex) { 2282c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa *proximityIndex = j; 2292c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa } 230f4425aaae971fe78d44530ebe01cf7a59b2e47aaSatoshi Kataoka return PROXIMITY_CHAR; 2312c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa } 2322c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa ++j; 2332c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa } 2346c22439bf80da08576e86c1282afc5cfa431e235Ken Wakasa if (j < MAX_PROXIMITY_CHARS_SIZE 2352c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa && currentCodePoints[j] == ADDITIONAL_PROXIMITY_CHAR_DELIMITER_CODE) { 2362c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa ++j; 2376c22439bf80da08576e86c1282afc5cfa431e235Ken Wakasa while (j < MAX_PROXIMITY_CHARS_SIZE 2382c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa && currentCodePoints[j] > ADDITIONAL_PROXIMITY_CHAR_DELIMITER_CODE) { 239697a9d3541dd5b643664fc1af9b3265267370127Satoshi Kataoka const bool matched = (currentCodePoints[j] == baseLowerC 240697a9d3541dd5b643664fc1af9b3265267370127Satoshi Kataoka || currentCodePoints[j] == codePoint); 2412c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa if (matched) { 2422c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa if (proximityIndex) { 2432c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa *proximityIndex = j; 2442c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa } 2452c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa return ADDITIONAL_PROXIMITY_CHAR; 2462c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa } 2472c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa ++j; 2482c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa } 2492c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa } 250f4425aaae971fe78d44530ebe01cf7a59b2e47aaSatoshi Kataoka // Was not included, signal this as a substitution character. 251f4425aaae971fe78d44530ebe01cf7a59b2e47aaSatoshi Kataoka return SUBSTITUTION_CHAR; 2522c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa} 2532c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa 254697a9d3541dd5b643664fc1af9b3265267370127Satoshi KataokaProximityType ProximityInfoState::getProximityTypeG(const int index, const int codePoint) const { 255697a9d3541dd5b643664fc1af9b3265267370127Satoshi Kataoka if (!isUsed()) { 256f4425aaae971fe78d44530ebe01cf7a59b2e47aaSatoshi Kataoka return UNRELATED_CHAR; 257697a9d3541dd5b643664fc1af9b3265267370127Satoshi Kataoka } 25884c52a3c813669d70305e584763549c989d9305dKeisuke Kuroyanagi const int sampledSearchKeyVectorsSize = static_cast<int>(mSampledSearchKeyVectors.size()); 25984c52a3c813669d70305e584763549c989d9305dKeisuke Kuroyanagi if (index < 0 || index >= sampledSearchKeyVectorsSize) { 26084c52a3c813669d70305e584763549c989d9305dKeisuke Kuroyanagi AKLOGE("getProximityTypeG() is called with an invalid index(%d). " 26184c52a3c813669d70305e584763549c989d9305dKeisuke Kuroyanagi "mSampledSearchKeyVectors.size() = %d, codePoint = %x.", index, 26284c52a3c813669d70305e584763549c989d9305dKeisuke Kuroyanagi sampledSearchKeyVectorsSize, codePoint); 26384c52a3c813669d70305e584763549c989d9305dKeisuke Kuroyanagi ASSERT(false); 26484c52a3c813669d70305e584763549c989d9305dKeisuke Kuroyanagi return UNRELATED_CHAR; 26584c52a3c813669d70305e584763549c989d9305dKeisuke Kuroyanagi } 266464d3ba43257da34ab165da8ba0af11e928aae5cKen Wakasa const int lowerCodePoint = CharUtils::toLowerCase(codePoint); 267464d3ba43257da34ab165da8ba0af11e928aae5cKen Wakasa const int baseLowerCodePoint = CharUtils::toBaseCodePoint(lowerCodePoint); 268697a9d3541dd5b643664fc1af9b3265267370127Satoshi Kataoka for (int i = 0; i < static_cast<int>(mSampledSearchKeyVectors[index].size()); ++i) { 269697a9d3541dd5b643664fc1af9b3265267370127Satoshi Kataoka if (mSampledSearchKeyVectors[index][i] == lowerCodePoint 270697a9d3541dd5b643664fc1af9b3265267370127Satoshi Kataoka || mSampledSearchKeyVectors[index][i] == baseLowerCodePoint) { 271f4425aaae971fe78d44530ebe01cf7a59b2e47aaSatoshi Kataoka return MATCH_CHAR; 272697a9d3541dd5b643664fc1af9b3265267370127Satoshi Kataoka } 273697a9d3541dd5b643664fc1af9b3265267370127Satoshi Kataoka } 274f4425aaae971fe78d44530ebe01cf7a59b2e47aaSatoshi Kataoka return UNRELATED_CHAR; 275697a9d3541dd5b643664fc1af9b3265267370127Satoshi Kataoka} 276697a9d3541dd5b643664fc1af9b3265267370127Satoshi Kataoka 277ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagibool ProximityInfoState::isKeyInSerchKeysAfterIndex(const int index, const int keyId) const { 27820b6775acc957896bdb038dfd99794d6cd7cea5aSatoshi Kataoka ASSERT(keyId >= 0 && index >= 0 && index < mSampledInputSize); 279e5cdd21102e4e49b18c696261a084783eb6d7e7aSatoshi Kataoka return mSampledSearchKeySets[index].test(keyId); 280ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi} 281ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi 282ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagifloat ProximityInfoState::getDirection(const int index0, const int index1) const { 283ee62b78c9675bddaf2437e0cf521f6115e1d9febSatoshi Kataoka return ProximityInfoStateUtils::getDirection( 284ee62b78c9675bddaf2437e0cf521f6115e1d9febSatoshi Kataoka &mSampledInputXs, &mSampledInputYs, index0, index1); 285ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi} 286ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi 287e0349619acdba79223390c9925d81f7e88c7f8adSatoshi Kataokafloat ProximityInfoState::getMostProbableString(int *const codePointBuf) const { 2883e0777e726ce40b4c4b65174a21db41c19f04602Keisuke Kuroyanagi memmove(codePointBuf, mMostProbableString, sizeof(mMostProbableString)); 28920b6775acc957896bdb038dfd99794d6cd7cea5aSatoshi Kataoka return mMostProbableStringProbability; 290ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi} 291ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi 292f32869c6b6296a8bf594abdf0b18281d9312e54fSatoshi Kataokabool ProximityInfoState::hasSpaceProximity(const int index) const { 293f32869c6b6296a8bf594abdf0b18281d9312e54fSatoshi Kataoka ASSERT(0 <= index && index < mSampledInputSize); 294f32869c6b6296a8bf594abdf0b18281d9312e54fSatoshi Kataoka return mProximityInfo->hasSpaceProximity(getInputX(index), getInputY(index)); 295f32869c6b6296a8bf594abdf0b18281d9312e54fSatoshi Kataoka} 296f32869c6b6296a8bf594abdf0b18281d9312e54fSatoshi Kataoka 297ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi// Returns a probability of mapping index to keyIndex. 298ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagifloat ProximityInfoState::getProbability(const int index, const int keyIndex) const { 299feec20a692c9ffdecf7855a45531a12f129086caSatoshi Kataoka ASSERT(0 <= index && index < mSampledInputSize); 3008ca9be17db2f1845c7c7a3b584507cf60c9ca53dKen Wakasa std::unordered_map<int, float>::const_iterator it = mCharProbabilities[index].find(keyIndex); 301ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi if (it != mCharProbabilities[index].end()) { 302ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi return it->second; 303ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi } 304830ba67498c6da53b38212dd9ac5ba318a00de11Satoshi Kataoka return static_cast<float>(MAX_VALUE_FOR_WEIGHTING); 305806eba452423e5e5971ef096dfae3fed180db665Keisuke Kuroyanagi} 3063e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka} // namespace latinime 307