Merge "refactor proximity info state"
This commit is contained in:
commit
7c7d7115b7
7 changed files with 234 additions and 152 deletions
|
@ -21,4 +21,8 @@ const int ProximityInfoParams::LOOKUP_RADIUS_PERCENTILE = 50;
|
|||
const int ProximityInfoParams::FIRST_POINT_TIME_OFFSET_MILLIS = 150;
|
||||
const int ProximityInfoParams::STRONG_DOUBLE_LETTER_TIME_MILLIS = 600;
|
||||
const int ProximityInfoParams::MIN_DOUBLE_LETTER_BEELINE_SPEED_PERCENTILE = 5;
|
||||
const int ProximityInfoParams::NORMALIZED_SQUARED_DISTANCE_SCALING_FACTOR_LOG_2 = 10;
|
||||
const int ProximityInfoParams::NORMALIZED_SQUARED_DISTANCE_SCALING_FACTOR =
|
||||
1 << NORMALIZED_SQUARED_DISTANCE_SCALING_FACTOR_LOG_2;
|
||||
const float ProximityInfoParams::NOT_A_DISTANCE_FLOAT = -1.0f;
|
||||
} // namespace latinime
|
||||
|
|
|
@ -27,8 +27,11 @@ class ProximityInfoParams {
|
|||
static const int FIRST_POINT_TIME_OFFSET_MILLIS;
|
||||
static const int STRONG_DOUBLE_LETTER_TIME_MILLIS;
|
||||
static const int MIN_DOUBLE_LETTER_BEELINE_SPEED_PERCENTILE;
|
||||
static const int NORMALIZED_SQUARED_DISTANCE_SCALING_FACTOR;
|
||||
static const float NOT_A_DISTANCE_FLOAT;
|
||||
private:
|
||||
DISALLOW_IMPLICIT_CONSTRUCTORS(ProximityInfoParams);
|
||||
static const int NORMALIZED_SQUARED_DISTANCE_SCALING_FACTOR_LOG_2;
|
||||
};
|
||||
} // namespace latinime
|
||||
#endif // LATINIME_PROXIMITY_INFO_PARAMS_H
|
||||
|
|
|
@ -27,10 +27,6 @@
|
|||
|
||||
namespace latinime {
|
||||
|
||||
const int ProximityInfoState::NORMALIZED_SQUARED_DISTANCE_SCALING_FACTOR_LOG_2 = 10;
|
||||
const int ProximityInfoState::NORMALIZED_SQUARED_DISTANCE_SCALING_FACTOR =
|
||||
1 << NORMALIZED_SQUARED_DISTANCE_SCALING_FACTOR_LOG_2;
|
||||
const float ProximityInfoState::NOT_A_DISTANCE_FLOAT = -1.0f;
|
||||
const int ProximityInfoState::NOT_A_CODE = -1;
|
||||
|
||||
void ProximityInfoState::initInputParams(const int pointerId, const float maxPointToKeyLength,
|
||||
|
@ -61,10 +57,10 @@ void ProximityInfoState::initInputParams(const int pointerId, const float maxPoi
|
|||
int pushTouchPointStartIndex = 0;
|
||||
int lastSavedInputSize = 0;
|
||||
mMaxPointToKeyLength = maxPointToKeyLength;
|
||||
if (mIsContinuationPossible && mInputIndice.size() > 1) {
|
||||
if (mIsContinuationPossible && mSampledInputIndice.size() > 1) {
|
||||
// Just update difference.
|
||||
// Two points prior is never skipped. Thus, we pop 2 input point data here.
|
||||
pushTouchPointStartIndex = mInputIndice[mInputIndice.size() - 2];
|
||||
pushTouchPointStartIndex = mSampledInputIndice[mSampledInputIndice.size() - 2];
|
||||
popInputData();
|
||||
popInputData();
|
||||
lastSavedInputSize = mSampledInputXs.size();
|
||||
|
@ -72,9 +68,9 @@ void ProximityInfoState::initInputParams(const int pointerId, const float maxPoi
|
|||
// Clear all data.
|
||||
mSampledInputXs.clear();
|
||||
mSampledInputYs.clear();
|
||||
mTimes.clear();
|
||||
mInputIndice.clear();
|
||||
mLengthCache.clear();
|
||||
mSampledTimes.clear();
|
||||
mSampledInputIndice.clear();
|
||||
mSampledLengthCache.clear();
|
||||
mDistanceCache_G.clear();
|
||||
mNearKeysVector.clear();
|
||||
mSearchKeysVector.clear();
|
||||
|
@ -93,56 +89,33 @@ void ProximityInfoState::initInputParams(const int pointerId, const float maxPoi
|
|||
mSampledInputSize = ProximityInfoStateUtils::updateTouchPoints(
|
||||
mProximityInfo->getMostCommonKeyWidth(), mProximityInfo, mMaxPointToKeyLength,
|
||||
mInputProximities, xCoordinates, yCoordinates, times, pointerIds, inputSize,
|
||||
isGeometric, pointerId, pushTouchPointStartIndex,
|
||||
&mSampledInputXs, &mSampledInputYs, &mTimes, &mLengthCache, &mInputIndice);
|
||||
isGeometric, pointerId, pushTouchPointStartIndex, &mSampledInputXs,
|
||||
&mSampledInputYs, &mSampledTimes, &mSampledLengthCache, &mSampledInputIndice);
|
||||
}
|
||||
|
||||
if (mSampledInputSize > 0 && isGeometric) {
|
||||
mAverageSpeed = ProximityInfoStateUtils::refreshSpeedRates(
|
||||
inputSize, xCoordinates, yCoordinates, times, lastSavedInputSize,
|
||||
mSampledInputSize, &mSampledInputXs, &mSampledInputYs, &mTimes, &mLengthCache,
|
||||
&mInputIndice, &mSpeedRates, &mDirections);
|
||||
mSampledInputSize, &mSampledInputXs, &mSampledInputYs, &mSampledTimes,
|
||||
&mSampledLengthCache, &mSampledInputIndice, &mSpeedRates, &mDirections);
|
||||
ProximityInfoStateUtils::refreshBeelineSpeedRates(
|
||||
mProximityInfo->getMostCommonKeyWidth(), mAverageSpeed, inputSize,
|
||||
xCoordinates, yCoordinates, times, mSampledInputSize, &mSampledInputXs,
|
||||
&mSampledInputYs, &mInputIndice, &mBeelineSpeedPercentiles);
|
||||
}
|
||||
|
||||
if (DEBUG_GEO_FULL) {
|
||||
for (int i = 0; i < mSampledInputSize; ++i) {
|
||||
AKLOGI("Sampled(%d): x = %d, y = %d, time = %d", i, mSampledInputXs[i],
|
||||
mSampledInputYs[i], mTimes[i]);
|
||||
}
|
||||
&mSampledInputYs, &mSampledInputIndice, &mBeelineSpeedPercentiles);
|
||||
}
|
||||
|
||||
if (mSampledInputSize > 0) {
|
||||
const int keyCount = mProximityInfo->getKeyCount();
|
||||
mNearKeysVector.resize(mSampledInputSize);
|
||||
mSearchKeysVector.resize(mSampledInputSize);
|
||||
mDistanceCache_G.resize(mSampledInputSize * keyCount);
|
||||
for (int i = lastSavedInputSize; i < mSampledInputSize; ++i) {
|
||||
mNearKeysVector[i].reset();
|
||||
mSearchKeysVector[i].reset();
|
||||
static const float NEAR_KEY_NORMALIZED_SQUARED_THRESHOLD = 4.0f;
|
||||
for (int k = 0; k < keyCount; ++k) {
|
||||
const int index = i * keyCount + k;
|
||||
const int x = mSampledInputXs[i];
|
||||
const int y = mSampledInputYs[i];
|
||||
const float normalizedSquaredDistance =
|
||||
mProximityInfo->getNormalizedSquaredDistanceFromCenterFloatG(k, x, y);
|
||||
mDistanceCache_G[index] = normalizedSquaredDistance;
|
||||
if (normalizedSquaredDistance < NEAR_KEY_NORMALIZED_SQUARED_THRESHOLD) {
|
||||
mNearKeysVector[i][k] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
ProximityInfoStateUtils::initGeometricDistanceInfos(
|
||||
mProximityInfo, mProximityInfo->getKeyCount(),
|
||||
mSampledInputSize, lastSavedInputSize, &mSampledInputXs, &mSampledInputYs,
|
||||
&mNearKeysVector, &mSearchKeysVector, &mDistanceCache_G);
|
||||
if (isGeometric) {
|
||||
// updates probabilities of skipping or mapping each key for all points.
|
||||
ProximityInfoStateUtils::updateAlignPointProbabilities(
|
||||
mMaxPointToKeyLength, mProximityInfo->getMostCommonKeyWidth(),
|
||||
keyCount, lastSavedInputSize, mSampledInputSize, &mSampledInputXs,
|
||||
&mSampledInputYs, &mSpeedRates, &mLengthCache, &mDistanceCache_G,
|
||||
&mNearKeysVector, &mCharProbabilities);
|
||||
mProximityInfo->getKeyCount(), lastSavedInputSize, mSampledInputSize,
|
||||
&mSampledInputXs, &mSampledInputYs, &mSpeedRates, &mSampledLengthCache,
|
||||
&mDistanceCache_G, &mNearKeysVector, &mCharProbabilities);
|
||||
|
||||
static const float READ_FORWORD_LENGTH_SCALE = 0.95f;
|
||||
const int readForwordLength = static_cast<int>(
|
||||
|
@ -153,7 +126,7 @@ void ProximityInfoState::initInputParams(const int pointerId, const float maxPoi
|
|||
mSearchKeysVector[i].reset();
|
||||
}
|
||||
for (int j = max(i, lastSavedInputSize); j < mSampledInputSize; ++j) {
|
||||
if (mLengthCache[j] - mLengthCache[i] >= readForwordLength) {
|
||||
if (mSampledLengthCache[j] - mSampledLengthCache[i] >= readForwordLength) {
|
||||
break;
|
||||
}
|
||||
mSearchKeysVector[i] |= mNearKeysVector[j];
|
||||
|
@ -163,32 +136,9 @@ void ProximityInfoState::initInputParams(const int pointerId, const float maxPoi
|
|||
}
|
||||
|
||||
if (DEBUG_SAMPLING_POINTS) {
|
||||
std::stringstream originalX, originalY, sampledX, sampledY;
|
||||
for (int i = 0; i < inputSize; ++i) {
|
||||
originalX << xCoordinates[i];
|
||||
originalY << yCoordinates[i];
|
||||
if (i != inputSize - 1) {
|
||||
originalX << ";";
|
||||
originalY << ";";
|
||||
}
|
||||
}
|
||||
AKLOGI("===== sampled points =====");
|
||||
for (int i = 0; i < mSampledInputSize; ++i) {
|
||||
if (isGeometric) {
|
||||
AKLOGI("%d: x = %d, y = %d, time = %d, relative speed = %.4f, beeline speed = %d",
|
||||
i, mSampledInputXs[i], mSampledInputYs[i], mTimes[i], mSpeedRates[i],
|
||||
getBeelineSpeedPercentile(i));
|
||||
}
|
||||
sampledX << mSampledInputXs[i];
|
||||
sampledY << mSampledInputYs[i];
|
||||
if (i != mSampledInputSize - 1) {
|
||||
sampledX << ";";
|
||||
sampledY << ";";
|
||||
}
|
||||
}
|
||||
AKLOGI("original points:\n%s, %s,\nsampled points:\n%s, %s,\n",
|
||||
originalX.str().c_str(), originalY.str().c_str(), sampledX.str().c_str(),
|
||||
sampledY.str().c_str());
|
||||
ProximityInfoStateUtils::dump(isGeometric, inputSize, xCoordinates, yCoordinates,
|
||||
mSampledInputSize, &mSampledInputXs, &mSampledInputYs, &mSpeedRates,
|
||||
&mBeelineSpeedPercentiles);
|
||||
}
|
||||
// end
|
||||
///////////////////////
|
||||
|
@ -198,42 +148,15 @@ void ProximityInfoState::initInputParams(const int pointerId, const float maxPoi
|
|||
mTouchPositionCorrectionEnabled = mSampledInputSize > 0 && mHasTouchPositionCorrectionData
|
||||
&& xCoordinates && yCoordinates;
|
||||
if (!isGeometric && pointerId == 0) {
|
||||
for (int i = 0; i < inputSize; ++i) {
|
||||
mPrimaryInputWord[i] = getPrimaryCodePointAt(i);
|
||||
}
|
||||
|
||||
for (int i = 0; i < mSampledInputSize && mTouchPositionCorrectionEnabled; ++i) {
|
||||
const int *proximityCodePoints = getProximityCodePointsAt(i);
|
||||
const int primaryKey = proximityCodePoints[0];
|
||||
const int x = xCoordinates[i];
|
||||
const int y = yCoordinates[i];
|
||||
if (DEBUG_PROXIMITY_CHARS) {
|
||||
int a = x + y + primaryKey;
|
||||
a += 0;
|
||||
AKLOGI("--- Primary = %c, x = %d, y = %d", primaryKey, x, y);
|
||||
}
|
||||
for (int j = 0; j < MAX_PROXIMITY_CHARS_SIZE && proximityCodePoints[j] > 0;
|
||||
++j) {
|
||||
const int currentCodePoint = proximityCodePoints[j];
|
||||
const float squaredDistance =
|
||||
hasInputCoordinates() ? calculateNormalizedSquaredDistance(
|
||||
mProximityInfo->getKeyIndexOf(currentCodePoint), i) :
|
||||
NOT_A_DISTANCE_FLOAT;
|
||||
if (squaredDistance >= 0.0f) {
|
||||
mNormalizedSquaredDistances[i * MAX_PROXIMITY_CHARS_SIZE + j] =
|
||||
(int) (squaredDistance * NORMALIZED_SQUARED_DISTANCE_SCALING_FACTOR);
|
||||
} else {
|
||||
mNormalizedSquaredDistances[i * MAX_PROXIMITY_CHARS_SIZE + j] =
|
||||
(j == 0) ? EQUIVALENT_CHAR_WITHOUT_DISTANCE_INFO :
|
||||
PROXIMITY_CHAR_WITHOUT_DISTANCE_INFO;
|
||||
}
|
||||
if (DEBUG_PROXIMITY_CHARS) {
|
||||
AKLOGI("--- Proximity (%d) = %c", j, currentCodePoint);
|
||||
}
|
||||
}
|
||||
ProximityInfoStateUtils::initPrimaryInputWord(
|
||||
inputSize, mInputProximities, mPrimaryInputWord);
|
||||
if (mTouchPositionCorrectionEnabled) {
|
||||
ProximityInfoStateUtils::initNormalizedSquaredDistances(
|
||||
mProximityInfo, inputSize, xCoordinates, yCoordinates, mInputProximities,
|
||||
hasInputCoordinates(), &mSampledInputXs, &mSampledInputYs,
|
||||
mNormalizedSquaredDistances);
|
||||
}
|
||||
}
|
||||
|
||||
if (DEBUG_GEO_FULL) {
|
||||
AKLOGI("ProximityState init finished: %d points out of %d", mSampledInputSize, inputSize);
|
||||
}
|
||||
|
@ -244,9 +167,9 @@ bool ProximityInfoState::checkAndReturnIsContinuationPossible(const int inputSiz
|
|||
const bool isGeometric) const {
|
||||
if (isGeometric) {
|
||||
for (int i = 0; i < mSampledInputSize; ++i) {
|
||||
const int index = mInputIndice[i];
|
||||
const int index = mSampledInputIndice[i];
|
||||
if (index > inputSize || xCoordinates[index] != mSampledInputXs[i] ||
|
||||
yCoordinates[index] != mSampledInputYs[i] || times[index] != mTimes[i]) {
|
||||
yCoordinates[index] != mSampledInputYs[i] || times[index] != mSampledTimes[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -265,26 +188,9 @@ bool ProximityInfoState::checkAndReturnIsContinuationPossible(const int inputSiz
|
|||
return true;
|
||||
}
|
||||
|
||||
float ProximityInfoState::calculateNormalizedSquaredDistance(
|
||||
const int keyIndex, const int inputIndex) const {
|
||||
if (keyIndex == NOT_AN_INDEX) {
|
||||
return NOT_A_DISTANCE_FLOAT;
|
||||
}
|
||||
if (!mProximityInfo->hasSweetSpotData(keyIndex)) {
|
||||
return NOT_A_DISTANCE_FLOAT;
|
||||
}
|
||||
if (NOT_A_COORDINATE == mSampledInputXs[inputIndex]) {
|
||||
return NOT_A_DISTANCE_FLOAT;
|
||||
}
|
||||
const float squaredDistance = calculateSquaredDistanceFromSweetSpotCenter(
|
||||
keyIndex, inputIndex);
|
||||
const float squaredRadius = square(mProximityInfo->getSweetSpotRadiiAt(keyIndex));
|
||||
return squaredDistance / squaredRadius;
|
||||
}
|
||||
|
||||
int ProximityInfoState::getDuration(const int index) const {
|
||||
if (index >= 0 && index < mSampledInputSize - 1) {
|
||||
return mTimes[index + 1] - mTimes[index];
|
||||
return mSampledTimes[index + 1] - mSampledTimes[index];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -388,15 +294,6 @@ int ProximityInfoState::getSpaceY() const {
|
|||
return mProximityInfo->getKeyCenterYOfKeyIdG(keyId);
|
||||
}
|
||||
|
||||
float ProximityInfoState::calculateSquaredDistanceFromSweetSpotCenter(
|
||||
const int keyIndex, const int inputIndex) const {
|
||||
const float sweetSpotCenterX = mProximityInfo->getSweetSpotCenterXAt(keyIndex);
|
||||
const float sweetSpotCenterY = mProximityInfo->getSweetSpotCenterYAt(keyIndex);
|
||||
const float inputX = static_cast<float>(mSampledInputXs[inputIndex]);
|
||||
const float inputY = static_cast<float>(mSampledInputYs[inputIndex]);
|
||||
return square(inputX - sweetSpotCenterX) + square(inputY - sweetSpotCenterY);
|
||||
}
|
||||
|
||||
// Puts possible characters into filter and returns new filter size.
|
||||
int ProximityInfoState::getAllPossibleChars(
|
||||
const size_t index, int *const filter, const int filterSize) const {
|
||||
|
@ -431,8 +328,8 @@ bool ProximityInfoState::isKeyInSerchKeysAfterIndex(const int index, const int k
|
|||
}
|
||||
|
||||
void ProximityInfoState::popInputData() {
|
||||
ProximityInfoStateUtils::popInputData(&mSampledInputXs, &mSampledInputYs, &mTimes,
|
||||
&mLengthCache, &mInputIndice);
|
||||
ProximityInfoStateUtils::popInputData(&mSampledInputXs, &mSampledInputYs, &mSampledTimes,
|
||||
&mSampledLengthCache, &mSampledInputIndice);
|
||||
}
|
||||
|
||||
float ProximityInfoState::getDirection(const int index0, const int index1) const {
|
||||
|
|
|
@ -32,9 +32,7 @@ class ProximityInfo;
|
|||
|
||||
class ProximityInfoState {
|
||||
public:
|
||||
static const int NORMALIZED_SQUARED_DISTANCE_SCALING_FACTOR_LOG_2;
|
||||
static const int NORMALIZED_SQUARED_DISTANCE_SCALING_FACTOR;
|
||||
static const float NOT_A_DISTANCE_FLOAT;
|
||||
|
||||
static const int NOT_A_CODE;
|
||||
|
||||
/////////////////////////////////////////
|
||||
|
@ -52,10 +50,11 @@ class ProximityInfoState {
|
|||
: mProximityInfo(0), mMaxPointToKeyLength(0.0f), mAverageSpeed(0.0f),
|
||||
mHasTouchPositionCorrectionData(false), mMostCommonKeyWidthSquare(0),
|
||||
mKeyCount(0), mCellHeight(0), mCellWidth(0), mGridHeight(0), mGridWidth(0),
|
||||
mIsContinuationPossible(false), mSampledInputXs(), mSampledInputYs(), mTimes(),
|
||||
mInputIndice(), mLengthCache(), mBeelineSpeedPercentiles(), mDistanceCache_G(),
|
||||
mSpeedRates(), mDirections(), mCharProbabilities(), mNearKeysVector(),
|
||||
mSearchKeysVector(), mTouchPositionCorrectionEnabled(false), mSampledInputSize(0) {
|
||||
mIsContinuationPossible(false), mSampledInputXs(), mSampledInputYs(), mSampledTimes(),
|
||||
mSampledInputIndice(), mSampledLengthCache(), mBeelineSpeedPercentiles(),
|
||||
mDistanceCache_G(), mSpeedRates(), mDirections(), mCharProbabilities(),
|
||||
mNearKeysVector(), mSearchKeysVector(), mTouchPositionCorrectionEnabled(false),
|
||||
mSampledInputSize(0) {
|
||||
memset(mInputProximities, 0, sizeof(mInputProximities));
|
||||
memset(mNormalizedSquaredDistances, 0, sizeof(mNormalizedSquaredDistances));
|
||||
memset(mPrimaryInputWord, 0, sizeof(mPrimaryInputWord));
|
||||
|
@ -144,7 +143,7 @@ class ProximityInfoState {
|
|||
bool hasSpaceProximity(const int index) const;
|
||||
|
||||
int getLengthCache(const int index) const {
|
||||
return mLengthCache[index];
|
||||
return mSampledLengthCache[index];
|
||||
}
|
||||
|
||||
bool isContinuationPossible() const {
|
||||
|
@ -210,7 +209,6 @@ class ProximityInfoState {
|
|||
/////////////////////////////////////////
|
||||
// Defined here //
|
||||
/////////////////////////////////////////
|
||||
inline float square(const float x) const { return x * x; }
|
||||
|
||||
bool hasInputCoordinates() const {
|
||||
return mSampledInputXs.size() > 0 && mSampledInputYs.size() > 0;
|
||||
|
@ -238,9 +236,9 @@ class ProximityInfoState {
|
|||
|
||||
std::vector<int> mSampledInputXs;
|
||||
std::vector<int> mSampledInputYs;
|
||||
std::vector<int> mTimes;
|
||||
std::vector<int> mInputIndice;
|
||||
std::vector<int> mLengthCache;
|
||||
std::vector<int> mSampledTimes;
|
||||
std::vector<int> mSampledInputIndice;
|
||||
std::vector<int> mSampledLengthCache;
|
||||
std::vector<int> mBeelineSpeedPercentiles;
|
||||
std::vector<float> mDistanceCache_G;
|
||||
std::vector<float> mSpeedRates;
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "proximity_info_state_utils.h"
|
||||
|
||||
namespace latinime {
|
||||
|
||||
/* static */ int ProximityInfoStateUtils::updateTouchPoints(const int mostCommonKeyWidth,
|
||||
const ProximityInfo *const proximityInfo, const int maxPointToKeyLength,
|
||||
const int *const inputProximities, const int *const inputXCoordinates,
|
||||
|
@ -126,6 +127,114 @@ namespace latinime {
|
|||
return getProximityCodePointsAt(inputProximities, index)[0];
|
||||
}
|
||||
|
||||
/* static */ void ProximityInfoStateUtils::initPrimaryInputWord(
|
||||
const int inputSize, const int *const inputProximities, int *primaryInputWord) {
|
||||
for (int i = 0; i < inputSize; ++i) {
|
||||
primaryInputWord[i] = getPrimaryCodePointAt(inputProximities, i);
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ float ProximityInfoStateUtils::calculateSquaredDistanceFromSweetSpotCenter(
|
||||
const ProximityInfo *const proximityInfo, const std::vector<int> *const sampledInputXs,
|
||||
const std::vector<int> *const sampledInputYs, const int keyIndex,
|
||||
const int inputIndex) {
|
||||
const float sweetSpotCenterX = proximityInfo->getSweetSpotCenterXAt(keyIndex);
|
||||
const float sweetSpotCenterY = proximityInfo->getSweetSpotCenterYAt(keyIndex);
|
||||
const float inputX = static_cast<float>((*sampledInputXs)[inputIndex]);
|
||||
const float inputY = static_cast<float>((*sampledInputYs)[inputIndex]);
|
||||
return SQUARE_FLOAT(inputX - sweetSpotCenterX) + SQUARE_FLOAT(inputY - sweetSpotCenterY);
|
||||
}
|
||||
|
||||
/* static */ float ProximityInfoStateUtils::calculateNormalizedSquaredDistance(
|
||||
const ProximityInfo *const proximityInfo, const std::vector<int> *const sampledInputXs,
|
||||
const std::vector<int> *const sampledInputYs,
|
||||
const int keyIndex, const int inputIndex) {
|
||||
if (keyIndex == NOT_AN_INDEX) {
|
||||
return ProximityInfoParams::NOT_A_DISTANCE_FLOAT;
|
||||
}
|
||||
if (!proximityInfo->hasSweetSpotData(keyIndex)) {
|
||||
return ProximityInfoParams::NOT_A_DISTANCE_FLOAT;
|
||||
}
|
||||
if (NOT_A_COORDINATE == (*sampledInputXs)[inputIndex]) {
|
||||
return ProximityInfoParams::NOT_A_DISTANCE_FLOAT;
|
||||
}
|
||||
const float squaredDistance = calculateSquaredDistanceFromSweetSpotCenter(proximityInfo,
|
||||
sampledInputXs, sampledInputYs, keyIndex, inputIndex);
|
||||
const float squaredRadius = SQUARE_FLOAT(proximityInfo->getSweetSpotRadiiAt(keyIndex));
|
||||
return squaredDistance / squaredRadius;
|
||||
}
|
||||
|
||||
/* static */ void ProximityInfoStateUtils::initNormalizedSquaredDistances(
|
||||
const ProximityInfo *const proximityInfo, const int inputSize,
|
||||
const int *inputXCoordinates, const int *inputYCoordinates,
|
||||
const int *const inputProximities, const bool hasInputCoordinates,
|
||||
const std::vector<int> *const sampledInputXs,
|
||||
const std::vector<int> *const sampledInputYs,
|
||||
int *normalizedSquaredDistances) {
|
||||
for (int i = 0; i < inputSize; ++i) {
|
||||
const int *proximityCodePoints = getProximityCodePointsAt(inputProximities, i);
|
||||
const int primaryKey = proximityCodePoints[0];
|
||||
const int x = inputXCoordinates[i];
|
||||
const int y = inputYCoordinates[i];
|
||||
if (DEBUG_PROXIMITY_CHARS) {
|
||||
int a = x + y + primaryKey;
|
||||
a += 0;
|
||||
AKLOGI("--- Primary = %c, x = %d, y = %d", primaryKey, x, y);
|
||||
}
|
||||
for (int j = 0; j < MAX_PROXIMITY_CHARS_SIZE && proximityCodePoints[j] > 0;
|
||||
++j) {
|
||||
const int currentCodePoint = proximityCodePoints[j];
|
||||
const float squaredDistance =
|
||||
hasInputCoordinates ? calculateNormalizedSquaredDistance(
|
||||
proximityInfo, sampledInputXs, sampledInputYs,
|
||||
proximityInfo->getKeyIndexOf(currentCodePoint), i) :
|
||||
ProximityInfoParams::NOT_A_DISTANCE_FLOAT;
|
||||
if (squaredDistance >= 0.0f) {
|
||||
normalizedSquaredDistances[i * MAX_PROXIMITY_CHARS_SIZE + j] =
|
||||
(int) (squaredDistance
|
||||
* ProximityInfoParams::NORMALIZED_SQUARED_DISTANCE_SCALING_FACTOR);
|
||||
} else {
|
||||
normalizedSquaredDistances[i * MAX_PROXIMITY_CHARS_SIZE + j] =
|
||||
(j == 0) ? EQUIVALENT_CHAR_WITHOUT_DISTANCE_INFO :
|
||||
PROXIMITY_CHAR_WITHOUT_DISTANCE_INFO;
|
||||
}
|
||||
if (DEBUG_PROXIMITY_CHARS) {
|
||||
AKLOGI("--- Proximity (%d) = %c", j, currentCodePoint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* static */ void ProximityInfoStateUtils::initGeometricDistanceInfos(
|
||||
const ProximityInfo *const proximityInfo, const int keyCount,
|
||||
const int sampledInputSize, const int lastSavedInputSize,
|
||||
const std::vector<int> *const sampledInputXs,
|
||||
const std::vector<int> *const sampledInputYs,
|
||||
std::vector<NearKeycodesSet> *nearKeysVector,
|
||||
std::vector<NearKeycodesSet> *searchKeysVector,
|
||||
std::vector<float> *distanceCache_G) {
|
||||
nearKeysVector->resize(sampledInputSize);
|
||||
searchKeysVector->resize(sampledInputSize);
|
||||
distanceCache_G->resize(sampledInputSize * keyCount);
|
||||
for (int i = lastSavedInputSize; i < sampledInputSize; ++i) {
|
||||
(*nearKeysVector)[i].reset();
|
||||
(*searchKeysVector)[i].reset();
|
||||
static const float NEAR_KEY_NORMALIZED_SQUARED_THRESHOLD = 4.0f;
|
||||
for (int k = 0; k < keyCount; ++k) {
|
||||
const int index = i * keyCount + k;
|
||||
const int x = (*sampledInputXs)[i];
|
||||
const int y = (*sampledInputYs)[i];
|
||||
const float normalizedSquaredDistance =
|
||||
proximityInfo->getNormalizedSquaredDistanceFromCenterFloatG(k, x, y);
|
||||
(*distanceCache_G)[index] = normalizedSquaredDistance;
|
||||
if (normalizedSquaredDistance < NEAR_KEY_NORMALIZED_SQUARED_THRESHOLD) {
|
||||
(*nearKeysVector)[i][k] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ void ProximityInfoStateUtils::popInputData(std::vector<int> *sampledInputXs,
|
||||
std::vector<int> *sampledInputYs, std::vector<int> *sampledInputTimes,
|
||||
std::vector<int> *sampledLengthCache, std::vector<int> *sampledInputIndice) {
|
||||
|
@ -171,7 +280,7 @@ namespace latinime {
|
|||
if (i > 0 && j < (*sampledInputIndice)[i - 1]) {
|
||||
break;
|
||||
}
|
||||
// TODO: use mLengthCache instead?
|
||||
// TODO: use mSampledLengthCache instead?
|
||||
length += getDistanceInt(xCoordinates[j], yCoordinates[j],
|
||||
xCoordinates[j + 1], yCoordinates[j + 1]);
|
||||
duration += times[j + 1] - times[j];
|
||||
|
@ -473,7 +582,7 @@ namespace latinime {
|
|||
if (DEBUG_DOUBLE_LETTER) {
|
||||
AKLOGI("--- (%d, %d) double letter: start = %d, end = %d, dist = %d, time = %d,"
|
||||
" speed = %f, ave = %f, val = %f, start time = %d, end time = %d",
|
||||
id, mInputIndice[id], start, end, beelineDistance, time,
|
||||
id, mSampledInputIndice[id], start, end, beelineDistance, time,
|
||||
(static_cast<float>(beelineDistance) / static_cast<float>(time)), mAverageSpeed,
|
||||
((static_cast<float>(beelineDistance) / static_cast<float>(time))
|
||||
/ mAverageSpeed), adjustedStartTime, adjustedEndTime);
|
||||
|
@ -849,4 +958,45 @@ namespace latinime {
|
|||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* static */ void ProximityInfoStateUtils::dump(const bool isGeometric, const int inputSize,
|
||||
const int *const inputXCoordinates, const int *const inputYCoordinates,
|
||||
const int sampledInputSize, const std::vector<int> *const sampledInputXs,
|
||||
const std::vector<int> *const sampledInputYs,
|
||||
const std::vector<float> *const sampledSpeedRates,
|
||||
const std::vector<int> *const sampledBeelineSpeedPercentiles) {
|
||||
if (DEBUG_GEO_FULL) {
|
||||
for (int i = 0; i < sampledInputSize; ++i) {
|
||||
AKLOGI("Sampled(%d): x = %d, y = %d, time = %d", i, mSampledInputXs[i],
|
||||
mSampledInputYs[i], mSampledTimes ? mSampledTimes[i], -1);
|
||||
}
|
||||
}
|
||||
|
||||
std::stringstream originalX, originalY, sampledX, sampledY;
|
||||
for (int i = 0; i < inputSize; ++i) {
|
||||
originalX << inputXCoordinates[i];
|
||||
originalY << inputYCoordinates[i];
|
||||
if (i != inputSize - 1) {
|
||||
originalX << ";";
|
||||
originalY << ";";
|
||||
}
|
||||
}
|
||||
AKLOGI("===== sampled points =====");
|
||||
for (int i = 0; i < sampledInputSize; ++i) {
|
||||
if (isGeometric) {
|
||||
AKLOGI("%d: x = %d, y = %d, time = %d, relative speed = %.4f, beeline speed = %d",
|
||||
i, mSampledInputXs[i], mSampledInputYs[i], mSampledTimes[i], mSpeedRates[i],
|
||||
getBeelineSpeedPercentile(i));
|
||||
}
|
||||
sampledX << (*sampledInputXs)[i];
|
||||
sampledY << (*sampledInputYs)[i];
|
||||
if (i != sampledInputSize - 1) {
|
||||
sampledX << ";";
|
||||
sampledY << ";";
|
||||
}
|
||||
}
|
||||
AKLOGI("original points:\n%s, %s,\nsampled points:\n%s, %s,\n",
|
||||
originalX.str().c_str(), originalY.str().c_str(), sampledX.str().c_str(),
|
||||
sampledY.str().c_str());
|
||||
}
|
||||
} // namespace latinime
|
||||
|
|
|
@ -78,7 +78,29 @@ class ProximityInfoStateUtils {
|
|||
static float getPointToKeyByIdLength(const float maxPointToKeyLength,
|
||||
const std::vector<float> *const distanceCache_G, const int keyCount,
|
||||
const int inputIndex, const int keyId);
|
||||
|
||||
static void initGeometricDistanceInfos(
|
||||
const ProximityInfo *const proximityInfo, const int keyCount,
|
||||
const int sampledInputSize, const int lastSavedInputSize,
|
||||
const std::vector<int> *const sampledInputXs,
|
||||
const std::vector<int> *const sampledInputYs,
|
||||
std::vector<NearKeycodesSet> *nearKeysVector,
|
||||
std::vector<NearKeycodesSet> *searchKeysVector,
|
||||
std::vector<float> *distanceCache_G);
|
||||
static void initPrimaryInputWord(
|
||||
const int inputSize, const int *const inputProximities, int *primaryInputWord);
|
||||
static void initNormalizedSquaredDistances(
|
||||
const ProximityInfo *const proximityInfo, const int inputSize,
|
||||
const int *inputXCoordinates, const int *inputYCoordinates,
|
||||
const int *const inputProximities, const bool hasInputCoordinates,
|
||||
const std::vector<int> *const sampledInputXs,
|
||||
const std::vector<int> *const sampledInputYs,
|
||||
int *normalizedSquaredDistances);
|
||||
static void dump(const bool isGeometric, const int inputSize,
|
||||
const int *const inputXCoordinates, const int *const inputYCoordinates,
|
||||
const int sampledInputSize, const std::vector<int> *const sampledInputXs,
|
||||
const std::vector<int> *const sampledInputYs,
|
||||
const std::vector<float> *const sampledSpeedRates,
|
||||
const std::vector<int> *const sampledBeelineSpeedPercentiles);
|
||||
private:
|
||||
DISALLOW_IMPLICIT_CONSTRUCTORS(ProximityInfoStateUtils);
|
||||
|
||||
|
@ -121,6 +143,13 @@ class ProximityInfoStateUtils {
|
|||
const int sampledInputSize, const std::vector<int> *const lengthCache,
|
||||
const int index0, const int index1,
|
||||
std::vector<hash_map_compat<int, float> > *charProbabilities);
|
||||
static float calculateSquaredDistanceFromSweetSpotCenter(
|
||||
const ProximityInfo *const proximityInfo, const std::vector<int> *const sampledInputXs,
|
||||
const std::vector<int> *const sampledInputYs, const int keyIndex,
|
||||
const int inputIndex);
|
||||
static float calculateNormalizedSquaredDistance(
|
||||
const ProximityInfo *const proximityInfo, const std::vector<int> *const sampledInputXs,
|
||||
const std::vector<int> *const sampledInputYs, const int keyIndex, const int inputIndex);
|
||||
};
|
||||
} // namespace latinime
|
||||
#endif // LATINIME_PROXIMITY_INFO_STATE_UTILS_H
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#define LATINIME_SUGGEST_UTILS_H
|
||||
|
||||
#include "defines.h"
|
||||
#include "proximity_info_params.h"
|
||||
#include "proximity_info_state.h"
|
||||
|
||||
namespace latinime {
|
||||
|
@ -35,7 +36,7 @@ class SuggestUtils {
|
|||
static const float R1 = NEUTRAL_SCORE_SQUARED_RADIUS;
|
||||
static const float R2 = HALF_SCORE_SQUARED_RADIUS;
|
||||
const float x = normalizedSquaredDistance / static_cast<float>(
|
||||
ProximityInfoState::NORMALIZED_SQUARED_DISTANCE_SCALING_FACTOR);
|
||||
ProximityInfoParams::NORMALIZED_SQUARED_DISTANCE_SCALING_FACTOR);
|
||||
const float factor = max((x < R1)
|
||||
? (A * (R1 - x) + B * x) / R1
|
||||
: (B * (R2 - x) + C * (x - R1)) / (R2 - R1), MIN);
|
||||
|
|
Loading…
Reference in a new issue