Merge "refactor proximity info state"

main
Satoshi Kataoka 2013-01-22 08:56:05 +00:00 committed by Android (Google) Code Review
commit 7c7d7115b7
7 changed files with 234 additions and 152 deletions

View File

@ -21,4 +21,8 @@ const int ProximityInfoParams::LOOKUP_RADIUS_PERCENTILE = 50;
const int ProximityInfoParams::FIRST_POINT_TIME_OFFSET_MILLIS = 150; const int ProximityInfoParams::FIRST_POINT_TIME_OFFSET_MILLIS = 150;
const int ProximityInfoParams::STRONG_DOUBLE_LETTER_TIME_MILLIS = 600; const int ProximityInfoParams::STRONG_DOUBLE_LETTER_TIME_MILLIS = 600;
const int ProximityInfoParams::MIN_DOUBLE_LETTER_BEELINE_SPEED_PERCENTILE = 5; 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 } // namespace latinime

View File

@ -27,8 +27,11 @@ class ProximityInfoParams {
static const int FIRST_POINT_TIME_OFFSET_MILLIS; static const int FIRST_POINT_TIME_OFFSET_MILLIS;
static const int STRONG_DOUBLE_LETTER_TIME_MILLIS; static const int STRONG_DOUBLE_LETTER_TIME_MILLIS;
static const int MIN_DOUBLE_LETTER_BEELINE_SPEED_PERCENTILE; 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: private:
DISALLOW_IMPLICIT_CONSTRUCTORS(ProximityInfoParams); DISALLOW_IMPLICIT_CONSTRUCTORS(ProximityInfoParams);
static const int NORMALIZED_SQUARED_DISTANCE_SCALING_FACTOR_LOG_2;
}; };
} // namespace latinime } // namespace latinime
#endif // LATINIME_PROXIMITY_INFO_PARAMS_H #endif // LATINIME_PROXIMITY_INFO_PARAMS_H

View File

@ -27,10 +27,6 @@
namespace latinime { 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; const int ProximityInfoState::NOT_A_CODE = -1;
void ProximityInfoState::initInputParams(const int pointerId, const float maxPointToKeyLength, 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 pushTouchPointStartIndex = 0;
int lastSavedInputSize = 0; int lastSavedInputSize = 0;
mMaxPointToKeyLength = maxPointToKeyLength; mMaxPointToKeyLength = maxPointToKeyLength;
if (mIsContinuationPossible && mInputIndice.size() > 1) { if (mIsContinuationPossible && mSampledInputIndice.size() > 1) {
// Just update difference. // Just update difference.
// Two points prior is never skipped. Thus, we pop 2 input point data here. // 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();
popInputData(); popInputData();
lastSavedInputSize = mSampledInputXs.size(); lastSavedInputSize = mSampledInputXs.size();
@ -72,9 +68,9 @@ void ProximityInfoState::initInputParams(const int pointerId, const float maxPoi
// Clear all data. // Clear all data.
mSampledInputXs.clear(); mSampledInputXs.clear();
mSampledInputYs.clear(); mSampledInputYs.clear();
mTimes.clear(); mSampledTimes.clear();
mInputIndice.clear(); mSampledInputIndice.clear();
mLengthCache.clear(); mSampledLengthCache.clear();
mDistanceCache_G.clear(); mDistanceCache_G.clear();
mNearKeysVector.clear(); mNearKeysVector.clear();
mSearchKeysVector.clear(); mSearchKeysVector.clear();
@ -93,56 +89,33 @@ void ProximityInfoState::initInputParams(const int pointerId, const float maxPoi
mSampledInputSize = ProximityInfoStateUtils::updateTouchPoints( mSampledInputSize = ProximityInfoStateUtils::updateTouchPoints(
mProximityInfo->getMostCommonKeyWidth(), mProximityInfo, mMaxPointToKeyLength, mProximityInfo->getMostCommonKeyWidth(), mProximityInfo, mMaxPointToKeyLength,
mInputProximities, xCoordinates, yCoordinates, times, pointerIds, inputSize, mInputProximities, xCoordinates, yCoordinates, times, pointerIds, inputSize,
isGeometric, pointerId, pushTouchPointStartIndex, isGeometric, pointerId, pushTouchPointStartIndex, &mSampledInputXs,
&mSampledInputXs, &mSampledInputYs, &mTimes, &mLengthCache, &mInputIndice); &mSampledInputYs, &mSampledTimes, &mSampledLengthCache, &mSampledInputIndice);
} }
if (mSampledInputSize > 0 && isGeometric) { if (mSampledInputSize > 0 && isGeometric) {
mAverageSpeed = ProximityInfoStateUtils::refreshSpeedRates( mAverageSpeed = ProximityInfoStateUtils::refreshSpeedRates(
inputSize, xCoordinates, yCoordinates, times, lastSavedInputSize, inputSize, xCoordinates, yCoordinates, times, lastSavedInputSize,
mSampledInputSize, &mSampledInputXs, &mSampledInputYs, &mTimes, &mLengthCache, mSampledInputSize, &mSampledInputXs, &mSampledInputYs, &mSampledTimes,
&mInputIndice, &mSpeedRates, &mDirections); &mSampledLengthCache, &mSampledInputIndice, &mSpeedRates, &mDirections);
ProximityInfoStateUtils::refreshBeelineSpeedRates( ProximityInfoStateUtils::refreshBeelineSpeedRates(
mProximityInfo->getMostCommonKeyWidth(), mAverageSpeed, inputSize, mProximityInfo->getMostCommonKeyWidth(), mAverageSpeed, inputSize,
xCoordinates, yCoordinates, times, mSampledInputSize, &mSampledInputXs, xCoordinates, yCoordinates, times, mSampledInputSize, &mSampledInputXs,
&mSampledInputYs, &mInputIndice, &mBeelineSpeedPercentiles); &mSampledInputYs, &mSampledInputIndice, &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]);
}
} }
if (mSampledInputSize > 0) { if (mSampledInputSize > 0) {
const int keyCount = mProximityInfo->getKeyCount(); ProximityInfoStateUtils::initGeometricDistanceInfos(
mNearKeysVector.resize(mSampledInputSize); mProximityInfo, mProximityInfo->getKeyCount(),
mSearchKeysVector.resize(mSampledInputSize); mSampledInputSize, lastSavedInputSize, &mSampledInputXs, &mSampledInputYs,
mDistanceCache_G.resize(mSampledInputSize * keyCount); &mNearKeysVector, &mSearchKeysVector, &mDistanceCache_G);
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;
}
}
}
if (isGeometric) { if (isGeometric) {
// updates probabilities of skipping or mapping each key for all points. // updates probabilities of skipping or mapping each key for all points.
ProximityInfoStateUtils::updateAlignPointProbabilities( ProximityInfoStateUtils::updateAlignPointProbabilities(
mMaxPointToKeyLength, mProximityInfo->getMostCommonKeyWidth(), mMaxPointToKeyLength, mProximityInfo->getMostCommonKeyWidth(),
keyCount, lastSavedInputSize, mSampledInputSize, &mSampledInputXs, mProximityInfo->getKeyCount(), lastSavedInputSize, mSampledInputSize,
&mSampledInputYs, &mSpeedRates, &mLengthCache, &mDistanceCache_G, &mSampledInputXs, &mSampledInputYs, &mSpeedRates, &mSampledLengthCache,
&mNearKeysVector, &mCharProbabilities); &mDistanceCache_G, &mNearKeysVector, &mCharProbabilities);
static const float READ_FORWORD_LENGTH_SCALE = 0.95f; static const float READ_FORWORD_LENGTH_SCALE = 0.95f;
const int readForwordLength = static_cast<int>( const int readForwordLength = static_cast<int>(
@ -153,7 +126,7 @@ void ProximityInfoState::initInputParams(const int pointerId, const float maxPoi
mSearchKeysVector[i].reset(); mSearchKeysVector[i].reset();
} }
for (int j = max(i, lastSavedInputSize); j < mSampledInputSize; ++j) { for (int j = max(i, lastSavedInputSize); j < mSampledInputSize; ++j) {
if (mLengthCache[j] - mLengthCache[i] >= readForwordLength) { if (mSampledLengthCache[j] - mSampledLengthCache[i] >= readForwordLength) {
break; break;
} }
mSearchKeysVector[i] |= mNearKeysVector[j]; mSearchKeysVector[i] |= mNearKeysVector[j];
@ -163,32 +136,9 @@ void ProximityInfoState::initInputParams(const int pointerId, const float maxPoi
} }
if (DEBUG_SAMPLING_POINTS) { if (DEBUG_SAMPLING_POINTS) {
std::stringstream originalX, originalY, sampledX, sampledY; ProximityInfoStateUtils::dump(isGeometric, inputSize, xCoordinates, yCoordinates,
for (int i = 0; i < inputSize; ++i) { mSampledInputSize, &mSampledInputXs, &mSampledInputYs, &mSpeedRates,
originalX << xCoordinates[i]; &mBeelineSpeedPercentiles);
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());
} }
// end // end
/////////////////////// ///////////////////////
@ -198,42 +148,15 @@ void ProximityInfoState::initInputParams(const int pointerId, const float maxPoi
mTouchPositionCorrectionEnabled = mSampledInputSize > 0 && mHasTouchPositionCorrectionData mTouchPositionCorrectionEnabled = mSampledInputSize > 0 && mHasTouchPositionCorrectionData
&& xCoordinates && yCoordinates; && xCoordinates && yCoordinates;
if (!isGeometric && pointerId == 0) { if (!isGeometric && pointerId == 0) {
for (int i = 0; i < inputSize; ++i) { ProximityInfoStateUtils::initPrimaryInputWord(
mPrimaryInputWord[i] = getPrimaryCodePointAt(i); inputSize, mInputProximities, mPrimaryInputWord);
} if (mTouchPositionCorrectionEnabled) {
ProximityInfoStateUtils::initNormalizedSquaredDistances(
for (int i = 0; i < mSampledInputSize && mTouchPositionCorrectionEnabled; ++i) { mProximityInfo, inputSize, xCoordinates, yCoordinates, mInputProximities,
const int *proximityCodePoints = getProximityCodePointsAt(i); hasInputCoordinates(), &mSampledInputXs, &mSampledInputYs,
const int primaryKey = proximityCodePoints[0]; mNormalizedSquaredDistances);
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);
}
}
} }
} }
if (DEBUG_GEO_FULL) { if (DEBUG_GEO_FULL) {
AKLOGI("ProximityState init finished: %d points out of %d", mSampledInputSize, inputSize); 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 { const bool isGeometric) const {
if (isGeometric) { if (isGeometric) {
for (int i = 0; i < mSampledInputSize; ++i) { for (int i = 0; i < mSampledInputSize; ++i) {
const int index = mInputIndice[i]; const int index = mSampledInputIndice[i];
if (index > inputSize || xCoordinates[index] != mSampledInputXs[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; return false;
} }
} }
@ -265,26 +188,9 @@ bool ProximityInfoState::checkAndReturnIsContinuationPossible(const int inputSiz
return true; 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 { int ProximityInfoState::getDuration(const int index) const {
if (index >= 0 && index < mSampledInputSize - 1) { if (index >= 0 && index < mSampledInputSize - 1) {
return mTimes[index + 1] - mTimes[index]; return mSampledTimes[index + 1] - mSampledTimes[index];
} }
return 0; return 0;
} }
@ -388,15 +294,6 @@ int ProximityInfoState::getSpaceY() const {
return mProximityInfo->getKeyCenterYOfKeyIdG(keyId); 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. // Puts possible characters into filter and returns new filter size.
int ProximityInfoState::getAllPossibleChars( int ProximityInfoState::getAllPossibleChars(
const size_t index, int *const filter, const int filterSize) const { 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() { void ProximityInfoState::popInputData() {
ProximityInfoStateUtils::popInputData(&mSampledInputXs, &mSampledInputYs, &mTimes, ProximityInfoStateUtils::popInputData(&mSampledInputXs, &mSampledInputYs, &mSampledTimes,
&mLengthCache, &mInputIndice); &mSampledLengthCache, &mSampledInputIndice);
} }
float ProximityInfoState::getDirection(const int index0, const int index1) const { float ProximityInfoState::getDirection(const int index0, const int index1) const {

View File

@ -32,9 +32,7 @@ class ProximityInfo;
class ProximityInfoState { class ProximityInfoState {
public: 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; static const int NOT_A_CODE;
///////////////////////////////////////// /////////////////////////////////////////
@ -52,10 +50,11 @@ class ProximityInfoState {
: mProximityInfo(0), mMaxPointToKeyLength(0.0f), mAverageSpeed(0.0f), : mProximityInfo(0), mMaxPointToKeyLength(0.0f), mAverageSpeed(0.0f),
mHasTouchPositionCorrectionData(false), mMostCommonKeyWidthSquare(0), mHasTouchPositionCorrectionData(false), mMostCommonKeyWidthSquare(0),
mKeyCount(0), mCellHeight(0), mCellWidth(0), mGridHeight(0), mGridWidth(0), mKeyCount(0), mCellHeight(0), mCellWidth(0), mGridHeight(0), mGridWidth(0),
mIsContinuationPossible(false), mSampledInputXs(), mSampledInputYs(), mTimes(), mIsContinuationPossible(false), mSampledInputXs(), mSampledInputYs(), mSampledTimes(),
mInputIndice(), mLengthCache(), mBeelineSpeedPercentiles(), mDistanceCache_G(), mSampledInputIndice(), mSampledLengthCache(), mBeelineSpeedPercentiles(),
mSpeedRates(), mDirections(), mCharProbabilities(), mNearKeysVector(), mDistanceCache_G(), mSpeedRates(), mDirections(), mCharProbabilities(),
mSearchKeysVector(), mTouchPositionCorrectionEnabled(false), mSampledInputSize(0) { mNearKeysVector(), mSearchKeysVector(), mTouchPositionCorrectionEnabled(false),
mSampledInputSize(0) {
memset(mInputProximities, 0, sizeof(mInputProximities)); memset(mInputProximities, 0, sizeof(mInputProximities));
memset(mNormalizedSquaredDistances, 0, sizeof(mNormalizedSquaredDistances)); memset(mNormalizedSquaredDistances, 0, sizeof(mNormalizedSquaredDistances));
memset(mPrimaryInputWord, 0, sizeof(mPrimaryInputWord)); memset(mPrimaryInputWord, 0, sizeof(mPrimaryInputWord));
@ -144,7 +143,7 @@ class ProximityInfoState {
bool hasSpaceProximity(const int index) const; bool hasSpaceProximity(const int index) const;
int getLengthCache(const int index) const { int getLengthCache(const int index) const {
return mLengthCache[index]; return mSampledLengthCache[index];
} }
bool isContinuationPossible() const { bool isContinuationPossible() const {
@ -210,7 +209,6 @@ class ProximityInfoState {
///////////////////////////////////////// /////////////////////////////////////////
// Defined here // // Defined here //
///////////////////////////////////////// /////////////////////////////////////////
inline float square(const float x) const { return x * x; }
bool hasInputCoordinates() const { bool hasInputCoordinates() const {
return mSampledInputXs.size() > 0 && mSampledInputYs.size() > 0; return mSampledInputXs.size() > 0 && mSampledInputYs.size() > 0;
@ -238,9 +236,9 @@ class ProximityInfoState {
std::vector<int> mSampledInputXs; std::vector<int> mSampledInputXs;
std::vector<int> mSampledInputYs; std::vector<int> mSampledInputYs;
std::vector<int> mTimes; std::vector<int> mSampledTimes;
std::vector<int> mInputIndice; std::vector<int> mSampledInputIndice;
std::vector<int> mLengthCache; std::vector<int> mSampledLengthCache;
std::vector<int> mBeelineSpeedPercentiles; std::vector<int> mBeelineSpeedPercentiles;
std::vector<float> mDistanceCache_G; std::vector<float> mDistanceCache_G;
std::vector<float> mSpeedRates; std::vector<float> mSpeedRates;

View File

@ -24,6 +24,7 @@
#include "proximity_info_state_utils.h" #include "proximity_info_state_utils.h"
namespace latinime { namespace latinime {
/* static */ int ProximityInfoStateUtils::updateTouchPoints(const int mostCommonKeyWidth, /* static */ int ProximityInfoStateUtils::updateTouchPoints(const int mostCommonKeyWidth,
const ProximityInfo *const proximityInfo, const int maxPointToKeyLength, const ProximityInfo *const proximityInfo, const int maxPointToKeyLength,
const int *const inputProximities, const int *const inputXCoordinates, const int *const inputProximities, const int *const inputXCoordinates,
@ -126,6 +127,114 @@ namespace latinime {
return getProximityCodePointsAt(inputProximities, index)[0]; 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, /* static */ void ProximityInfoStateUtils::popInputData(std::vector<int> *sampledInputXs,
std::vector<int> *sampledInputYs, std::vector<int> *sampledInputTimes, std::vector<int> *sampledInputYs, std::vector<int> *sampledInputTimes,
std::vector<int> *sampledLengthCache, std::vector<int> *sampledInputIndice) { std::vector<int> *sampledLengthCache, std::vector<int> *sampledInputIndice) {
@ -171,7 +280,7 @@ namespace latinime {
if (i > 0 && j < (*sampledInputIndice)[i - 1]) { if (i > 0 && j < (*sampledInputIndice)[i - 1]) {
break; break;
} }
// TODO: use mLengthCache instead? // TODO: use mSampledLengthCache instead?
length += getDistanceInt(xCoordinates[j], yCoordinates[j], length += getDistanceInt(xCoordinates[j], yCoordinates[j],
xCoordinates[j + 1], yCoordinates[j + 1]); xCoordinates[j + 1], yCoordinates[j + 1]);
duration += times[j + 1] - times[j]; duration += times[j + 1] - times[j];
@ -473,7 +582,7 @@ namespace latinime {
if (DEBUG_DOUBLE_LETTER) { if (DEBUG_DOUBLE_LETTER) {
AKLOGI("--- (%d, %d) double letter: start = %d, end = %d, dist = %d, time = %d," 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", " 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,
((static_cast<float>(beelineDistance) / static_cast<float>(time)) ((static_cast<float>(beelineDistance) / static_cast<float>(time))
/ mAverageSpeed), adjustedStartTime, adjustedEndTime); / mAverageSpeed), adjustedStartTime, adjustedEndTime);
@ -849,4 +958,45 @@ namespace latinime {
} }
return true; 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 } // namespace latinime

View File

@ -78,7 +78,29 @@ class ProximityInfoStateUtils {
static float getPointToKeyByIdLength(const float maxPointToKeyLength, static float getPointToKeyByIdLength(const float maxPointToKeyLength,
const std::vector<float> *const distanceCache_G, const int keyCount, const std::vector<float> *const distanceCache_G, const int keyCount,
const int inputIndex, const int keyId); 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: private:
DISALLOW_IMPLICIT_CONSTRUCTORS(ProximityInfoStateUtils); DISALLOW_IMPLICIT_CONSTRUCTORS(ProximityInfoStateUtils);
@ -121,6 +143,13 @@ class ProximityInfoStateUtils {
const int sampledInputSize, const std::vector<int> *const lengthCache, const int sampledInputSize, const std::vector<int> *const lengthCache,
const int index0, const int index1, const int index0, const int index1,
std::vector<hash_map_compat<int, float> > *charProbabilities); 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 } // namespace latinime
#endif // LATINIME_PROXIMITY_INFO_STATE_UTILS_H #endif // LATINIME_PROXIMITY_INFO_STATE_UTILS_H

View File

@ -18,6 +18,7 @@
#define LATINIME_SUGGEST_UTILS_H #define LATINIME_SUGGEST_UTILS_H
#include "defines.h" #include "defines.h"
#include "proximity_info_params.h"
#include "proximity_info_state.h" #include "proximity_info_state.h"
namespace latinime { namespace latinime {
@ -35,7 +36,7 @@ class SuggestUtils {
static const float R1 = NEUTRAL_SCORE_SQUARED_RADIUS; static const float R1 = NEUTRAL_SCORE_SQUARED_RADIUS;
static const float R2 = HALF_SCORE_SQUARED_RADIUS; static const float R2 = HALF_SCORE_SQUARED_RADIUS;
const float x = normalizedSquaredDistance / static_cast<float>( 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) const float factor = max((x < R1)
? (A * (R1 - x) + B * x) / R1 ? (A * (R1 - x) + B * x) / R1
: (B * (R2 - x) + C * (x - R1)) / (R2 - R1), MIN); : (B * (R2 - x) + C * (x - R1)) / (R2 - R1), MIN);