proximity_info_state.cpp revision e5aad5646309e80e1cd71533fb47a6be43f3aa2f
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
1777e8e81ad95cfc1eb8f8407fc872674b8d08bbe9Ken Wakasa#include <cstring> // for memset()
18806eba452423e5e5971ef096dfae3fed180db665Keisuke Kuroyanagi#include <sstream> // for debug prints
193e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka
203e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka#define LOG_TAG "LatinIME: proximity_info_state.cpp"
213e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka
223e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka#include "defines.h"
236cee61deebd0ca2b85054ccc239523d1e5fdfab1Ken Wakasa#include "geometry_utils.h"
243e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka#include "proximity_info.h"
253e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka#include "proximity_info_state.h"
2647cc52415e3affb83eb4369190425b2a17b956c5Satoshi Kataoka#include "proximity_info_state_utils.h"
273e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka
283e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataokanamespace latinime {
29764dd712032d7b8012797b1116b523bef7b907f3Ken Wakasa
30764dd712032d7b8012797b1116b523bef7b907f3Ken Wakasaconst int ProximityInfoState::NOT_A_CODE = -1;
31764dd712032d7b8012797b1116b523bef7b907f3Ken Wakasa
32233aad5e5c7567a97af30f38f50a65365f729dfeSatoshi Kataokavoid ProximityInfoState::initInputParams(const int pointerId, const float maxPointToKeyLength,
331e61493c50082264caaef862df02b1ccc84dc396Ken Wakasa        const ProximityInfo *proximityInfo, const int *const inputCodes, const int inputSize,
34687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka        const int *const xCoordinates, const int *const yCoordinates, const int *const times,
35687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka        const int *const pointerIds, const bool isGeometric) {
36fe4f1ce26ca41ef51b5245d70e93b502f76262a5Satoshi Kataoka    mIsContinuationPossible = checkAndReturnIsContinuationPossible(
37fe4f1ce26ca41ef51b5245d70e93b502f76262a5Satoshi Kataoka            inputSize, xCoordinates, yCoordinates, times, isGeometric);
38096f35ff4b5413906e2a339663baf16e5dabaf64Keisuke Kuroyanagi
394a3db7057f77dc85311fb1f94934b5a004ab613eSatoshi Kataoka    mProximityInfo = proximityInfo;
404a3db7057f77dc85311fb1f94934b5a004ab613eSatoshi Kataoka    mHasTouchPositionCorrectionData = proximityInfo->hasTouchPositionCorrectionData();
414a3db7057f77dc85311fb1f94934b5a004ab613eSatoshi Kataoka    mMostCommonKeyWidthSquare = proximityInfo->getMostCommonKeyWidthSquare();
424a3db7057f77dc85311fb1f94934b5a004ab613eSatoshi Kataoka    mKeyCount = proximityInfo->getKeyCount();
434a3db7057f77dc85311fb1f94934b5a004ab613eSatoshi Kataoka    mCellHeight = proximityInfo->getCellHeight();
444a3db7057f77dc85311fb1f94934b5a004ab613eSatoshi Kataoka    mCellWidth = proximityInfo->getCellWidth();
454a3db7057f77dc85311fb1f94934b5a004ab613eSatoshi Kataoka    mGridHeight = proximityInfo->getGridWidth();
464a3db7057f77dc85311fb1f94934b5a004ab613eSatoshi Kataoka    mGridWidth = proximityInfo->getGridHeight();
473e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka
48bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka    memset(mInputProximities, 0, sizeof(mInputProximities));
493e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka
5008f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka    if (!isGeometric && pointerId == 0) {
51bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka        mProximityInfo->initializeProximities(inputCodes, xCoordinates, yCoordinates,
52bf78e1371c12d819020d60f0e585f5e6c26e6aa2Satoshi Kataoka                inputSize, mInputProximities);
533e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka    }
54687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka
55687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka    ///////////////////////
56687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka    // Setup touch points
57096f35ff4b5413906e2a339663baf16e5dabaf64Keisuke Kuroyanagi    int pushTouchPointStartIndex = 0;
58096f35ff4b5413906e2a339663baf16e5dabaf64Keisuke Kuroyanagi    int lastSavedInputSize = 0;
5908f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka    mMaxPointToKeyLength = maxPointToKeyLength;
60d7a8fbf6a9ec8828d4b6d1c615a6c605bbe5b72eSatoshi Kataoka    if (mIsContinuationPossible && mSampledInputIndice.size() > 1) {
61096f35ff4b5413906e2a339663baf16e5dabaf64Keisuke Kuroyanagi        // Just update difference.
62096f35ff4b5413906e2a339663baf16e5dabaf64Keisuke Kuroyanagi        // Two points prior is never skipped. Thus, we pop 2 input point data here.
63d7a8fbf6a9ec8828d4b6d1c615a6c605bbe5b72eSatoshi Kataoka        pushTouchPointStartIndex = mSampledInputIndice[mSampledInputIndice.size() - 2];
64096f35ff4b5413906e2a339663baf16e5dabaf64Keisuke Kuroyanagi        popInputData();
65096f35ff4b5413906e2a339663baf16e5dabaf64Keisuke Kuroyanagi        popInputData();
66feec20a692c9ffdecf7855a45531a12f129086caSatoshi Kataoka        lastSavedInputSize = mSampledInputXs.size();
67096f35ff4b5413906e2a339663baf16e5dabaf64Keisuke Kuroyanagi    } else {
68096f35ff4b5413906e2a339663baf16e5dabaf64Keisuke Kuroyanagi        // Clear all data.
69feec20a692c9ffdecf7855a45531a12f129086caSatoshi Kataoka        mSampledInputXs.clear();
70feec20a692c9ffdecf7855a45531a12f129086caSatoshi Kataoka        mSampledInputYs.clear();
71d7a8fbf6a9ec8828d4b6d1c615a6c605bbe5b72eSatoshi Kataoka        mSampledTimes.clear();
72d7a8fbf6a9ec8828d4b6d1c615a6c605bbe5b72eSatoshi Kataoka        mSampledInputIndice.clear();
73d7a8fbf6a9ec8828d4b6d1c615a6c605bbe5b72eSatoshi Kataoka        mSampledLengthCache.clear();
74e5aad5646309e80e1cd71533fb47a6be43f3aa2fSatoshi Kataoka        mSampledDistanceCache_G.clear();
75e5aad5646309e80e1cd71533fb47a6be43f3aa2fSatoshi Kataoka        mSampledNearKeysVector.clear();
76e5aad5646309e80e1cd71533fb47a6be43f3aa2fSatoshi Kataoka        mSampledSearchKeysVector.clear();
779af533538ea749d7c930bb3125fa4d3e4feb8478Satoshi Kataoka        mSpeedRates.clear();
786ae8dd4343445d2df4444388b605d2aa930fa2a0Satoshi Kataoka        mBeelineSpeedPercentiles.clear();
79806eba452423e5e5971ef096dfae3fed180db665Keisuke Kuroyanagi        mCharProbabilities.clear();
801e06a4d8e9e71188ed685282155ea52a48ddc050Keisuke Kuroyanagi        mDirections.clear();
81096f35ff4b5413906e2a339663baf16e5dabaf64Keisuke Kuroyanagi    }
829182daf98c0d1db897e82b77c2196b7f9aad6f01Satoshi Kataoka    if (DEBUG_GEO_FULL) {
839182daf98c0d1db897e82b77c2196b7f9aad6f01Satoshi Kataoka        AKLOGI("Init ProximityInfoState: reused points =  %d, last input size = %d",
849182daf98c0d1db897e82b77c2196b7f9aad6f01Satoshi Kataoka                pushTouchPointStartIndex, lastSavedInputSize);
859182daf98c0d1db897e82b77c2196b7f9aad6f01Satoshi Kataoka    }
86feec20a692c9ffdecf7855a45531a12f129086caSatoshi Kataoka    mSampledInputSize = 0;
87d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi
88687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka    if (xCoordinates && yCoordinates) {
8947cc52415e3affb83eb4369190425b2a17b956c5Satoshi Kataoka        mSampledInputSize = ProximityInfoStateUtils::updateTouchPoints(
9047cc52415e3affb83eb4369190425b2a17b956c5Satoshi Kataoka                mProximityInfo->getMostCommonKeyWidth(), mProximityInfo, mMaxPointToKeyLength,
9147cc52415e3affb83eb4369190425b2a17b956c5Satoshi Kataoka                mInputProximities, xCoordinates, yCoordinates, times, pointerIds, inputSize,
92d7a8fbf6a9ec8828d4b6d1c615a6c605bbe5b72eSatoshi Kataoka                isGeometric, pointerId, pushTouchPointStartIndex, &mSampledInputXs,
93d7a8fbf6a9ec8828d4b6d1c615a6c605bbe5b72eSatoshi Kataoka                &mSampledInputYs, &mSampledTimes, &mSampledLengthCache, &mSampledInputIndice);
943e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka    }
95687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka
96feec20a692c9ffdecf7855a45531a12f129086caSatoshi Kataoka    if (mSampledInputSize > 0 && isGeometric) {
97ee62b78c9675bddaf2437e0cf521f6115e1d9febSatoshi Kataoka        mAverageSpeed = ProximityInfoStateUtils::refreshSpeedRates(
98ee62b78c9675bddaf2437e0cf521f6115e1d9febSatoshi Kataoka                inputSize, xCoordinates, yCoordinates, times, lastSavedInputSize,
99d7a8fbf6a9ec8828d4b6d1c615a6c605bbe5b72eSatoshi Kataoka                mSampledInputSize, &mSampledInputXs, &mSampledInputYs, &mSampledTimes,
100d7a8fbf6a9ec8828d4b6d1c615a6c605bbe5b72eSatoshi Kataoka                &mSampledLengthCache, &mSampledInputIndice, &mSpeedRates, &mDirections);
101ee62b78c9675bddaf2437e0cf521f6115e1d9febSatoshi Kataoka        ProximityInfoStateUtils::refreshBeelineSpeedRates(
102ee62b78c9675bddaf2437e0cf521f6115e1d9febSatoshi Kataoka                mProximityInfo->getMostCommonKeyWidth(), mAverageSpeed, inputSize,
103ee62b78c9675bddaf2437e0cf521f6115e1d9febSatoshi Kataoka                xCoordinates, yCoordinates, times, mSampledInputSize, &mSampledInputXs,
104d7a8fbf6a9ec8828d4b6d1c615a6c605bbe5b72eSatoshi Kataoka                &mSampledInputYs, &mSampledInputIndice, &mBeelineSpeedPercentiles);
105ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi    }
106ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi
107feec20a692c9ffdecf7855a45531a12f129086caSatoshi Kataoka    if (mSampledInputSize > 0) {
108d7a8fbf6a9ec8828d4b6d1c615a6c605bbe5b72eSatoshi Kataoka        ProximityInfoStateUtils::initGeometricDistanceInfos(
109d7a8fbf6a9ec8828d4b6d1c615a6c605bbe5b72eSatoshi Kataoka                mProximityInfo, mProximityInfo->getKeyCount(),
110d7a8fbf6a9ec8828d4b6d1c615a6c605bbe5b72eSatoshi Kataoka                mSampledInputSize, lastSavedInputSize, &mSampledInputXs, &mSampledInputYs,
111e5aad5646309e80e1cd71533fb47a6be43f3aa2fSatoshi Kataoka                &mSampledNearKeysVector, &mSampledDistanceCache_G);
112ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi        if (isGeometric) {
113ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi            // updates probabilities of skipping or mapping each key for all points.
114d4828d5053ac30476b884c177235be0cac982c92Satoshi Kataoka            ProximityInfoStateUtils::updateAlignPointProbabilities(
115d4828d5053ac30476b884c177235be0cac982c92Satoshi Kataoka                    mMaxPointToKeyLength, mProximityInfo->getMostCommonKeyWidth(),
116d7a8fbf6a9ec8828d4b6d1c615a6c605bbe5b72eSatoshi Kataoka                    mProximityInfo->getKeyCount(), lastSavedInputSize, mSampledInputSize,
117d7a8fbf6a9ec8828d4b6d1c615a6c605bbe5b72eSatoshi Kataoka                    &mSampledInputXs, &mSampledInputYs, &mSpeedRates, &mSampledLengthCache,
118e5aad5646309e80e1cd71533fb47a6be43f3aa2fSatoshi Kataoka                    &mSampledDistanceCache_G, &mSampledNearKeysVector, &mCharProbabilities);
119e5aad5646309e80e1cd71533fb47a6be43f3aa2fSatoshi Kataoka            ProximityInfoStateUtils::updateSampledSearchKeysVector(mProximityInfo,
120e5aad5646309e80e1cd71533fb47a6be43f3aa2fSatoshi Kataoka                    mSampledInputSize, lastSavedInputSize, &mSampledLengthCache,
121e5aad5646309e80e1cd71533fb47a6be43f3aa2fSatoshi Kataoka                    &mSampledNearKeysVector, &mSampledSearchKeysVector);
122687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka        }
123687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka    }
12408f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka
125806eba452423e5e5971ef096dfae3fed180db665Keisuke Kuroyanagi    if (DEBUG_SAMPLING_POINTS) {
126d7a8fbf6a9ec8828d4b6d1c615a6c605bbe5b72eSatoshi Kataoka        ProximityInfoStateUtils::dump(isGeometric, inputSize, xCoordinates, yCoordinates,
127e2912d17e4dab75b81f4c9e41a539e491ac059caSatoshi Kataoka                mSampledInputSize, &mSampledInputXs, &mSampledInputYs, &mSampledTimes, &mSpeedRates,
128d7a8fbf6a9ec8828d4b6d1c615a6c605bbe5b72eSatoshi Kataoka                &mBeelineSpeedPercentiles);
129806eba452423e5e5971ef096dfae3fed180db665Keisuke Kuroyanagi    }
130687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka    // end
131687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka    ///////////////////////
132687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka
13308f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka    memset(mNormalizedSquaredDistances, NOT_A_DISTANCE, sizeof(mNormalizedSquaredDistances));
13408f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka    memset(mPrimaryInputWord, 0, sizeof(mPrimaryInputWord));
135feec20a692c9ffdecf7855a45531a12f129086caSatoshi Kataoka    mTouchPositionCorrectionEnabled = mSampledInputSize > 0 && mHasTouchPositionCorrectionData
1360edab9d2fcc30667c79aa9221dbb27f042d8b455Satoshi Kataoka            && xCoordinates && yCoordinates;
13708f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka    if (!isGeometric && pointerId == 0) {
138d7a8fbf6a9ec8828d4b6d1c615a6c605bbe5b72eSatoshi Kataoka        ProximityInfoStateUtils::initPrimaryInputWord(
139d7a8fbf6a9ec8828d4b6d1c615a6c605bbe5b72eSatoshi Kataoka                inputSize, mInputProximities, mPrimaryInputWord);
140d7a8fbf6a9ec8828d4b6d1c615a6c605bbe5b72eSatoshi Kataoka        if (mTouchPositionCorrectionEnabled) {
141d7a8fbf6a9ec8828d4b6d1c615a6c605bbe5b72eSatoshi Kataoka            ProximityInfoStateUtils::initNormalizedSquaredDistances(
142d7a8fbf6a9ec8828d4b6d1c615a6c605bbe5b72eSatoshi Kataoka                    mProximityInfo, inputSize, xCoordinates, yCoordinates, mInputProximities,
143d7a8fbf6a9ec8828d4b6d1c615a6c605bbe5b72eSatoshi Kataoka                    hasInputCoordinates(), &mSampledInputXs, &mSampledInputYs,
144d7a8fbf6a9ec8828d4b6d1c615a6c605bbe5b72eSatoshi Kataoka                    mNormalizedSquaredDistances);
1453e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka        }
1463e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka    }
147952ec4977d772607140773ae7d8868f86a7e0097Satoshi Kataoka    if (DEBUG_GEO_FULL) {
148feec20a692c9ffdecf7855a45531a12f129086caSatoshi Kataoka        AKLOGI("ProximityState init finished: %d points out of %d", mSampledInputSize, inputSize);
149feec20a692c9ffdecf7855a45531a12f129086caSatoshi Kataoka    }
150feec20a692c9ffdecf7855a45531a12f129086caSatoshi Kataoka}
151feec20a692c9ffdecf7855a45531a12f129086caSatoshi Kataoka
152096f35ff4b5413906e2a339663baf16e5dabaf64Keisuke Kuroyanagibool ProximityInfoState::checkAndReturnIsContinuationPossible(const int inputSize,
153fe4f1ce26ca41ef51b5245d70e93b502f76262a5Satoshi Kataoka        const int *const xCoordinates, const int *const yCoordinates, const int *const times,
154fe4f1ce26ca41ef51b5245d70e93b502f76262a5Satoshi Kataoka        const bool isGeometric) const {
155fe4f1ce26ca41ef51b5245d70e93b502f76262a5Satoshi Kataoka    if (isGeometric) {
156fe4f1ce26ca41ef51b5245d70e93b502f76262a5Satoshi Kataoka        for (int i = 0; i < mSampledInputSize; ++i) {
157d7a8fbf6a9ec8828d4b6d1c615a6c605bbe5b72eSatoshi Kataoka            const int index = mSampledInputIndice[i];
158fe4f1ce26ca41ef51b5245d70e93b502f76262a5Satoshi Kataoka            if (index > inputSize || xCoordinates[index] != mSampledInputXs[i] ||
159d7a8fbf6a9ec8828d4b6d1c615a6c605bbe5b72eSatoshi Kataoka                    yCoordinates[index] != mSampledInputYs[i] || times[index] != mSampledTimes[i]) {
160fe4f1ce26ca41ef51b5245d70e93b502f76262a5Satoshi Kataoka                return false;
161fe4f1ce26ca41ef51b5245d70e93b502f76262a5Satoshi Kataoka            }
162fe4f1ce26ca41ef51b5245d70e93b502f76262a5Satoshi Kataoka        }
163fe4f1ce26ca41ef51b5245d70e93b502f76262a5Satoshi Kataoka    } else {
164fe4f1ce26ca41ef51b5245d70e93b502f76262a5Satoshi Kataoka        if (inputSize < mSampledInputSize) {
165fe4f1ce26ca41ef51b5245d70e93b502f76262a5Satoshi Kataoka            // Assuming the cache is invalid if the previous input size is larger than the new one.
166096f35ff4b5413906e2a339663baf16e5dabaf64Keisuke Kuroyanagi            return false;
167096f35ff4b5413906e2a339663baf16e5dabaf64Keisuke Kuroyanagi        }
1685db594abbad2d9e8d2cf1aa6e417aa50ffc5dfc1Ken Wakasa        for (int i = 0; i < mSampledInputSize && i < MAX_WORD_LENGTH; ++i) {
169fe4f1ce26ca41ef51b5245d70e93b502f76262a5Satoshi Kataoka            if (xCoordinates[i] != mSampledInputXs[i]
170fe4f1ce26ca41ef51b5245d70e93b502f76262a5Satoshi Kataoka                    || yCoordinates[i] != mSampledInputYs[i]) {
171fe4f1ce26ca41ef51b5245d70e93b502f76262a5Satoshi Kataoka                return false;
172fe4f1ce26ca41ef51b5245d70e93b502f76262a5Satoshi Kataoka            }
173fe4f1ce26ca41ef51b5245d70e93b502f76262a5Satoshi Kataoka        }
174096f35ff4b5413906e2a339663baf16e5dabaf64Keisuke Kuroyanagi    }
175096f35ff4b5413906e2a339663baf16e5dabaf64Keisuke Kuroyanagi    return true;
176096f35ff4b5413906e2a339663baf16e5dabaf64Keisuke Kuroyanagi}
177096f35ff4b5413906e2a339663baf16e5dabaf64Keisuke Kuroyanagi
178687a244703a02323ebd64433cbaead5def499861Satoshi Kataokaint ProximityInfoState::getDuration(const int index) const {
179feec20a692c9ffdecf7855a45531a12f129086caSatoshi Kataoka    if (index >= 0 && index < mSampledInputSize - 1) {
180d7a8fbf6a9ec8828d4b6d1c615a6c605bbe5b72eSatoshi Kataoka        return mSampledTimes[index + 1] - mSampledTimes[index];
181687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka    }
18237b153e205c9672b299b47e97921fee2462a78bbSatoshi Kataoka    return 0;
183687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka}
184687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka
1850519fdd18ac4414b8298d3338db1c8ccce032170Satoshi Kataoka// TODO: Remove the "scale" parameter
1860519fdd18ac4414b8298d3338db1c8ccce032170Satoshi Kataoka// This function basically converts from a length to an edit distance. Accordingly, it's obviously
1870519fdd18ac4414b8298d3338db1c8ccce032170Satoshi Kataoka// wrong to compare with mMaxPointToKeyLength.
1880519fdd18ac4414b8298d3338db1c8ccce032170Satoshi Kataokafloat ProximityInfoState::getPointToKeyLength(
1890519fdd18ac4414b8298d3338db1c8ccce032170Satoshi Kataoka        const int inputIndex, const int codePoint, const float scale) const {
190ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi    const int keyId = mProximityInfo->getKeyIndexOf(codePoint);
191ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi    if (keyId != NOT_AN_INDEX) {
192ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi        const int index = inputIndex * mProximityInfo->getKeyCount() + keyId;
193e5aad5646309e80e1cd71533fb47a6be43f3aa2fSatoshi Kataoka        return min(mSampledDistanceCache_G[index] * scale, mMaxPointToKeyLength);
194ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi    }
1951e61493c50082264caaef862df02b1ccc84dc396Ken Wakasa    if (isSkippableCodePoint(codePoint)) {
196806eba452423e5e5971ef096dfae3fed180db665Keisuke Kuroyanagi        return 0.0f;
197806eba452423e5e5971ef096dfae3fed180db665Keisuke Kuroyanagi    }
198ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi    // If the char is not a key on the keyboard then return the max length.
199ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi    return MAX_POINT_TO_KEY_LENGTH;
200806eba452423e5e5971ef096dfae3fed180db665Keisuke Kuroyanagi}
201806eba452423e5e5971ef096dfae3fed180db665Keisuke Kuroyanagi
202a9763f93d76f97b9c6ed7dd1369a4d8cb016f06fSatoshi Kataokafloat ProximityInfoState::getPointToKeyLength_G(const int inputIndex, const int codePoint) const {
2030519fdd18ac4414b8298d3338db1c8ccce032170Satoshi Kataoka    return getPointToKeyLength(inputIndex, codePoint, 1.0f);
2040519fdd18ac4414b8298d3338db1c8ccce032170Satoshi Kataoka}
2050519fdd18ac4414b8298d3338db1c8ccce032170Satoshi Kataoka
2060519fdd18ac4414b8298d3338db1c8ccce032170Satoshi Kataoka// TODO: Remove the "scale" parameter
2070519fdd18ac4414b8298d3338db1c8ccce032170Satoshi Kataokafloat ProximityInfoState::getPointToKeyByIdLength(
2080519fdd18ac4414b8298d3338db1c8ccce032170Satoshi Kataoka        const int inputIndex, const int keyId, const float scale) const {
209d4828d5053ac30476b884c177235be0cac982c92Satoshi Kataoka    return ProximityInfoStateUtils::getPointToKeyByIdLength(mMaxPointToKeyLength,
210e5aad5646309e80e1cd71533fb47a6be43f3aa2fSatoshi Kataoka            &mSampledDistanceCache_G, mProximityInfo->getKeyCount(), inputIndex, keyId, scale);
211687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka}
212687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka
2130519fdd18ac4414b8298d3338db1c8ccce032170Satoshi Kataokafloat ProximityInfoState::getPointToKeyByIdLength(const int inputIndex, const int keyId) const {
2140519fdd18ac4414b8298d3338db1c8ccce032170Satoshi Kataoka    return getPointToKeyByIdLength(inputIndex, keyId, 1.0f);
2150519fdd18ac4414b8298d3338db1c8ccce032170Satoshi Kataoka}
2160519fdd18ac4414b8298d3338db1c8ccce032170Satoshi Kataoka
2172c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa// In the following function, c is the current character of the dictionary word currently examined.
2182c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa// currentChars is an array containing the keys close to the character the user actually typed at
2192c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa// the same position. We want to see if c is in it: if so, then the word contains at that position
2202c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa// a character close to what the user typed.
2212c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa// What the user typed is actually the first character of the array.
2222c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa// proximityIndex is a pointer to the variable where getMatchedProximityId returns the index of c
2232c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa// in the proximity chars of the input index.
2242c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa// Notice : accented characters do not have a proximity list, so they are alone in their list. The
2252c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa// non-accented version of the character should be considered "close", but not the other keys close
2262c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa// to the non-accented version.
2272c2f3a90d8115777adbe9ffd597f344aede84276Ken WakasaProximityType ProximityInfoState::getMatchedProximityId(const int index, const int c,
2282c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa        const bool checkProximityChars, int *proximityIndex) const {
2292c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa    const int *currentCodePoints = getProximityCodePointsAt(index);
2302c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa    const int firstCodePoint = currentCodePoints[0];
2312c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa    const int baseLowerC = toBaseLowerCase(c);
2322c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa
2332c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa    // The first char in the array is what user typed. If it matches right away, that means the
2342c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa    // user typed that same char for this pos.
2352c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa    if (firstCodePoint == baseLowerC || firstCodePoint == c) {
2362c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa        return EQUIVALENT_CHAR;
2372c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa    }
2382c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa
2392c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa    if (!checkProximityChars) return UNRELATED_CHAR;
2402c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa
2412c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa    // If the non-accented, lowercased version of that first character matches c, then we have a
2422c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa    // non-accented version of the accented character the user typed. Treat it as a close char.
2432c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa    if (toBaseLowerCase(firstCodePoint) == baseLowerC) {
2442c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa        return NEAR_PROXIMITY_CHAR;
2452c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa    }
2462c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa
2472c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa    // Not an exact nor an accent-alike match: search the list of close keys
2482c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa    int j = 1;
2496c22439bf80da08576e86c1282afc5cfa431e235Ken Wakasa    while (j < MAX_PROXIMITY_CHARS_SIZE
2502c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa            && currentCodePoints[j] > ADDITIONAL_PROXIMITY_CHAR_DELIMITER_CODE) {
2512c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa        const bool matched = (currentCodePoints[j] == baseLowerC || currentCodePoints[j] == c);
2522c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa        if (matched) {
2532c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa            if (proximityIndex) {
2542c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa                *proximityIndex = j;
2552c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa            }
2562c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa            return NEAR_PROXIMITY_CHAR;
2572c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa        }
2582c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa        ++j;
2592c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa    }
2606c22439bf80da08576e86c1282afc5cfa431e235Ken Wakasa    if (j < MAX_PROXIMITY_CHARS_SIZE
2612c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa            && currentCodePoints[j] == ADDITIONAL_PROXIMITY_CHAR_DELIMITER_CODE) {
2622c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa        ++j;
2636c22439bf80da08576e86c1282afc5cfa431e235Ken Wakasa        while (j < MAX_PROXIMITY_CHARS_SIZE
2642c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa                && currentCodePoints[j] > ADDITIONAL_PROXIMITY_CHAR_DELIMITER_CODE) {
2652c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa            const bool matched = (currentCodePoints[j] == baseLowerC || currentCodePoints[j] == c);
2662c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa            if (matched) {
2672c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa                if (proximityIndex) {
2682c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa                    *proximityIndex = j;
2692c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa                }
2702c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa                return ADDITIONAL_PROXIMITY_CHAR;
2712c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa            }
2722c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa            ++j;
2732c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa        }
2742c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa    }
2752c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa    // Was not included, signal this as an unrelated character.
2762c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa    return UNRELATED_CHAR;
2772c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa}
2782c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa
2793811a28ddc07201930e0bbd2e1d01045b59af308Keisuke Kuroyanagiint ProximityInfoState::getSpaceY() const {
280b02ee3d67a1884b6ff59cc16c29a476845c0694fKen Wakasa    const int keyId = mProximityInfo->getKeyIndexOf(KEYCODE_SPACE);
281f2789819bd005b5b0581e8439601b5501306327dKen Wakasa    return mProximityInfo->getKeyCenterYOfKeyIdG(keyId);
282687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka}
283687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka
28495a49a527ac9c2c97cfcc758bd6f0d58fb4ad9c0Keisuke Kuroyanagi// Puts possible characters into filter and returns new filter size.
285082507e1da56c6cefe575ec3d6a334e9b717e3faKen Wakasaint ProximityInfoState::getAllPossibleChars(
286082507e1da56c6cefe575ec3d6a334e9b717e3faKen Wakasa        const size_t index, int *const filter, const int filterSize) const {
287feec20a692c9ffdecf7855a45531a12f129086caSatoshi Kataoka    if (index >= mSampledInputXs.size()) {
28895a49a527ac9c2c97cfcc758bd6f0d58fb4ad9c0Keisuke Kuroyanagi        return filterSize;
28995a49a527ac9c2c97cfcc758bd6f0d58fb4ad9c0Keisuke Kuroyanagi    }
29041f12ee27b269033fe818f7d52e81ba948a046c3Keisuke Kuroyanagi    int newFilterSize = filterSize;
291ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi    const int keyCount = mProximityInfo->getKeyCount();
292ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi    for (int j = 0; j < keyCount; ++j) {
293e5aad5646309e80e1cd71533fb47a6be43f3aa2fSatoshi Kataoka        if (mSampledSearchKeysVector[index].test(j)) {
294082507e1da56c6cefe575ec3d6a334e9b717e3faKen Wakasa            const int keyCodePoint = mProximityInfo->getCodePointOf(j);
29595a49a527ac9c2c97cfcc758bd6f0d58fb4ad9c0Keisuke Kuroyanagi            bool insert = true;
29695a49a527ac9c2c97cfcc758bd6f0d58fb4ad9c0Keisuke Kuroyanagi            // TODO: Avoid linear search
29795a49a527ac9c2c97cfcc758bd6f0d58fb4ad9c0Keisuke Kuroyanagi            for (int k = 0; k < filterSize; ++k) {
29895a49a527ac9c2c97cfcc758bd6f0d58fb4ad9c0Keisuke Kuroyanagi                if (filter[k] == keyCodePoint) {
29995a49a527ac9c2c97cfcc758bd6f0d58fb4ad9c0Keisuke Kuroyanagi                    insert = false;
30095a49a527ac9c2c97cfcc758bd6f0d58fb4ad9c0Keisuke Kuroyanagi                    break;
30195a49a527ac9c2c97cfcc758bd6f0d58fb4ad9c0Keisuke Kuroyanagi                }
30295a49a527ac9c2c97cfcc758bd6f0d58fb4ad9c0Keisuke Kuroyanagi            }
30395a49a527ac9c2c97cfcc758bd6f0d58fb4ad9c0Keisuke Kuroyanagi            if (insert) {
30441f12ee27b269033fe818f7d52e81ba948a046c3Keisuke Kuroyanagi                filter[newFilterSize++] = keyCodePoint;
30595a49a527ac9c2c97cfcc758bd6f0d58fb4ad9c0Keisuke Kuroyanagi            }
30695a49a527ac9c2c97cfcc758bd6f0d58fb4ad9c0Keisuke Kuroyanagi        }
30795a49a527ac9c2c97cfcc758bd6f0d58fb4ad9c0Keisuke Kuroyanagi    }
30841f12ee27b269033fe818f7d52e81ba948a046c3Keisuke Kuroyanagi    return newFilterSize;
30995a49a527ac9c2c97cfcc758bd6f0d58fb4ad9c0Keisuke Kuroyanagi}
3103811a28ddc07201930e0bbd2e1d01045b59af308Keisuke Kuroyanagi
311ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagibool ProximityInfoState::isKeyInSerchKeysAfterIndex(const int index, const int keyId) const {
312ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi    ASSERT(keyId >= 0);
313feec20a692c9ffdecf7855a45531a12f129086caSatoshi Kataoka    ASSERT(index >= 0 && index < mSampledInputSize);
314e5aad5646309e80e1cd71533fb47a6be43f3aa2fSatoshi Kataoka    return mSampledSearchKeysVector[index].test(keyId);
315ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi}
316ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi
317096f35ff4b5413906e2a339663baf16e5dabaf64Keisuke Kuroyanagivoid ProximityInfoState::popInputData() {
318d7a8fbf6a9ec8828d4b6d1c615a6c605bbe5b72eSatoshi Kataoka    ProximityInfoStateUtils::popInputData(&mSampledInputXs, &mSampledInputYs, &mSampledTimes,
319d7a8fbf6a9ec8828d4b6d1c615a6c605bbe5b72eSatoshi Kataoka            &mSampledLengthCache, &mSampledInputIndice);
320096f35ff4b5413906e2a339663baf16e5dabaf64Keisuke Kuroyanagi}
321096f35ff4b5413906e2a339663baf16e5dabaf64Keisuke Kuroyanagi
322ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagifloat ProximityInfoState::getDirection(const int index0, const int index1) const {
323ee62b78c9675bddaf2437e0cf521f6115e1d9febSatoshi Kataoka    return ProximityInfoStateUtils::getDirection(
324ee62b78c9675bddaf2437e0cf521f6115e1d9febSatoshi Kataoka            &mSampledInputXs, &mSampledInputYs, index0, index1);
325ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi}
326ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi
327ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagifloat ProximityInfoState::getLineToKeyDistance(
328ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi        const int from, const int to, const int keyId, const bool extend) const {
329feec20a692c9ffdecf7855a45531a12f129086caSatoshi Kataoka    if (from < 0 || from > mSampledInputSize - 1) {
330ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi        return 0.0f;
331ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi    }
332feec20a692c9ffdecf7855a45531a12f129086caSatoshi Kataoka    if (to < 0 || to > mSampledInputSize - 1) {
333ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi        return 0.0f;
334ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi    }
335feec20a692c9ffdecf7855a45531a12f129086caSatoshi Kataoka    const int x0 = mSampledInputXs[from];
336feec20a692c9ffdecf7855a45531a12f129086caSatoshi Kataoka    const int y0 = mSampledInputYs[from];
337feec20a692c9ffdecf7855a45531a12f129086caSatoshi Kataoka    const int x1 = mSampledInputXs[to];
338feec20a692c9ffdecf7855a45531a12f129086caSatoshi Kataoka    const int y1 = mSampledInputYs[to];
339ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi
340ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi    const int keyX = mProximityInfo->getKeyCenterXOfKeyIdG(keyId);
341ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi    const int keyY = mProximityInfo->getKeyCenterYOfKeyIdG(keyId);
342ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi
3430c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa    return ProximityInfoUtils::pointToLineSegSquaredDistanceFloat(
3440c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa            keyX, keyY, x0, y0, x1, y1, extend);
345806eba452423e5e5971ef096dfae3fed180db665Keisuke Kuroyanagi}
346806eba452423e5e5971ef096dfae3fed180db665Keisuke Kuroyanagi
347e0349619acdba79223390c9925d81f7e88c7f8adSatoshi Kataoka// Get a word that is detected by tracing the most probable string into codePointBuf and
3481e61493c50082264caaef862df02b1ccc84dc396Ken Wakasa// returns probability of generating the word.
349e0349619acdba79223390c9925d81f7e88c7f8adSatoshi Kataokafloat ProximityInfoState::getMostProbableString(int *const codePointBuf) const {
350350309aeb81ad1924af4d2e6d0bceaa6f98e4821Keisuke Kuroyanagi    static const float DEMOTION_LOG_PROBABILITY = 0.3f;
351ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi    int index = 0;
352ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi    float sumLogProbability = 0.0f;
353806eba452423e5e5971ef096dfae3fed180db665Keisuke Kuroyanagi    // TODO: Current implementation is greedy algorithm. DP would be efficient for many cases.
3545db594abbad2d9e8d2cf1aa6e417aa50ffc5dfc1Ken Wakasa    for (int i = 0; i < mSampledInputSize && index < MAX_WORD_LENGTH - 1; ++i) {
355ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi        float minLogProbability = static_cast<float>(MAX_POINT_TO_KEY_LENGTH);
356ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi        int character = NOT_AN_INDEX;
357806eba452423e5e5971ef096dfae3fed180db665Keisuke Kuroyanagi        for (hash_map_compat<int, float>::const_iterator it = mCharProbabilities[i].begin();
358806eba452423e5e5971ef096dfae3fed180db665Keisuke Kuroyanagi                it != mCharProbabilities[i].end(); ++it) {
359ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi            const float logProbability = (it->first != NOT_AN_INDEX)
360350309aeb81ad1924af4d2e6d0bceaa6f98e4821Keisuke Kuroyanagi                    ? it->second + DEMOTION_LOG_PROBABILITY : it->second;
361ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi            if (logProbability < minLogProbability) {
362ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi                minLogProbability = logProbability;
363ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi                character = it->first;
364806eba452423e5e5971ef096dfae3fed180db665Keisuke Kuroyanagi            }
365806eba452423e5e5971ef096dfae3fed180db665Keisuke Kuroyanagi        }
366ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi        if (character != NOT_AN_INDEX) {
3671e61493c50082264caaef862df02b1ccc84dc396Ken Wakasa            codePointBuf[index] = mProximityInfo->getCodePointOf(character);
368806eba452423e5e5971ef096dfae3fed180db665Keisuke Kuroyanagi            index++;
369806eba452423e5e5971ef096dfae3fed180db665Keisuke Kuroyanagi        }
370ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi        sumLogProbability += minLogProbability;
371806eba452423e5e5971ef096dfae3fed180db665Keisuke Kuroyanagi    }
3721e61493c50082264caaef862df02b1ccc84dc396Ken Wakasa    codePointBuf[index] = '\0';
373ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi    return sumLogProbability;
374ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi}
375ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi
376f32869c6b6296a8bf594abdf0b18281d9312e54fSatoshi Kataokabool ProximityInfoState::hasSpaceProximity(const int index) const {
377f32869c6b6296a8bf594abdf0b18281d9312e54fSatoshi Kataoka    ASSERT(0 <= index && index < mSampledInputSize);
378f32869c6b6296a8bf594abdf0b18281d9312e54fSatoshi Kataoka    return mProximityInfo->hasSpaceProximity(getInputX(index), getInputY(index));
379f32869c6b6296a8bf594abdf0b18281d9312e54fSatoshi Kataoka}
380f32869c6b6296a8bf594abdf0b18281d9312e54fSatoshi Kataoka
381ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi// Returns a probability of mapping index to keyIndex.
382ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagifloat ProximityInfoState::getProbability(const int index, const int keyIndex) const {
383feec20a692c9ffdecf7855a45531a12f129086caSatoshi Kataoka    ASSERT(0 <= index && index < mSampledInputSize);
384ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi    hash_map_compat<int, float>::const_iterator it = mCharProbabilities[index].find(keyIndex);
385ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi    if (it != mCharProbabilities[index].end()) {
386ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi        return it->second;
387ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi    }
388ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi    return static_cast<float>(MAX_POINT_TO_KEY_LENGTH);
389806eba452423e5e5971ef096dfae3fed180db665Keisuke Kuroyanagi}
3903e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka} // namespace latinime
391