proximity_info_state.cpp revision 28c008421cc5d97da8e470dbc934a2891daf9997
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
1720b6775acc957896bdb038dfd99794d6cd7cea5aSatoshi Kataoka#include <cstring> // for memset() and memcpy()
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
30233aad5e5c7567a97af30f38f50a65365f729dfeSatoshi Kataokavoid ProximityInfoState::initInputParams(const int pointerId, const float maxPointToKeyLength,
311e61493c50082264caaef862df02b1ccc84dc396Ken Wakasa        const ProximityInfo *proximityInfo, const int *const inputCodes, const int inputSize,
32687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka        const int *const xCoordinates, const int *const yCoordinates, const int *const times,
33687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka        const int *const pointerIds, const bool isGeometric) {
349d18c6dd38c4d5632a5d5a5c26f567b9f6f7f969Satoshi Kataoka    ASSERT(isGeometric || (inputSize < MAX_WORD_LENGTH));
359d18c6dd38c4d5632a5d5a5c26f567b9f6f7f969Satoshi Kataoka    mIsContinuationPossible = ProximityInfoStateUtils::checkAndReturnIsContinuationPossible(
369d18c6dd38c4d5632a5d5a5c26f567b9f6f7f969Satoshi Kataoka            inputSize, xCoordinates, yCoordinates, times, mSampledInputSize, &mSampledInputXs,
379d18c6dd38c4d5632a5d5a5c26f567b9f6f7f969Satoshi Kataoka            &mSampledInputYs, &mSampledTimes, &mSampledInputIndice);
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;
6020b6775acc957896bdb038dfd99794d6cd7cea5aSatoshi Kataoka    mSampledInputSize = 0;
6120b6775acc957896bdb038dfd99794d6cd7cea5aSatoshi Kataoka    mMostProbableStringProbability = 0.0f;
6220b6775acc957896bdb038dfd99794d6cd7cea5aSatoshi Kataoka
63d7a8fbf6a9ec8828d4b6d1c615a6c605bbe5b72eSatoshi Kataoka    if (mIsContinuationPossible && mSampledInputIndice.size() > 1) {
64096f35ff4b5413906e2a339663baf16e5dabaf64Keisuke Kuroyanagi        // Just update difference.
6520b6775acc957896bdb038dfd99794d6cd7cea5aSatoshi Kataoka        // Previous two points are never skipped. Thus, we pop 2 input point data here.
6620b6775acc957896bdb038dfd99794d6cd7cea5aSatoshi Kataoka        pushTouchPointStartIndex = ProximityInfoStateUtils::trimLastTwoTouchPoints(
6720b6775acc957896bdb038dfd99794d6cd7cea5aSatoshi Kataoka                &mSampledInputXs, &mSampledInputYs, &mSampledTimes, &mSampledLengthCache,
6820b6775acc957896bdb038dfd99794d6cd7cea5aSatoshi Kataoka                &mSampledInputIndice);
69feec20a692c9ffdecf7855a45531a12f129086caSatoshi Kataoka        lastSavedInputSize = mSampledInputXs.size();
70096f35ff4b5413906e2a339663baf16e5dabaf64Keisuke Kuroyanagi    } else {
71096f35ff4b5413906e2a339663baf16e5dabaf64Keisuke Kuroyanagi        // Clear all data.
72feec20a692c9ffdecf7855a45531a12f129086caSatoshi Kataoka        mSampledInputXs.clear();
73feec20a692c9ffdecf7855a45531a12f129086caSatoshi Kataoka        mSampledInputYs.clear();
74d7a8fbf6a9ec8828d4b6d1c615a6c605bbe5b72eSatoshi Kataoka        mSampledTimes.clear();
75d7a8fbf6a9ec8828d4b6d1c615a6c605bbe5b72eSatoshi Kataoka        mSampledInputIndice.clear();
76d7a8fbf6a9ec8828d4b6d1c615a6c605bbe5b72eSatoshi Kataoka        mSampledLengthCache.clear();
77e5aad5646309e80e1cd71533fb47a6be43f3aa2fSatoshi Kataoka        mSampledDistanceCache_G.clear();
78e5aad5646309e80e1cd71533fb47a6be43f3aa2fSatoshi Kataoka        mSampledNearKeysVector.clear();
79e5aad5646309e80e1cd71533fb47a6be43f3aa2fSatoshi Kataoka        mSampledSearchKeysVector.clear();
809af533538ea749d7c930bb3125fa4d3e4feb8478Satoshi Kataoka        mSpeedRates.clear();
816ae8dd4343445d2df4444388b605d2aa930fa2a0Satoshi Kataoka        mBeelineSpeedPercentiles.clear();
82806eba452423e5e5971ef096dfae3fed180db665Keisuke Kuroyanagi        mCharProbabilities.clear();
831e06a4d8e9e71188ed685282155ea52a48ddc050Keisuke Kuroyanagi        mDirections.clear();
84096f35ff4b5413906e2a339663baf16e5dabaf64Keisuke Kuroyanagi    }
8520b6775acc957896bdb038dfd99794d6cd7cea5aSatoshi Kataoka
869182daf98c0d1db897e82b77c2196b7f9aad6f01Satoshi Kataoka    if (DEBUG_GEO_FULL) {
879182daf98c0d1db897e82b77c2196b7f9aad6f01Satoshi Kataoka        AKLOGI("Init ProximityInfoState: reused points =  %d, last input size = %d",
889182daf98c0d1db897e82b77c2196b7f9aad6f01Satoshi Kataoka                pushTouchPointStartIndex, lastSavedInputSize);
899182daf98c0d1db897e82b77c2196b7f9aad6f01Satoshi Kataoka    }
90d9c10b19793b011f862e3dd31883f746044431d7Keisuke Kuroyanagi
91687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka    if (xCoordinates && yCoordinates) {
9228c008421cc5d97da8e470dbc934a2891daf9997Ken Wakasa        mSampledInputSize = ProximityInfoStateUtils::updateTouchPoints(mProximityInfo,
9328c008421cc5d97da8e470dbc934a2891daf9997Ken Wakasa                mMaxPointToKeyLength, mInputProximities, xCoordinates, yCoordinates, times,
9428c008421cc5d97da8e470dbc934a2891daf9997Ken Wakasa                pointerIds, inputSize, isGeometric, pointerId, pushTouchPointStartIndex,
9528c008421cc5d97da8e470dbc934a2891daf9997Ken Wakasa                &mSampledInputXs, &mSampledInputYs, &mSampledTimes, &mSampledLengthCache,
9628c008421cc5d97da8e470dbc934a2891daf9997Ken Wakasa                &mSampledInputIndice);
973e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka    }
98687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka
99feec20a692c9ffdecf7855a45531a12f129086caSatoshi Kataoka    if (mSampledInputSize > 0 && isGeometric) {
10028c008421cc5d97da8e470dbc934a2891daf9997Ken Wakasa        mAverageSpeed = ProximityInfoStateUtils::refreshSpeedRates(inputSize, xCoordinates,
10128c008421cc5d97da8e470dbc934a2891daf9997Ken Wakasa                yCoordinates, times, lastSavedInputSize, mSampledInputSize, &mSampledInputXs,
10228c008421cc5d97da8e470dbc934a2891daf9997Ken Wakasa                &mSampledInputYs, &mSampledTimes, &mSampledLengthCache, &mSampledInputIndice,
10328c008421cc5d97da8e470dbc934a2891daf9997Ken Wakasa                &mSpeedRates, &mDirections);
10428c008421cc5d97da8e470dbc934a2891daf9997Ken Wakasa        ProximityInfoStateUtils::refreshBeelineSpeedRates(mProximityInfo->getMostCommonKeyWidth(),
10528c008421cc5d97da8e470dbc934a2891daf9997Ken Wakasa                mAverageSpeed, inputSize, xCoordinates, yCoordinates, times, mSampledInputSize,
10628c008421cc5d97da8e470dbc934a2891daf9997Ken Wakasa                &mSampledInputXs, &mSampledInputYs, &mSampledInputIndice,
10728c008421cc5d97da8e470dbc934a2891daf9997Ken Wakasa                &mBeelineSpeedPercentiles);
108ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi    }
109ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi
110feec20a692c9ffdecf7855a45531a12f129086caSatoshi Kataoka    if (mSampledInputSize > 0) {
11128c008421cc5d97da8e470dbc934a2891daf9997Ken Wakasa        ProximityInfoStateUtils::initGeometricDistanceInfos(mProximityInfo, mSampledInputSize,
11228c008421cc5d97da8e470dbc934a2891daf9997Ken Wakasa                lastSavedInputSize, &mSampledInputXs, &mSampledInputYs, &mSampledNearKeysVector,
11328c008421cc5d97da8e470dbc934a2891daf9997Ken Wakasa                &mSampledDistanceCache_G);
114ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi        if (isGeometric) {
115ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi            // updates probabilities of skipping or mapping each key for all points.
116d4828d5053ac30476b884c177235be0cac982c92Satoshi Kataoka            ProximityInfoStateUtils::updateAlignPointProbabilities(
117d4828d5053ac30476b884c177235be0cac982c92Satoshi Kataoka                    mMaxPointToKeyLength, mProximityInfo->getMostCommonKeyWidth(),
118d7a8fbf6a9ec8828d4b6d1c615a6c605bbe5b72eSatoshi Kataoka                    mProximityInfo->getKeyCount(), lastSavedInputSize, mSampledInputSize,
119d7a8fbf6a9ec8828d4b6d1c615a6c605bbe5b72eSatoshi Kataoka                    &mSampledInputXs, &mSampledInputYs, &mSpeedRates, &mSampledLengthCache,
120e5aad5646309e80e1cd71533fb47a6be43f3aa2fSatoshi Kataoka                    &mSampledDistanceCache_G, &mSampledNearKeysVector, &mCharProbabilities);
121e5aad5646309e80e1cd71533fb47a6be43f3aa2fSatoshi Kataoka            ProximityInfoStateUtils::updateSampledSearchKeysVector(mProximityInfo,
122e5aad5646309e80e1cd71533fb47a6be43f3aa2fSatoshi Kataoka                    mSampledInputSize, lastSavedInputSize, &mSampledLengthCache,
123e5aad5646309e80e1cd71533fb47a6be43f3aa2fSatoshi Kataoka                    &mSampledNearKeysVector, &mSampledSearchKeysVector);
12420b6775acc957896bdb038dfd99794d6cd7cea5aSatoshi Kataoka            mMostProbableStringProbability = ProximityInfoStateUtils::getMostProbableString(
12520b6775acc957896bdb038dfd99794d6cd7cea5aSatoshi Kataoka                    mProximityInfo, mSampledInputSize, &mCharProbabilities, mMostProbableString);
12620b6775acc957896bdb038dfd99794d6cd7cea5aSatoshi Kataoka
127687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka        }
128687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka    }
12908f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka
130806eba452423e5e5971ef096dfae3fed180db665Keisuke Kuroyanagi    if (DEBUG_SAMPLING_POINTS) {
131d7a8fbf6a9ec8828d4b6d1c615a6c605bbe5b72eSatoshi Kataoka        ProximityInfoStateUtils::dump(isGeometric, inputSize, xCoordinates, yCoordinates,
132e2912d17e4dab75b81f4c9e41a539e491ac059caSatoshi Kataoka                mSampledInputSize, &mSampledInputXs, &mSampledInputYs, &mSampledTimes, &mSpeedRates,
133d7a8fbf6a9ec8828d4b6d1c615a6c605bbe5b72eSatoshi Kataoka                &mBeelineSpeedPercentiles);
134806eba452423e5e5971ef096dfae3fed180db665Keisuke Kuroyanagi    }
135687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka    // end
136687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka    ///////////////////////
137687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka
138feec20a692c9ffdecf7855a45531a12f129086caSatoshi Kataoka    mTouchPositionCorrectionEnabled = mSampledInputSize > 0 && mHasTouchPositionCorrectionData
1390edab9d2fcc30667c79aa9221dbb27f042d8b455Satoshi Kataoka            && xCoordinates && yCoordinates;
14008f00cf55f2e083c1ed254a32495b622c9ad9862Satoshi Kataoka    if (!isGeometric && pointerId == 0) {
141d7a8fbf6a9ec8828d4b6d1c615a6c605bbe5b72eSatoshi Kataoka        ProximityInfoStateUtils::initPrimaryInputWord(
142d7a8fbf6a9ec8828d4b6d1c615a6c605bbe5b72eSatoshi Kataoka                inputSize, mInputProximities, mPrimaryInputWord);
143d7a8fbf6a9ec8828d4b6d1c615a6c605bbe5b72eSatoshi Kataoka        if (mTouchPositionCorrectionEnabled) {
144d7a8fbf6a9ec8828d4b6d1c615a6c605bbe5b72eSatoshi Kataoka            ProximityInfoStateUtils::initNormalizedSquaredDistances(
145d7a8fbf6a9ec8828d4b6d1c615a6c605bbe5b72eSatoshi Kataoka                    mProximityInfo, inputSize, xCoordinates, yCoordinates, mInputProximities,
14620b6775acc957896bdb038dfd99794d6cd7cea5aSatoshi Kataoka                    &mSampledInputXs, &mSampledInputYs, mNormalizedSquaredDistances);
1473e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka        }
1483e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka    }
149952ec4977d772607140773ae7d8868f86a7e0097Satoshi Kataoka    if (DEBUG_GEO_FULL) {
150feec20a692c9ffdecf7855a45531a12f129086caSatoshi Kataoka        AKLOGI("ProximityState init finished: %d points out of %d", mSampledInputSize, inputSize);
151feec20a692c9ffdecf7855a45531a12f129086caSatoshi Kataoka    }
152feec20a692c9ffdecf7855a45531a12f129086caSatoshi Kataoka}
153feec20a692c9ffdecf7855a45531a12f129086caSatoshi Kataoka
1540519fdd18ac4414b8298d3338db1c8ccce032170Satoshi Kataoka// TODO: Remove the "scale" parameter
1550519fdd18ac4414b8298d3338db1c8ccce032170Satoshi Kataoka// This function basically converts from a length to an edit distance. Accordingly, it's obviously
1560519fdd18ac4414b8298d3338db1c8ccce032170Satoshi Kataoka// wrong to compare with mMaxPointToKeyLength.
1570519fdd18ac4414b8298d3338db1c8ccce032170Satoshi Kataokafloat ProximityInfoState::getPointToKeyLength(
1580519fdd18ac4414b8298d3338db1c8ccce032170Satoshi Kataoka        const int inputIndex, const int codePoint, const float scale) const {
159ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi    const int keyId = mProximityInfo->getKeyIndexOf(codePoint);
160ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi    if (keyId != NOT_AN_INDEX) {
161ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi        const int index = inputIndex * mProximityInfo->getKeyCount() + keyId;
162e5aad5646309e80e1cd71533fb47a6be43f3aa2fSatoshi Kataoka        return min(mSampledDistanceCache_G[index] * scale, mMaxPointToKeyLength);
163ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi    }
1641e61493c50082264caaef862df02b1ccc84dc396Ken Wakasa    if (isSkippableCodePoint(codePoint)) {
165806eba452423e5e5971ef096dfae3fed180db665Keisuke Kuroyanagi        return 0.0f;
166806eba452423e5e5971ef096dfae3fed180db665Keisuke Kuroyanagi    }
167ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi    // If the char is not a key on the keyboard then return the max length.
168ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi    return MAX_POINT_TO_KEY_LENGTH;
169806eba452423e5e5971ef096dfae3fed180db665Keisuke Kuroyanagi}
170806eba452423e5e5971ef096dfae3fed180db665Keisuke Kuroyanagi
171a9763f93d76f97b9c6ed7dd1369a4d8cb016f06fSatoshi Kataokafloat ProximityInfoState::getPointToKeyLength_G(const int inputIndex, const int codePoint) const {
1720519fdd18ac4414b8298d3338db1c8ccce032170Satoshi Kataoka    return getPointToKeyLength(inputIndex, codePoint, 1.0f);
1730519fdd18ac4414b8298d3338db1c8ccce032170Satoshi Kataoka}
1740519fdd18ac4414b8298d3338db1c8ccce032170Satoshi Kataoka
1750519fdd18ac4414b8298d3338db1c8ccce032170Satoshi Kataoka// TODO: Remove the "scale" parameter
1760519fdd18ac4414b8298d3338db1c8ccce032170Satoshi Kataokafloat ProximityInfoState::getPointToKeyByIdLength(
1770519fdd18ac4414b8298d3338db1c8ccce032170Satoshi Kataoka        const int inputIndex, const int keyId, const float scale) const {
178d4828d5053ac30476b884c177235be0cac982c92Satoshi Kataoka    return ProximityInfoStateUtils::getPointToKeyByIdLength(mMaxPointToKeyLength,
179e5aad5646309e80e1cd71533fb47a6be43f3aa2fSatoshi Kataoka            &mSampledDistanceCache_G, mProximityInfo->getKeyCount(), inputIndex, keyId, scale);
180687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka}
181687a244703a02323ebd64433cbaead5def499861Satoshi Kataoka
1820519fdd18ac4414b8298d3338db1c8ccce032170Satoshi Kataokafloat ProximityInfoState::getPointToKeyByIdLength(const int inputIndex, const int keyId) const {
1830519fdd18ac4414b8298d3338db1c8ccce032170Satoshi Kataoka    return getPointToKeyByIdLength(inputIndex, keyId, 1.0f);
1840519fdd18ac4414b8298d3338db1c8ccce032170Satoshi Kataoka}
1850519fdd18ac4414b8298d3338db1c8ccce032170Satoshi Kataoka
1862c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa// In the following function, c is the current character of the dictionary word currently examined.
1872c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa// currentChars is an array containing the keys close to the character the user actually typed at
1882c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa// the same position. We want to see if c is in it: if so, then the word contains at that position
1892c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa// a character close to what the user typed.
1902c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa// What the user typed is actually the first character of the array.
1912c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa// proximityIndex is a pointer to the variable where getMatchedProximityId returns the index of c
1922c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa// in the proximity chars of the input index.
1932c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa// Notice : accented characters do not have a proximity list, so they are alone in their list. The
1942c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa// non-accented version of the character should be considered "close", but not the other keys close
1952c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa// to the non-accented version.
1962c2f3a90d8115777adbe9ffd597f344aede84276Ken WakasaProximityType ProximityInfoState::getMatchedProximityId(const int index, const int c,
1972c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa        const bool checkProximityChars, int *proximityIndex) const {
1982c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa    const int *currentCodePoints = getProximityCodePointsAt(index);
1992c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa    const int firstCodePoint = currentCodePoints[0];
2002c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa    const int baseLowerC = toBaseLowerCase(c);
2012c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa
2022c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa    // The first char in the array is what user typed. If it matches right away, that means the
2032c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa    // user typed that same char for this pos.
2042c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa    if (firstCodePoint == baseLowerC || firstCodePoint == c) {
2052c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa        return EQUIVALENT_CHAR;
2062c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa    }
2072c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa
2082c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa    if (!checkProximityChars) return UNRELATED_CHAR;
2092c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa
2102c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa    // If the non-accented, lowercased version of that first character matches c, then we have a
2112c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa    // non-accented version of the accented character the user typed. Treat it as a close char.
2122c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa    if (toBaseLowerCase(firstCodePoint) == baseLowerC) {
2132c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa        return NEAR_PROXIMITY_CHAR;
2142c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa    }
2152c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa
2162c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa    // Not an exact nor an accent-alike match: search the list of close keys
2172c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa    int j = 1;
2186c22439bf80da08576e86c1282afc5cfa431e235Ken Wakasa    while (j < MAX_PROXIMITY_CHARS_SIZE
2192c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa            && currentCodePoints[j] > ADDITIONAL_PROXIMITY_CHAR_DELIMITER_CODE) {
2202c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa        const bool matched = (currentCodePoints[j] == baseLowerC || currentCodePoints[j] == c);
2212c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa        if (matched) {
2222c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa            if (proximityIndex) {
2232c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa                *proximityIndex = j;
2242c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa            }
2252c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa            return NEAR_PROXIMITY_CHAR;
2262c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa        }
2272c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa        ++j;
2282c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa    }
2296c22439bf80da08576e86c1282afc5cfa431e235Ken Wakasa    if (j < MAX_PROXIMITY_CHARS_SIZE
2302c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa            && currentCodePoints[j] == ADDITIONAL_PROXIMITY_CHAR_DELIMITER_CODE) {
2312c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa        ++j;
2326c22439bf80da08576e86c1282afc5cfa431e235Ken Wakasa        while (j < MAX_PROXIMITY_CHARS_SIZE
2332c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa                && currentCodePoints[j] > ADDITIONAL_PROXIMITY_CHAR_DELIMITER_CODE) {
2342c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa            const bool matched = (currentCodePoints[j] == baseLowerC || currentCodePoints[j] == c);
2352c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa            if (matched) {
2362c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa                if (proximityIndex) {
2372c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa                    *proximityIndex = j;
2382c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa                }
2392c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa                return ADDITIONAL_PROXIMITY_CHAR;
2402c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa            }
2412c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa            ++j;
2422c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa        }
2432c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa    }
2442c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa    // Was not included, signal this as an unrelated character.
2452c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa    return UNRELATED_CHAR;
2462c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa}
2472c2f3a90d8115777adbe9ffd597f344aede84276Ken Wakasa
24895a49a527ac9c2c97cfcc758bd6f0d58fb4ad9c0Keisuke Kuroyanagi// Puts possible characters into filter and returns new filter size.
249082507e1da56c6cefe575ec3d6a334e9b717e3faKen Wakasaint ProximityInfoState::getAllPossibleChars(
250082507e1da56c6cefe575ec3d6a334e9b717e3faKen Wakasa        const size_t index, int *const filter, const int filterSize) const {
251feec20a692c9ffdecf7855a45531a12f129086caSatoshi Kataoka    if (index >= mSampledInputXs.size()) {
25295a49a527ac9c2c97cfcc758bd6f0d58fb4ad9c0Keisuke Kuroyanagi        return filterSize;
25395a49a527ac9c2c97cfcc758bd6f0d58fb4ad9c0Keisuke Kuroyanagi    }
25441f12ee27b269033fe818f7d52e81ba948a046c3Keisuke Kuroyanagi    int newFilterSize = filterSize;
255ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi    const int keyCount = mProximityInfo->getKeyCount();
256ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi    for (int j = 0; j < keyCount; ++j) {
257e5aad5646309e80e1cd71533fb47a6be43f3aa2fSatoshi Kataoka        if (mSampledSearchKeysVector[index].test(j)) {
258082507e1da56c6cefe575ec3d6a334e9b717e3faKen Wakasa            const int keyCodePoint = mProximityInfo->getCodePointOf(j);
25995a49a527ac9c2c97cfcc758bd6f0d58fb4ad9c0Keisuke Kuroyanagi            bool insert = true;
26095a49a527ac9c2c97cfcc758bd6f0d58fb4ad9c0Keisuke Kuroyanagi            // TODO: Avoid linear search
26195a49a527ac9c2c97cfcc758bd6f0d58fb4ad9c0Keisuke Kuroyanagi            for (int k = 0; k < filterSize; ++k) {
26295a49a527ac9c2c97cfcc758bd6f0d58fb4ad9c0Keisuke Kuroyanagi                if (filter[k] == keyCodePoint) {
26395a49a527ac9c2c97cfcc758bd6f0d58fb4ad9c0Keisuke Kuroyanagi                    insert = false;
26495a49a527ac9c2c97cfcc758bd6f0d58fb4ad9c0Keisuke Kuroyanagi                    break;
26595a49a527ac9c2c97cfcc758bd6f0d58fb4ad9c0Keisuke Kuroyanagi                }
26695a49a527ac9c2c97cfcc758bd6f0d58fb4ad9c0Keisuke Kuroyanagi            }
26795a49a527ac9c2c97cfcc758bd6f0d58fb4ad9c0Keisuke Kuroyanagi            if (insert) {
26841f12ee27b269033fe818f7d52e81ba948a046c3Keisuke Kuroyanagi                filter[newFilterSize++] = keyCodePoint;
26995a49a527ac9c2c97cfcc758bd6f0d58fb4ad9c0Keisuke Kuroyanagi            }
27095a49a527ac9c2c97cfcc758bd6f0d58fb4ad9c0Keisuke Kuroyanagi        }
27195a49a527ac9c2c97cfcc758bd6f0d58fb4ad9c0Keisuke Kuroyanagi    }
27241f12ee27b269033fe818f7d52e81ba948a046c3Keisuke Kuroyanagi    return newFilterSize;
27395a49a527ac9c2c97cfcc758bd6f0d58fb4ad9c0Keisuke Kuroyanagi}
2743811a28ddc07201930e0bbd2e1d01045b59af308Keisuke Kuroyanagi
275ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagibool ProximityInfoState::isKeyInSerchKeysAfterIndex(const int index, const int keyId) const {
27620b6775acc957896bdb038dfd99794d6cd7cea5aSatoshi Kataoka    ASSERT(keyId >= 0 && index >= 0 && index < mSampledInputSize);
277e5aad5646309e80e1cd71533fb47a6be43f3aa2fSatoshi Kataoka    return mSampledSearchKeysVector[index].test(keyId);
278ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi}
279ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi
280ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagifloat ProximityInfoState::getDirection(const int index0, const int index1) const {
281ee62b78c9675bddaf2437e0cf521f6115e1d9febSatoshi Kataoka    return ProximityInfoStateUtils::getDirection(
282ee62b78c9675bddaf2437e0cf521f6115e1d9febSatoshi Kataoka            &mSampledInputXs, &mSampledInputYs, index0, index1);
283ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi}
284ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi
285ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagifloat ProximityInfoState::getLineToKeyDistance(
286ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi        const int from, const int to, const int keyId, const bool extend) const {
287feec20a692c9ffdecf7855a45531a12f129086caSatoshi Kataoka    if (from < 0 || from > mSampledInputSize - 1) {
288ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi        return 0.0f;
289ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi    }
290feec20a692c9ffdecf7855a45531a12f129086caSatoshi Kataoka    if (to < 0 || to > mSampledInputSize - 1) {
291ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi        return 0.0f;
292ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi    }
293feec20a692c9ffdecf7855a45531a12f129086caSatoshi Kataoka    const int x0 = mSampledInputXs[from];
294feec20a692c9ffdecf7855a45531a12f129086caSatoshi Kataoka    const int y0 = mSampledInputYs[from];
295feec20a692c9ffdecf7855a45531a12f129086caSatoshi Kataoka    const int x1 = mSampledInputXs[to];
296feec20a692c9ffdecf7855a45531a12f129086caSatoshi Kataoka    const int y1 = mSampledInputYs[to];
297ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi
298ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi    const int keyX = mProximityInfo->getKeyCenterXOfKeyIdG(keyId);
299ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi    const int keyY = mProximityInfo->getKeyCenterYOfKeyIdG(keyId);
300ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi
3010c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa    return ProximityInfoUtils::pointToLineSegSquaredDistanceFloat(
3020c2227ab991774768414d8ea60a469f005eb9f1aKen Wakasa            keyX, keyY, x0, y0, x1, y1, extend);
303806eba452423e5e5971ef096dfae3fed180db665Keisuke Kuroyanagi}
304806eba452423e5e5971ef096dfae3fed180db665Keisuke Kuroyanagi
305e0349619acdba79223390c9925d81f7e88c7f8adSatoshi Kataokafloat ProximityInfoState::getMostProbableString(int *const codePointBuf) const {
30620b6775acc957896bdb038dfd99794d6cd7cea5aSatoshi Kataoka    memcpy(codePointBuf, mMostProbableString, sizeof(mMostProbableString));
30720b6775acc957896bdb038dfd99794d6cd7cea5aSatoshi Kataoka    return mMostProbableStringProbability;
308ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi}
309ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi
310f32869c6b6296a8bf594abdf0b18281d9312e54fSatoshi Kataokabool ProximityInfoState::hasSpaceProximity(const int index) const {
311f32869c6b6296a8bf594abdf0b18281d9312e54fSatoshi Kataoka    ASSERT(0 <= index && index < mSampledInputSize);
312f32869c6b6296a8bf594abdf0b18281d9312e54fSatoshi Kataoka    return mProximityInfo->hasSpaceProximity(getInputX(index), getInputY(index));
313f32869c6b6296a8bf594abdf0b18281d9312e54fSatoshi Kataoka}
314f32869c6b6296a8bf594abdf0b18281d9312e54fSatoshi Kataoka
315ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi// Returns a probability of mapping index to keyIndex.
316ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagifloat ProximityInfoState::getProbability(const int index, const int keyIndex) const {
317feec20a692c9ffdecf7855a45531a12f129086caSatoshi Kataoka    ASSERT(0 <= index && index < mSampledInputSize);
318ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi    hash_map_compat<int, float>::const_iterator it = mCharProbabilities[index].find(keyIndex);
319ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi    if (it != mCharProbabilities[index].end()) {
320ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi        return it->second;
321ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi    }
322ff74cc3e5e75fc0c6b9ffaa5e68d879775dc6115Keisuke Kuroyanagi    return static_cast<float>(MAX_POINT_TO_KEY_LENGTH);
323806eba452423e5e5971ef096dfae3fed180db665Keisuke Kuroyanagi}
3243e8c58f68d53e6cc9dbf59201c7bdfb8ad04a1cdSatoshi Kataoka} // namespace latinime
325