diff --git a/native/jni/src/proximity_info_params.cpp b/native/jni/src/proximity_info_params.cpp index f7b3d4d71..8a17bf132 100644 --- a/native/jni/src/proximity_info_params.cpp +++ b/native/jni/src/proximity_info_params.cpp @@ -14,6 +14,7 @@ * limitations under the License. */ +#include "defines.h" #include "proximity_info_params.h" namespace latinime { @@ -26,10 +27,17 @@ 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; -// Per method constants +/* Per method constants */ +// Used by ProximityInfoStateUtils::initGeometricDistanceInfos() const float ProximityInfoParams::NEAR_KEY_NORMALIZED_SQUARED_THRESHOLD = 4.0f; + +// Used by ProximityInfoStateUtils::updateNearKeysDistances() const float ProximityInfoParams::NEAR_KEY_THRESHOLD_FOR_DISTANCE = 2.0f; + +// Used by ProximityInfoStateUtils::isPrevLocalMin() const float ProximityInfoParams::MARGIN_FOR_PREV_LOCAL_MIN = 0.01f; + +// Used by ProximityInfoStateUtils::getPointScore() const int ProximityInfoParams::DISTANCE_BASE_SCALE = 100; const float ProximityInfoParams::NEAR_KEY_THRESHOLD_FOR_POINT_SCORE = 0.6f; const int ProximityInfoParams::CORNER_CHECK_DISTANCE_THRESHOLD_SCALE = 25; @@ -39,6 +47,52 @@ const float ProximityInfoParams::CORNER_ANGLE_THRESHOLD_FOR_POINT_SCORE = M_PI_F const float ProximityInfoParams::CORNER_SUM_ANGLE_THRESHOLD = M_PI_F / 4.0f; const float ProximityInfoParams::CORNER_SCORE = 1.0f; +// Used by ProximityInfoStateUtils::refreshSpeedRates() +const int ProximityInfoParams::NUM_POINTS_FOR_SPEED_CALCULATION = 2; + +// Used by ProximityInfoStateUtils::pushTouchPoint() +const int ProximityInfoParams::LAST_POINT_SKIP_DISTANCE_SCALE = 4; + +// Used by ProximityInfoStateUtils::updateAlignPointProbabilities() +const float ProximityInfoParams::MIN_PROBABILITY = 0.000001f; +const float ProximityInfoParams::MAX_SKIP_PROBABILITY = 0.95f; +const float ProximityInfoParams::SKIP_FIRST_POINT_PROBABILITY = 0.01f; +const float ProximityInfoParams::SKIP_LAST_POINT_PROBABILITY = 0.1f; +const float ProximityInfoParams::MIN_SPEED_RATE_FOR_SKIP_PROBABILITY = 0.15f; +const float ProximityInfoParams::SPEED_WEIGHT_FOR_SKIP_PROBABILITY = 0.9f; +const float ProximityInfoParams::SLOW_STRAIGHT_WEIGHT_FOR_SKIP_PROBABILITY = 0.6f; +const float ProximityInfoParams::NEAREST_DISTANCE_WEIGHT = 0.5f; +const float ProximityInfoParams::NEAREST_DISTANCE_BIAS = 0.5f; +const float ProximityInfoParams::NEAREST_DISTANCE_WEIGHT_FOR_LAST = 0.6f; +const float ProximityInfoParams::NEAREST_DISTANCE_BIAS_FOR_LAST = 0.4f; +const float ProximityInfoParams::ANGLE_WEIGHT = 0.90f; +const float ProximityInfoParams::DEEP_CORNER_ANGLE_THRESHOLD = M_PI_F * 60.0f / 180.0f; +const float ProximityInfoParams::SKIP_DEEP_CORNER_PROBABILITY = 0.1f; +const float ProximityInfoParams::CORNER_ANGLE_THRESHOLD = M_PI_F * 30.0f / 180.0f; +const float ProximityInfoParams::STRAIGHT_ANGLE_THRESHOLD = M_PI_F * 15.0f / 180.0f; +const float ProximityInfoParams::SKIP_CORNER_PROBABILITY = 0.4f; +const float ProximityInfoParams::SPEED_MARGIN = 0.1f; +const float ProximityInfoParams::CENTER_VALUE_OF_NORMALIZED_DISTRIBUTION = 0.0f; +// TODO: The variance is critical for accuracy; thus, adjusting these parameter by machine +// learning or something would be efficient. +const float ProximityInfoParams::SPEEDxANGLE_WEIGHT_FOR_STANDARD_DIVIATION = 0.3f; +const float ProximityInfoParams::MAX_SPEEDxANGLE_RATE_FOR_STANDERD_DIVIATION = 0.25f; +const float ProximityInfoParams::SPEEDxNEAREST_WEIGHT_FOR_STANDARD_DIVIATION = 0.5f; +const float ProximityInfoParams::MAX_SPEEDxNEAREST_RATE_FOR_STANDERD_DIVIATION = 0.15f; +const float ProximityInfoParams::MIN_STANDERD_DIVIATION = 0.37f; +const float ProximityInfoParams::PREV_DISTANCE_WEIGHT = 0.5f; +const float ProximityInfoParams::NEXT_DISTANCE_WEIGHT = 0.6f; + +// Used by ProximityInfoStateUtils::suppressCharProbabilities() +const float ProximityInfoParams::SUPPRESSION_LENGTH_WEIGHT = 1.5f; +const float ProximityInfoParams::MIN_SUPPRESSION_RATE = 0.1f; +const float ProximityInfoParams::SUPPRESSION_WEIGHT = 0.5f; +const float ProximityInfoParams::SUPPRESSION_WEIGHT_FOR_PROBABILITY_GAIN = 0.1f; +const float ProximityInfoParams::SKIP_PROBABALITY_WEIGHT_FOR_PROBABILITY_GAIN = 0.3f; + +// Used by ProximityInfoStateUtils::getMostProbableString() +const float ProximityInfoParams::DEMOTION_LOG_PROBABILITY = 0.3f; + // TODO: Investigate if this is required const float ProximityInfoParams::SEARCH_KEY_RADIUS_RATIO = 0.95f; } // namespace latinime diff --git a/native/jni/src/proximity_info_params.h b/native/jni/src/proximity_info_params.h index 978b99917..fb7e82313 100644 --- a/native/jni/src/proximity_info_params.h +++ b/native/jni/src/proximity_info_params.h @@ -50,6 +50,50 @@ class ProximityInfoParams { static const float CORNER_SUM_ANGLE_THRESHOLD; static const float CORNER_SCORE; + // Used by ProximityInfoStateUtils::refreshSpeedRates() + static const int NUM_POINTS_FOR_SPEED_CALCULATION; + + // Used by ProximityInfoStateUtils::pushTouchPoint() + static const int LAST_POINT_SKIP_DISTANCE_SCALE; + + // Used by ProximityInfoStateUtils::updateAlignPointProbabilities() + static const float MIN_PROBABILITY; + static const float MAX_SKIP_PROBABILITY; + static const float SKIP_FIRST_POINT_PROBABILITY; + static const float SKIP_LAST_POINT_PROBABILITY; + static const float MIN_SPEED_RATE_FOR_SKIP_PROBABILITY; + static const float SPEED_WEIGHT_FOR_SKIP_PROBABILITY; + static const float SLOW_STRAIGHT_WEIGHT_FOR_SKIP_PROBABILITY; + static const float NEAREST_DISTANCE_WEIGHT; + static const float NEAREST_DISTANCE_BIAS; + static const float NEAREST_DISTANCE_WEIGHT_FOR_LAST; + static const float NEAREST_DISTANCE_BIAS_FOR_LAST; + static const float ANGLE_WEIGHT; + static const float DEEP_CORNER_ANGLE_THRESHOLD; + static const float SKIP_DEEP_CORNER_PROBABILITY; + static const float CORNER_ANGLE_THRESHOLD; + static const float STRAIGHT_ANGLE_THRESHOLD; + static const float SKIP_CORNER_PROBABILITY; + static const float SPEED_MARGIN; + static const float CENTER_VALUE_OF_NORMALIZED_DISTRIBUTION; + static const float SPEEDxANGLE_WEIGHT_FOR_STANDARD_DIVIATION; + static const float MAX_SPEEDxANGLE_RATE_FOR_STANDERD_DIVIATION; + static const float SPEEDxNEAREST_WEIGHT_FOR_STANDARD_DIVIATION; + static const float MAX_SPEEDxNEAREST_RATE_FOR_STANDERD_DIVIATION; + static const float MIN_STANDERD_DIVIATION; + static const float PREV_DISTANCE_WEIGHT; + static const float NEXT_DISTANCE_WEIGHT; + + // Used by ProximityInfoStateUtils::suppressCharProbabilities() + static const float SUPPRESSION_LENGTH_WEIGHT; + static const float MIN_SUPPRESSION_RATE; + static const float SUPPRESSION_WEIGHT; + static const float SUPPRESSION_WEIGHT_FOR_PROBABILITY_GAIN; + static const float SKIP_PROBABALITY_WEIGHT_FOR_PROBABILITY_GAIN; + + // Used by ProximityInfoStateUtils::getMostProbableString() + static const float DEMOTION_LOG_PROBABILITY; + private: DISALLOW_IMPLICIT_CONSTRUCTORS(ProximityInfoParams); static const int NORMALIZED_SQUARED_DISTANCE_SCALING_FACTOR_LOG_2; diff --git a/native/jni/src/proximity_info_state.cpp b/native/jni/src/proximity_info_state.cpp index fbdc2c816..4c1ffb30e 100644 --- a/native/jni/src/proximity_info_state.cpp +++ b/native/jni/src/proximity_info_state.cpp @@ -89,29 +89,28 @@ void ProximityInfoState::initInputParams(const int pointerId, const float maxPoi } if (xCoordinates && yCoordinates) { - mSampledInputSize = ProximityInfoStateUtils::updateTouchPoints( - mProximityInfo->getMostCommonKeyWidth(), mProximityInfo, mMaxPointToKeyLength, - mInputProximities, xCoordinates, yCoordinates, times, pointerIds, inputSize, - isGeometric, pointerId, pushTouchPointStartIndex, &mSampledInputXs, - &mSampledInputYs, &mSampledTimes, &mSampledLengthCache, &mSampledInputIndice); + mSampledInputSize = ProximityInfoStateUtils::updateTouchPoints(mProximityInfo, + mMaxPointToKeyLength, mInputProximities, xCoordinates, yCoordinates, times, + pointerIds, inputSize, isGeometric, pointerId, pushTouchPointStartIndex, + &mSampledInputXs, &mSampledInputYs, &mSampledTimes, &mSampledLengthCache, + &mSampledInputIndice); } if (mSampledInputSize > 0 && isGeometric) { - mAverageSpeed = ProximityInfoStateUtils::refreshSpeedRates( - inputSize, xCoordinates, yCoordinates, times, lastSavedInputSize, - mSampledInputSize, &mSampledInputXs, &mSampledInputYs, &mSampledTimes, - &mSampledLengthCache, &mSampledInputIndice, &mSpeedRates, &mDirections); - ProximityInfoStateUtils::refreshBeelineSpeedRates( - mProximityInfo->getMostCommonKeyWidth(), mAverageSpeed, inputSize, - xCoordinates, yCoordinates, times, mSampledInputSize, &mSampledInputXs, - &mSampledInputYs, &mSampledInputIndice, &mBeelineSpeedPercentiles); + mAverageSpeed = ProximityInfoStateUtils::refreshSpeedRates(inputSize, xCoordinates, + yCoordinates, times, lastSavedInputSize, mSampledInputSize, &mSampledInputXs, + &mSampledInputYs, &mSampledTimes, &mSampledLengthCache, &mSampledInputIndice, + &mSpeedRates, &mDirections); + ProximityInfoStateUtils::refreshBeelineSpeedRates(mProximityInfo->getMostCommonKeyWidth(), + mAverageSpeed, inputSize, xCoordinates, yCoordinates, times, mSampledInputSize, + &mSampledInputXs, &mSampledInputYs, &mSampledInputIndice, + &mBeelineSpeedPercentiles); } if (mSampledInputSize > 0) { - ProximityInfoStateUtils::initGeometricDistanceInfos( - mProximityInfo, mProximityInfo->getKeyCount(), - mSampledInputSize, lastSavedInputSize, &mSampledInputXs, &mSampledInputYs, - &mSampledNearKeysVector, &mSampledDistanceCache_G); + ProximityInfoStateUtils::initGeometricDistanceInfos(mProximityInfo, mSampledInputSize, + lastSavedInputSize, &mSampledInputXs, &mSampledInputYs, &mSampledNearKeysVector, + &mSampledDistanceCache_G); if (isGeometric) { // updates probabilities of skipping or mapping each key for all points. ProximityInfoStateUtils::updateAlignPointProbabilities( diff --git a/native/jni/src/proximity_info_state_utils.cpp b/native/jni/src/proximity_info_state_utils.cpp index da3f03deb..f9b69d264 100644 --- a/native/jni/src/proximity_info_state_utils.cpp +++ b/native/jni/src/proximity_info_state_utils.cpp @@ -38,7 +38,7 @@ namespace latinime { return nextStartIndex; } -/* static */ int ProximityInfoStateUtils::updateTouchPoints(const int mostCommonKeyWidth, +/* static */ int ProximityInfoStateUtils::updateTouchPoints( const ProximityInfo *const proximityInfo, const int maxPointToKeyLength, const int *const inputProximities, const int *const inputXCoordinates, const int *const inputYCoordinates, const int *const times, const int *const pointerIds, @@ -106,15 +106,14 @@ namespace latinime { const float prevAngle = getAngle( inputXCoordinates[i - 2], inputYCoordinates[i - 2], inputXCoordinates[i - 1], inputYCoordinates[i - 1]); - const float currentAngle = - getAngle(inputXCoordinates[i - 1], inputYCoordinates[i - 1], x, y); + const float currentAngle = getAngle( + inputXCoordinates[i - 1], inputYCoordinates[i - 1], x, y); sumAngle += getAngleDiff(prevAngle, currentAngle); } - if (pushTouchPoint(mostCommonKeyWidth, proximityInfo, maxPointToKeyLength, - i, c, x, y, time, isGeometric /* doSampling */, - i == lastInputIndex, sumAngle, currentNearKeysDistances, - prevNearKeysDistances, prevPrevNearKeysDistances, + if (pushTouchPoint(proximityInfo, maxPointToKeyLength, i, c, x, y, time, + isGeometric /* doSampling */, i == lastInputIndex, sumAngle, + currentNearKeysDistances, prevNearKeysDistances, prevPrevNearKeysDistances, sampledInputXs, sampledInputYs, sampledInputTimes, sampledLengthCache, sampledInputIndice)) { // Previous point information was popped. @@ -222,12 +221,13 @@ namespace latinime { } /* static */ void ProximityInfoStateUtils::initGeometricDistanceInfos( - const ProximityInfo *const proximityInfo, const int keyCount, const int sampledInputSize, + const ProximityInfo *const proximityInfo, const int sampledInputSize, const int lastSavedInputSize, const std::vector *const sampledInputXs, const std::vector *const sampledInputYs, std::vector *SampledNearKeysVector, std::vector *SampledDistanceCache_G) { SampledNearKeysVector->resize(sampledInputSize); + const int keyCount = proximityInfo->getKeyCount(); SampledDistanceCache_G->resize(sampledInputSize * keyCount); for (int i = lastSavedInputSize; i < sampledInputSize; ++i) { (*SampledNearKeysVector)[i].reset(); @@ -275,10 +275,11 @@ namespace latinime { int duration = 0; // Calculate velocity by using distances and durations of - // NUM_POINTS_FOR_SPEED_CALCULATION points for both forward and backward. - static const int NUM_POINTS_FOR_SPEED_CALCULATION = 2; - for (int j = index; j < min(inputSize - 1, index + NUM_POINTS_FOR_SPEED_CALCULATION); - ++j) { + // ProximityInfoParams::NUM_POINTS_FOR_SPEED_CALCULATION points for both forward and + // backward. + const int forwardNumPoints = min(inputSize - 1, + index + ProximityInfoParams::NUM_POINTS_FOR_SPEED_CALCULATION); + for (int j = index; j < forwardNumPoints; ++j) { if (i < sampledInputSize - 1 && j >= (*sampledInputIndice)[i + 1]) { break; } @@ -286,7 +287,9 @@ namespace latinime { xCoordinates[j + 1], yCoordinates[j + 1]); duration += times[j + 1] - times[j]; } - for (int j = index - 1; j >= max(0, index - NUM_POINTS_FOR_SPEED_CALCULATION); --j) { + const int backwardNumPoints = max(0, + index - ProximityInfoParams::NUM_POINTS_FOR_SPEED_CALCULATION); + for (int j = index - 1; j >= backwardNumPoints; --j) { if (i > 0 && j < (*sampledInputIndice)[i - 1]) { break; } @@ -434,9 +437,8 @@ namespace latinime { // Sampling touch point and pushing information to vectors. // Returning if previous point is popped or not. -/* static */ bool ProximityInfoStateUtils::pushTouchPoint(const int mostCommonKeyWidth, - const ProximityInfo *const proximityInfo, const int maxPointToKeyLength, - const int inputIndex, const int nodeCodePoint, int x, int y, +/* static */ bool ProximityInfoStateUtils::pushTouchPoint(const ProximityInfo *const proximityInfo, + const int maxPointToKeyLength, const int inputIndex, const int nodeCodePoint, int x, int y, const int time, const bool doSampling, const bool isLastPoint, const float sumAngle, NearKeysDistanceMap *const currentNearKeysDistances, const NearKeysDistanceMap *const prevNearKeysDistances, @@ -444,7 +446,7 @@ namespace latinime { std::vector *sampledInputXs, std::vector *sampledInputYs, std::vector *sampledInputTimes, std::vector *sampledLengthCache, std::vector *sampledInputIndice) { - static const int LAST_POINT_SKIP_DISTANCE_SCALE = 4; + const int mostCommonKeyWidth = proximityInfo->getMostCommonKeyWidth(); size_t size = sampledInputXs->size(); bool popped = false; @@ -465,16 +467,16 @@ namespace latinime { } // Check if the last point should be skipped. if (isLastPoint && size > 0) { - if (getDistanceInt(x, y, sampledInputXs->back(), - sampledInputYs->back()) * LAST_POINT_SKIP_DISTANCE_SCALE - < mostCommonKeyWidth) { + if (getDistanceInt(x, y, sampledInputXs->back(), sampledInputYs->back()) + * ProximityInfoParams::LAST_POINT_SKIP_DISTANCE_SCALE < mostCommonKeyWidth) { // This point is not used because it's too close to the previous point. if (DEBUG_GEO_FULL) { AKLOGI("p0: size = %zd, x = %d, y = %d, lx = %d, ly = %d, dist = %d, " "width = %d", size, x, y, sampledInputXs->back(), sampledInputYs->back(), getDistanceInt( x, y, sampledInputXs->back(), sampledInputYs->back()), - mostCommonKeyWidth / LAST_POINT_SKIP_DISTANCE_SCALE); + mostCommonKeyWidth + / ProximityInfoParams::LAST_POINT_SKIP_DISTANCE_SCALE); } return popped; } @@ -664,35 +666,14 @@ namespace latinime { const std::vector *const SampledDistanceCache_G, std::vector *SampledNearKeysVector, std::vector > *charProbabilities) { - static const float MIN_PROBABILITY = 0.000001f; - static const float MAX_SKIP_PROBABILITY = 0.95f; - static const float SKIP_FIRST_POINT_PROBABILITY = 0.01f; - static const float SKIP_LAST_POINT_PROBABILITY = 0.1f; - static const float MIN_SPEED_RATE_FOR_SKIP_PROBABILITY = 0.15f; - static const float SPEED_WEIGHT_FOR_SKIP_PROBABILITY = 0.9f; - static const float SLOW_STRAIGHT_WEIGHT_FOR_SKIP_PROBABILITY = 0.6f; - static const float NEAREST_DISTANCE_WEIGHT = 0.5f; - static const float NEAREST_DISTANCE_BIAS = 0.5f; - static const float NEAREST_DISTANCE_WEIGHT_FOR_LAST = 0.6f; - static const float NEAREST_DISTANCE_BIAS_FOR_LAST = 0.4f; - - static const float ANGLE_WEIGHT = 0.90f; - static const float DEEP_CORNER_ANGLE_THRESHOLD = M_PI_F * 60.0f / 180.0f; - static const float SKIP_DEEP_CORNER_PROBABILITY = 0.1f; - static const float CORNER_ANGLE_THRESHOLD = M_PI_F * 30.0f / 180.0f; - static const float STRAIGHT_ANGLE_THRESHOLD = M_PI_F * 15.0f / 180.0f; - static const float SKIP_CORNER_PROBABILITY = 0.4f; - static const float SPEED_MARGIN = 0.1f; - static const float CENTER_VALUE_OF_NORMALIZED_DISTRIBUTION = 0.0f; - charProbabilities->resize(sampledInputSize); // Calculates probabilities of using a point as a correlated point with the character // for each point. for (int i = start; i < sampledInputSize; ++i) { (*charProbabilities)[i].clear(); - // First, calculates skip probability. Starts form MIN_SKIP_PROBABILITY. + // First, calculates skip probability. Starts from MAX_SKIP_PROBABILITY. // Note that all values that are multiplied to this probability should be in [0.0, 1.0]; - float skipProbability = MAX_SKIP_PROBABILITY; + float skipProbability = ProximityInfoParams::MAX_SKIP_PROBABILITY; const float currentAngle = getPointAngle(sampledInputXs, sampledInputYs, i); const float speedRate = (*sampledSpeedRates)[i]; @@ -709,78 +690,74 @@ namespace latinime { } if (i == 0) { - skipProbability *= min(1.0f, nearestKeyDistance * NEAREST_DISTANCE_WEIGHT - + NEAREST_DISTANCE_BIAS); + skipProbability *= min(1.0f, + nearestKeyDistance * ProximityInfoParams::NEAREST_DISTANCE_WEIGHT + + ProximityInfoParams::NEAREST_DISTANCE_BIAS); // Promote the first point - skipProbability *= SKIP_FIRST_POINT_PROBABILITY; + skipProbability *= ProximityInfoParams::SKIP_FIRST_POINT_PROBABILITY; } else if (i == sampledInputSize - 1) { - skipProbability *= min(1.0f, nearestKeyDistance * NEAREST_DISTANCE_WEIGHT_FOR_LAST - + NEAREST_DISTANCE_BIAS_FOR_LAST); + skipProbability *= min(1.0f, + nearestKeyDistance * ProximityInfoParams::NEAREST_DISTANCE_WEIGHT_FOR_LAST + + ProximityInfoParams::NEAREST_DISTANCE_BIAS_FOR_LAST); // Promote the last point - skipProbability *= SKIP_LAST_POINT_PROBABILITY; + skipProbability *= ProximityInfoParams::SKIP_LAST_POINT_PROBABILITY; } else { // If the current speed is relatively slower than adjacent keys, we promote this point. - if ((*sampledSpeedRates)[i - 1] - SPEED_MARGIN > speedRate - && speedRate < (*sampledSpeedRates)[i + 1] - SPEED_MARGIN) { - if (currentAngle < CORNER_ANGLE_THRESHOLD) { + if ((*sampledSpeedRates)[i - 1] - ProximityInfoParams::SPEED_MARGIN > speedRate + && speedRate + < (*sampledSpeedRates)[i + 1] - ProximityInfoParams::SPEED_MARGIN) { + if (currentAngle < ProximityInfoParams::CORNER_ANGLE_THRESHOLD) { skipProbability *= min(1.0f, speedRate - * SLOW_STRAIGHT_WEIGHT_FOR_SKIP_PROBABILITY); + * ProximityInfoParams::SLOW_STRAIGHT_WEIGHT_FOR_SKIP_PROBABILITY); } else { // If the angle is small enough, we promote this point more. (e.g. pit vs put) - skipProbability *= min(1.0f, speedRate * SPEED_WEIGHT_FOR_SKIP_PROBABILITY - + MIN_SPEED_RATE_FOR_SKIP_PROBABILITY); + skipProbability *= min(1.0f, + speedRate * ProximityInfoParams::SPEED_WEIGHT_FOR_SKIP_PROBABILITY + + ProximityInfoParams::MIN_SPEED_RATE_FOR_SKIP_PROBABILITY); } } - skipProbability *= min(1.0f, speedRate * nearestKeyDistance * - NEAREST_DISTANCE_WEIGHT + NEAREST_DISTANCE_BIAS); + skipProbability *= min(1.0f, + speedRate * nearestKeyDistance * ProximityInfoParams::NEAREST_DISTANCE_WEIGHT + + ProximityInfoParams::NEAREST_DISTANCE_BIAS); // Adjusts skip probability by a rate depending on angle. // ANGLE_RATE of skipProbability is adjusted by current angle. - skipProbability *= (M_PI_F - currentAngle) / M_PI_F * ANGLE_WEIGHT - + (1.0f - ANGLE_WEIGHT); - if (currentAngle > DEEP_CORNER_ANGLE_THRESHOLD) { - skipProbability *= SKIP_DEEP_CORNER_PROBABILITY; + skipProbability *= (M_PI_F - currentAngle) / M_PI_F * ProximityInfoParams::ANGLE_WEIGHT + + (1.0f - ProximityInfoParams::ANGLE_WEIGHT); + if (currentAngle > ProximityInfoParams::DEEP_CORNER_ANGLE_THRESHOLD) { + skipProbability *= ProximityInfoParams::SKIP_DEEP_CORNER_PROBABILITY; } // We assume the angle of this point is the angle for point[i], point[i - 2] // and point[i - 3]. The reason why we don't use the angle for point[i], point[i - 1] // and point[i - 2] is this angle can be more affected by the noise. const float prevAngle = getPointsAngle(sampledInputXs, sampledInputYs, i, i - 2, i - 3); - if (i >= 3 && prevAngle < STRAIGHT_ANGLE_THRESHOLD - && currentAngle > CORNER_ANGLE_THRESHOLD) { - skipProbability *= SKIP_CORNER_PROBABILITY; + if (i >= 3 && prevAngle < ProximityInfoParams::STRAIGHT_ANGLE_THRESHOLD + && currentAngle > ProximityInfoParams::CORNER_ANGLE_THRESHOLD) { + skipProbability *= ProximityInfoParams::SKIP_CORNER_PROBABILITY; } } - // probabilities must be in [0.0, MAX_SKIP_PROBABILITY]; + // probabilities must be in [0.0, ProximityInfoParams::MAX_SKIP_PROBABILITY]; ASSERT(skipProbability >= 0.0f); - ASSERT(skipProbability <= MAX_SKIP_PROBABILITY); + ASSERT(skipProbability <= ProximityInfoParams::MAX_SKIP_PROBABILITY); (*charProbabilities)[i][NOT_AN_INDEX] = skipProbability; // Second, calculates key probabilities by dividing the rest probability // (1.0f - skipProbability). const float inputCharProbability = 1.0f - skipProbability; - // TODO: The variance is critical for accuracy; thus, adjusting these parameter by machine - // learning or something would be efficient. - static const float SPEEDxANGLE_WEIGHT_FOR_STANDARD_DIVIATION = 0.3f; - static const float MAX_SPEEDxANGLE_RATE_FOR_STANDERD_DIVIATION = 0.25f; - static const float SPEEDxNEAREST_WEIGHT_FOR_STANDARD_DIVIATION = 0.5f; - static const float MAX_SPEEDxNEAREST_RATE_FOR_STANDERD_DIVIATION = 0.15f; - static const float MIN_STANDERD_DIVIATION = 0.37f; - const float speedxAngleRate = min(speedRate * currentAngle / M_PI_F - * SPEEDxANGLE_WEIGHT_FOR_STANDARD_DIVIATION, - MAX_SPEEDxANGLE_RATE_FOR_STANDERD_DIVIATION); + * ProximityInfoParams::SPEEDxANGLE_WEIGHT_FOR_STANDARD_DIVIATION, + ProximityInfoParams::MAX_SPEEDxANGLE_RATE_FOR_STANDERD_DIVIATION); const float speedxNearestKeyDistanceRate = min(speedRate * nearestKeyDistance - * SPEEDxNEAREST_WEIGHT_FOR_STANDARD_DIVIATION, - MAX_SPEEDxNEAREST_RATE_FOR_STANDERD_DIVIATION); - const float sigma = speedxAngleRate + speedxNearestKeyDistanceRate + MIN_STANDERD_DIVIATION; + * ProximityInfoParams::SPEEDxNEAREST_WEIGHT_FOR_STANDARD_DIVIATION, + ProximityInfoParams::MAX_SPEEDxNEAREST_RATE_FOR_STANDERD_DIVIATION); + const float sigma = speedxAngleRate + speedxNearestKeyDistanceRate + + ProximityInfoParams::MIN_STANDERD_DIVIATION; ProximityInfoUtils::NormalDistribution - distribution(CENTER_VALUE_OF_NORMALIZED_DISTRIBUTION, sigma); - static const float PREV_DISTANCE_WEIGHT = 0.5f; - static const float NEXT_DISTANCE_WEIGHT = 0.6f; + distribution(ProximityInfoParams::CENTER_VALUE_OF_NORMALIZED_DISTRIBUTION, sigma); // Summing up probability densities of all near keys. float sumOfProbabilityDensities = 0.0f; for (int j = 0; j < keyCount; ++j) { @@ -797,8 +774,9 @@ namespace latinime { // points because the first touch by the user can be sloppy. // So we promote the first point if the distance of that point is larger // than the distance of the next point. - distance = (distance + nextDistance * NEXT_DISTANCE_WEIGHT) - / (1.0f + NEXT_DISTANCE_WEIGHT); + distance = (distance + + nextDistance * ProximityInfoParams::NEXT_DISTANCE_WEIGHT) + / (1.0f + ProximityInfoParams::NEXT_DISTANCE_WEIGHT); } } else if (i != 0 && i == sampledInputSize - 1) { // For the first point, weighted average of distances from last point and @@ -810,8 +788,9 @@ namespace latinime { // because the last touch by the user can be sloppy. So we promote the // last point if the distance of that point is larger than the distance of // the previous point. - distance = (distance + previousDistance * PREV_DISTANCE_WEIGHT) - / (1.0f + PREV_DISTANCE_WEIGHT); + distance = (distance + + previousDistance * ProximityInfoParams::PREV_DISTANCE_WEIGHT) + / (1.0f + ProximityInfoParams::PREV_DISTANCE_WEIGHT); } } // TODO: Promote the first point when the extended line from the next input is near @@ -831,8 +810,9 @@ namespace latinime { const float prevDistance = sqrtf(getPointToKeyByIdLength( maxPointToKeyLength, SampledDistanceCache_G, keyCount, i + 1, j)); if (prevDistance < distance) { - distance = (distance + prevDistance * NEXT_DISTANCE_WEIGHT) - / (1.0f + NEXT_DISTANCE_WEIGHT); + distance = (distance + + prevDistance * ProximityInfoParams::NEXT_DISTANCE_WEIGHT) + / (1.0f + ProximityInfoParams::NEXT_DISTANCE_WEIGHT); } } else if (i != 0 && i == sampledInputSize - 1) { // For the first point, weighted average of distances from last point and @@ -840,8 +820,9 @@ namespace latinime { const float prevDistance = sqrtf(getPointToKeyByIdLength( maxPointToKeyLength, SampledDistanceCache_G, keyCount, i - 1, j)); if (prevDistance < distance) { - distance = (distance + prevDistance * PREV_DISTANCE_WEIGHT) - / (1.0f + PREV_DISTANCE_WEIGHT); + distance = (distance + + prevDistance * ProximityInfoParams::PREV_DISTANCE_WEIGHT) + / (1.0f + ProximityInfoParams::PREV_DISTANCE_WEIGHT); } } const float probabilityDensity = distribution.getProbabilityDensity(distance); @@ -905,7 +886,7 @@ namespace latinime { hash_map_compat::iterator it = (*charProbabilities)[i].find(j); if (it == (*charProbabilities)[i].end()){ (*SampledNearKeysVector)[i].reset(j); - } else if(it->second < MIN_PROBABILITY) { + } else if(it->second < ProximityInfoParams::MIN_PROBABILITY) { // Erases from near keys vector because it has very low probability. (*SampledNearKeysVector)[i].reset(j); (*charProbabilities)[i].erase(j); @@ -949,20 +930,14 @@ namespace latinime { std::vector > *charProbabilities) { ASSERT(0 <= index0 && index0 < sampledInputSize); ASSERT(0 <= index1 && index1 < sampledInputSize); - - static const float SUPPRESSION_LENGTH_WEIGHT = 1.5f; - static const float MIN_SUPPRESSION_RATE = 0.1f; - static const float SUPPRESSION_WEIGHT = 0.5f; - static const float SUPPRESSION_WEIGHT_FOR_PROBABILITY_GAIN = 0.1f; - static const float SKIP_PROBABALITY_WEIGHT_FOR_PROBABILITY_GAIN = 0.3f; - const float keyWidthFloat = static_cast(mostCommonKeyWidth); const float diff = fabsf(static_cast((*lengthCache)[index0] - (*lengthCache)[index1])); - if (diff > keyWidthFloat * SUPPRESSION_LENGTH_WEIGHT) { + if (diff > keyWidthFloat * ProximityInfoParams::SUPPRESSION_LENGTH_WEIGHT) { return false; } - const float suppressionRate = MIN_SUPPRESSION_RATE - + diff / keyWidthFloat / SUPPRESSION_LENGTH_WEIGHT * SUPPRESSION_WEIGHT; + const float suppressionRate = ProximityInfoParams::MIN_SUPPRESSION_RATE + + diff / keyWidthFloat / ProximityInfoParams::SUPPRESSION_LENGTH_WEIGHT + * ProximityInfoParams::SUPPRESSION_WEIGHT; for (hash_map_compat::iterator it = (*charProbabilities)[index0].begin(); it != (*charProbabilities)[index0].end(); ++it) { hash_map_compat::iterator it2 = (*charProbabilities)[index1].find(it->first); @@ -974,9 +949,10 @@ namespace latinime { (*charProbabilities)[index0][NOT_AN_INDEX] += suppression; // Add the probability of the same key nearby index1 - const float probabilityGain = min(suppression * SUPPRESSION_WEIGHT_FOR_PROBABILITY_GAIN, + const float probabilityGain = min(suppression + * ProximityInfoParams::SUPPRESSION_WEIGHT_FOR_PROBABILITY_GAIN, (*charProbabilities)[index1][NOT_AN_INDEX] - * SKIP_PROBABALITY_WEIGHT_FOR_PROBABILITY_GAIN); + * ProximityInfoParams::SKIP_PROBABALITY_WEIGHT_FOR_PROBABILITY_GAIN); it2->second += probabilityGain; (*charProbabilities)[index1][NOT_AN_INDEX] -= probabilityGain; } @@ -1020,7 +996,6 @@ namespace latinime { int *const codePointBuf) { ASSERT(sampledInputSize >= 0); memset(codePointBuf, 0, sizeof(codePointBuf[0]) * MAX_WORD_LENGTH); - static const float DEMOTION_LOG_PROBABILITY = 0.3f; int index = 0; float sumLogProbability = 0.0f; // TODO: Current implementation is greedy algorithm. DP would be efficient for many cases. @@ -1030,7 +1005,7 @@ namespace latinime { for (hash_map_compat::const_iterator it = (*charProbabilities)[i].begin(); it != (*charProbabilities)[i].end(); ++it) { const float logProbability = (it->first != NOT_AN_INDEX) - ? it->second + DEMOTION_LOG_PROBABILITY : it->second; + ? it->second + ProximityInfoParams::DEMOTION_LOG_PROBABILITY : it->second; if (logProbability < minLogProbability) { minLogProbability = logProbability; character = it->first; diff --git a/native/jni/src/proximity_info_state_utils.h b/native/jni/src/proximity_info_state_utils.h index c8f0aeb75..af0acc788 100644 --- a/native/jni/src/proximity_info_state_utils.h +++ b/native/jni/src/proximity_info_state_utils.h @@ -35,9 +35,8 @@ class ProximityInfoStateUtils { static int trimLastTwoTouchPoints(std::vector *sampledInputXs, std::vector *sampledInputYs, std::vector *sampledInputTimes, std::vector *sampledLengthCache, std::vector *sampledInputIndice); - static int updateTouchPoints(const int mostCommonKeyWidth, - const ProximityInfo *const proximityInfo, const int maxPointToKeyLength, - const int *const inputProximities, + static int updateTouchPoints(const ProximityInfo *const proximityInfo, + const int maxPointToKeyLength, const int *const inputProximities, const int *const inputXCoordinates, const int *const inputYCoordinates, const int *const times, const int *const pointerIds, const int inputSize, const bool isGeometric, const int pointerId, const int pushTouchPointStartIndex, @@ -65,19 +64,17 @@ class ProximityInfoStateUtils { std::vector *beelineSpeedPercentiles); static float getDirection(const std::vector *const sampledInputXs, const std::vector *const sampledInputYs, const int index0, const int index1); - static void updateAlignPointProbabilities( - const float maxPointToKeyLength, const int mostCommonKeyWidth, const int keyCount, - const int start, const int sampledInputSize, - const std::vector *const sampledInputXs, + static void updateAlignPointProbabilities(const float maxPointToKeyLength, + const int mostCommonKeyWidth, const int keyCount, const int start, + const int sampledInputSize, const std::vector *const sampledInputXs, const std::vector *const sampledInputYs, const std::vector *const sampledSpeedRates, const std::vector *const sampledLengthCache, const std::vector *const SampledDistanceCache_G, std::vector *SampledNearKeysVector, std::vector > *charProbabilities); - static void updateSampledSearchKeysVector( - const ProximityInfo *const proximityInfo, const int sampledInputSize, - const int lastSavedInputSize, + static void updateSampledSearchKeysVector(const ProximityInfo *const proximityInfo, + const int sampledInputSize, const int lastSavedInputSize, const std::vector *const sampledLengthCache, const std::vector *const SampledNearKeysVector, std::vector *sampledSearchKeysVector); @@ -87,22 +84,18 @@ class ProximityInfoStateUtils { static float getPointToKeyByIdLength(const float maxPointToKeyLength, const std::vector *const SampledDistanceCache_G, const int keyCount, const int inputIndex, const int keyId); - static void initGeometricDistanceInfos( - const ProximityInfo *const proximityInfo, const int keyCount, + static void initGeometricDistanceInfos(const ProximityInfo *const proximityInfo, const int sampledInputSize, const int lastSavedInputSize, const std::vector *const sampledInputXs, const std::vector *const sampledInputYs, std::vector *SampledNearKeysVector, std::vector *SampledDistanceCache_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 std::vector *const sampledInputXs, - const std::vector *const sampledInputYs, - int *normalizedSquaredDistances); + 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 std::vector *const sampledInputXs, + const std::vector *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 *const sampledInputXs, @@ -117,8 +110,8 @@ class ProximityInfoStateUtils { const std::vector *const sampledTimes, const std::vector *const sampledInputIndices); // TODO: Move to most_probable_string_utils.h - static float getMostProbableString( - const ProximityInfo *const proximityInfo, const int sampledInputSize, + static float getMostProbableString(const ProximityInfo *const proximityInfo, + const int sampledInputSize, const std::vector > *const charProbabilities, int *const codePointBuf); @@ -137,11 +130,10 @@ class ProximityInfoStateUtils { const NearKeysDistanceMap *const prevNearKeysDistances, const NearKeysDistanceMap *const prevPrevNearKeysDistances, std::vector *sampledInputXs, std::vector *sampledInputYs); - static bool pushTouchPoint(const int mostCommonKeyWidth, - const ProximityInfo *const proximityInfo, const int maxPointToKeyLength, - const int inputIndex, const int nodeCodePoint, int x, int y, const int time, - const bool doSampling, const bool isLastPoint, const float sumAngle, - NearKeysDistanceMap *const currentNearKeysDistances, + static bool pushTouchPoint(const ProximityInfo *const proximityInfo, + const int maxPointToKeyLength, const int inputIndex, const int nodeCodePoint, int x, + int y, const int time, const bool doSampling, const bool isLastPoint, + const float sumAngle, NearKeysDistanceMap *const currentNearKeysDistances, const NearKeysDistanceMap *const prevNearKeysDistances, const NearKeysDistanceMap *const prevPrevNearKeysDistances, std::vector *sampledInputXs, std::vector *sampledInputYs, @@ -153,23 +145,20 @@ class ProximityInfoStateUtils { const std::vector *const sampledInputXs, const std::vector *const sampledInputYs, const std::vector *const inputIndice); - static float getPointAngle( - const std::vector *const sampledInputXs, + static float getPointAngle(const std::vector *const sampledInputXs, const std::vector *const sampledInputYs, const int index); - static float getPointsAngle( - const std::vector *const sampledInputXs, - const std::vector *const sampledInputYs, - const int index0, const int index1, const int index2); + static float getPointsAngle(const std::vector *const sampledInputXs, + const std::vector *const sampledInputYs, const int index0, const int index1, + const int index2); static bool suppressCharProbabilities(const int mostCommonKeyWidth, - const int sampledInputSize, const std::vector *const lengthCache, - const int index0, const int index1, - std::vector > *charProbabilities); + const int sampledInputSize, const std::vector *const lengthCache, const int index0, + const int index1, std::vector > *charProbabilities); static float calculateSquaredDistanceFromSweetSpotCenter( const ProximityInfo *const proximityInfo, const std::vector *const sampledInputXs, const std::vector *const sampledInputYs, const int keyIndex, const int inputIndex); - static float calculateNormalizedSquaredDistance( - const ProximityInfo *const proximityInfo, const std::vector *const sampledInputXs, + static float calculateNormalizedSquaredDistance(const ProximityInfo *const proximityInfo, + const std::vector *const sampledInputXs, const std::vector *const sampledInputYs, const int keyIndex, const int inputIndex); }; } // namespace latinime