aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--java/res/values/strings.xml4
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/GestureFloatingPreviewText.java76
-rw-r--r--java/src/com/android/inputmethod/research/LogStatement.java9
-rw-r--r--java/src/com/android/inputmethod/research/LogUnit.java9
-rw-r--r--java/src/com/android/inputmethod/research/MotionEventReader.java2
-rw-r--r--java/src/com/android/inputmethod/research/Replayer.java33
-rw-r--r--java/src/com/android/inputmethod/research/ReplayerService.java65
-rw-r--r--java/src/com/android/inputmethod/research/ResearchLogger.java11
-rw-r--r--native/jni/src/dictionary.h18
-rw-r--r--native/jni/src/proximity_info.cpp9
-rw-r--r--native/jni/src/proximity_info.h1
-rw-r--r--native/jni/src/proximity_info_params.cpp75
-rw-r--r--native/jni/src/proximity_info_params.h64
-rw-r--r--native/jni/src/proximity_info_state.cpp33
-rw-r--r--native/jni/src/proximity_info_state_utils.cpp187
-rw-r--r--native/jni/src/proximity_info_state_utils.h67
16 files changed, 399 insertions, 264 deletions
diff --git a/java/res/values/strings.xml b/java/res/values/strings.xml
index 8822e8d18..bab612b28 100644
--- a/java/res/values/strings.xml
+++ b/java/res/values/strings.xml
@@ -313,6 +313,10 @@
<!-- TODO: remove translatable=false attribute once text is stable -->
<string name="research_log_uploader_name" translatable="false">Research Uploader Service</string>
+ <!-- Name for the research replaying service to be displayed to users. [CHAR LIMIT=50] -->
+ <!-- TODO: remove translatable=false attribute once text is stable -->
+ <string name="research_log_replayer_name" translatable="false">Research Replayer Service</string>
+
<!-- Preference for input language selection -->
<string name="select_language">Input languages</string>
diff --git a/java/src/com/android/inputmethod/keyboard/internal/GestureFloatingPreviewText.java b/java/src/com/android/inputmethod/keyboard/internal/GestureFloatingPreviewText.java
index 28655a930..ab810a580 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/GestureFloatingPreviewText.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/GestureFloatingPreviewText.java
@@ -28,7 +28,6 @@ import android.view.View;
import com.android.inputmethod.keyboard.PointerTracker;
import com.android.inputmethod.latin.CoordinateUtils;
import com.android.inputmethod.latin.R;
-import com.android.inputmethod.latin.ResizableIntArray;
import com.android.inputmethod.latin.SuggestedWords;
/**
@@ -44,16 +43,17 @@ import com.android.inputmethod.latin.SuggestedWords;
* @attr ref R.styleable#KeyboardView_gestureFloatingPreviewRoundRadius
*/
public class GestureFloatingPreviewText extends AbstractDrawingPreview {
- private static final class GesturePreviewTextParams {
- public final int mGesturePreviewTextSize;
- public final int mGesturePreviewTextColor;
+ protected static final class GesturePreviewTextParams {
public final int mGesturePreviewTextOffset;
public final int mGesturePreviewTextHeight;
- public final int mGesturePreviewColor;
public final float mGesturePreviewHorizontalPadding;
public final float mGesturePreviewVerticalPadding;
public final float mGesturePreviewRoundRadius;
- public final Paint mTextPaint;
+
+ private final int mGesturePreviewTextSize;
+ private final int mGesturePreviewTextColor;
+ private final int mGesturePreviewColor;
+ private final Paint mPaint = new Paint();
private static final char[] TEXT_HEIGHT_REFERENCE_CHAR = { 'M' };
@@ -73,37 +73,36 @@ public class GestureFloatingPreviewText extends AbstractDrawingPreview {
mGesturePreviewRoundRadius = mainKeyboardViewAttr.getDimension(
R.styleable.MainKeyboardView_gestureFloatingPreviewRoundRadius, 0.0f);
- final Paint textPaint = new Paint();
- textPaint.setAntiAlias(true);
- textPaint.setTextAlign(Align.CENTER);
- textPaint.setTextSize(mGesturePreviewTextSize);
- mTextPaint = textPaint;
+ final Paint textPaint = getTextPaint();
final Rect textRect = new Rect();
textPaint.getTextBounds(TEXT_HEIGHT_REFERENCE_CHAR, 0, 1, textRect);
mGesturePreviewTextHeight = textRect.height();
}
- }
- protected final GesturePreviewTextParams mParams;
- protected int mPreviewWordNum;
- protected final RectF mGesturePreviewRectangle = new RectF();
- protected int mHighlightedWordIndex;
+ public Paint getTextPaint() {
+ mPaint.setAntiAlias(true);
+ mPaint.setTextAlign(Align.CENTER);
+ mPaint.setTextSize(mGesturePreviewTextSize);
+ mPaint.setColor(mGesturePreviewTextColor);
+ return mPaint;
+ }
- private static final int PREVIEW_TEXT_ARRAY_CAPACITY = 10;
- // These variables store the positions of preview words. In multi-preview mode, the gesture
- // floating preview at most shows PREVIEW_TEXT_ARRAY_CAPACITY words.
- protected final ResizableIntArray mPreviewTextXArray = new ResizableIntArray(
- PREVIEW_TEXT_ARRAY_CAPACITY);
- protected final ResizableIntArray mPreviewTextYArray = new ResizableIntArray(
- PREVIEW_TEXT_ARRAY_CAPACITY);
+ public Paint getBackgroundPaint() {
+ mPaint.setColor(mGesturePreviewColor);
+ return mPaint;
+ }
+ }
- protected SuggestedWords mSuggestedWords = SuggestedWords.EMPTY;
- public final int[] mLastPointerCoords = CoordinateUtils.newInstance();
+ private final GesturePreviewTextParams mParams;
+ private final RectF mGesturePreviewRectangle = new RectF();
+ private int mPreviewTextX;
+ private int mPreviewTextY;
+ private SuggestedWords mSuggestedWords = SuggestedWords.EMPTY;
+ private final int[] mLastPointerCoords = CoordinateUtils.newInstance();
public GestureFloatingPreviewText(final View drawingView, final TypedArray typedArray) {
super(drawingView);
mParams = new GesturePreviewTextParams(typedArray);
- mHighlightedWordIndex = 0;
}
public void setSuggetedWords(final SuggestedWords suggestedWords) {
@@ -114,13 +113,6 @@ public class GestureFloatingPreviewText extends AbstractDrawingPreview {
updatePreviewPosition();
}
- protected void drawText(final Canvas canvas, final String text, final float textX,
- final float textY, final int color) {
- final Paint paint = mParams.mTextPaint;
- paint.setColor(color);
- canvas.drawText(text, textX, textY, paint);
- }
-
@Override
public void setPreviewPosition(final PointerTracker tracker) {
final boolean needsToUpdateLastPointer =
@@ -142,14 +134,11 @@ public class GestureFloatingPreviewText extends AbstractDrawingPreview {
|| TextUtils.isEmpty(mSuggestedWords.getWord(0))) {
return;
}
- final Paint paint = mParams.mTextPaint;
- paint.setColor(mParams.mGesturePreviewColor);
final float round = mParams.mGesturePreviewRoundRadius;
- canvas.drawRoundRect(mGesturePreviewRectangle, round, round, paint);
+ canvas.drawRoundRect(
+ mGesturePreviewRectangle, round, round, mParams.getBackgroundPaint());
final String text = mSuggestedWords.getWord(0);
- final int textX = mPreviewTextXArray.get(0);
- final int textY = mPreviewTextYArray.get(0);
- drawText(canvas, text, textX, textY, mParams.mGesturePreviewTextColor);
+ canvas.drawText(text, mPreviewTextX, mPreviewTextY, mParams.getTextPaint());
}
/**
@@ -162,11 +151,10 @@ public class GestureFloatingPreviewText extends AbstractDrawingPreview {
}
final String text = mSuggestedWords.getWord(0);
- final Paint paint = mParams.mTextPaint;
final RectF rectangle = mGesturePreviewRectangle;
final int textHeight = mParams.mGesturePreviewTextHeight;
- final float textWidth = paint.measureText(text);
+ final float textWidth = mParams.getTextPaint().measureText(text);
final float hPad = mParams.mGesturePreviewHorizontalPadding;
final float vPad = mParams.mGesturePreviewVerticalPadding;
final float rectWidth = textWidth + hPad * 2.0f;
@@ -180,10 +168,8 @@ public class GestureFloatingPreviewText extends AbstractDrawingPreview {
- mParams.mGesturePreviewTextOffset - rectHeight;
rectangle.set(rectX, rectY, rectX + rectWidth, rectY + rectHeight);
- final int textX = (int)(rectX + hPad + textWidth / 2.0f);
- final int textY = (int)(rectY + vPad) + textHeight;
- mPreviewTextXArray.add(0, textX);
- mPreviewTextYArray.add(0, textY);
+ mPreviewTextX = (int)(rectX + hPad + textWidth / 2.0f);
+ mPreviewTextY = (int)(rectY + vPad) + textHeight;
// TODO: Should narrow the invalidate region.
getDrawingView().invalidate();
}
diff --git a/java/src/com/android/inputmethod/research/LogStatement.java b/java/src/com/android/inputmethod/research/LogStatement.java
index 090c58e27..1d83e1a86 100644
--- a/java/src/com/android/inputmethod/research/LogStatement.java
+++ b/java/src/com/android/inputmethod/research/LogStatement.java
@@ -29,13 +29,12 @@ class LogStatement {
"PointerTrackerCallListenerOnCodeInput";
public static final String KEY_CODE = "code";
public static final String VALUE_RESEARCH = "research";
- public static final String TYPE_LATIN_KEYBOARD_VIEW_ON_LONG_PRESS =
- "LatinKeyboardViewOnLongPress";
+ public static final String TYPE_MAIN_KEYBOARD_VIEW_ON_LONG_PRESS =
+ "MainKeyboardViewOnLongPress";
public static final String ACTION = "action";
public static final String VALUE_DOWN = "DOWN";
- public static final String TYPE_LATIN_KEYBOARD_VIEW_PROCESS_MOTION_EVENTS =
- "LatinKeyboardViewProcessMotionEvents";
- public static final String KEY_LOGGING_RELATED = "loggingRelated";
+ public static final String TYPE_MOTION_EVENT = "MotionEvent";
+ public static final String KEY_IS_LOGGING_RELATED = "isLoggingRelated";
// Name specifying the LogStatement type.
private final String mType;
diff --git a/java/src/com/android/inputmethod/research/LogUnit.java b/java/src/com/android/inputmethod/research/LogUnit.java
index 608fab3f1..2e732fc6c 100644
--- a/java/src/com/android/inputmethod/research/LogUnit.java
+++ b/java/src/com/android/inputmethod/research/LogUnit.java
@@ -453,13 +453,12 @@ import java.util.List;
// Look for the long press that started the invocation of the research key code input.
final int indexOfLastLongPressBeforeResearchKey =
- findLastIndexBefore(LogStatement.TYPE_LATIN_KEYBOARD_VIEW_ON_LONG_PRESS,
+ findLastIndexBefore(LogStatement.TYPE_MAIN_KEYBOARD_VIEW_ON_LONG_PRESS,
indexOfLastResearchKey);
// Look for DOWN event preceding the long press
final int indexOfLastDownEventBeforeLongPress =
- findLastIndexContainingKeyValueBefore(
- LogStatement.TYPE_LATIN_KEYBOARD_VIEW_PROCESS_MOTION_EVENTS,
+ findLastIndexContainingKeyValueBefore(LogStatement.TYPE_MOTION_EVENT,
LogStatement.ACTION, LogStatement.VALUE_DOWN,
indexOfLastLongPressBeforeResearchKey);
@@ -471,8 +470,8 @@ import java.util.List;
final LogStatement logStatement = mLogStatementList.get(index);
final String type = logStatement.getType();
final Object[] values = mValuesList.get(index);
- if (type.equals(LogStatement.TYPE_LATIN_KEYBOARD_VIEW_PROCESS_MOTION_EVENTS)) {
- logStatement.setValue(LogStatement.KEY_LOGGING_RELATED, values, true);
+ if (type.equals(LogStatement.TYPE_MOTION_EVENT)) {
+ logStatement.setValue(LogStatement.KEY_IS_LOGGING_RELATED, values, true);
}
}
return true;
diff --git a/java/src/com/android/inputmethod/research/MotionEventReader.java b/java/src/com/android/inputmethod/research/MotionEventReader.java
index 36e75be1c..26a1d7f55 100644
--- a/java/src/com/android/inputmethod/research/MotionEventReader.java
+++ b/java/src/com/android/inputmethod/research/MotionEventReader.java
@@ -101,7 +101,7 @@ public class MotionEventReader {
jsonReader.endObject();
if (logStatementType != null && time != null && x != null && y != null && actionType != null
- && logStatementType.equals("MainKeyboardViewProcessMotionEvent")
+ && logStatementType.equals("MotionEvent")
&& !loggingRelated) {
replayData.mActions.add(actionType);
replayData.mXCoords.add(x);
diff --git a/java/src/com/android/inputmethod/research/Replayer.java b/java/src/com/android/inputmethod/research/Replayer.java
index 4cc2a5814..611abb288 100644
--- a/java/src/com/android/inputmethod/research/Replayer.java
+++ b/java/src/com/android/inputmethod/research/Replayer.java
@@ -1,22 +1,23 @@
/*
* Copyright (C) 2012 The Android Open Source Project
*
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
*/
package com.android.inputmethod.research;
import android.os.Handler;
+import android.os.Looper;
import android.os.Message;
import android.os.SystemClock;
import android.util.Log;
@@ -40,6 +41,14 @@ public class Replayer {
private boolean mIsReplaying = false;
private KeyboardSwitcher mKeyboardSwitcher;
+ private Replayer() {
+ }
+
+ private static final Replayer sInstance = new Replayer();
+ public static Replayer getInstance() {
+ return sInstance;
+ }
+
public void setKeyboardSwitcher(final KeyboardSwitcher keyboardSwitcher) {
mKeyboardSwitcher = keyboardSwitcher;
}
@@ -49,7 +58,7 @@ public class Replayer {
private static final int COMPLETION_TIME_MS = 500;
// TODO: Support historical events and multi-touch.
- public void replay(final ReplayData replayData) {
+ public void replay(final ReplayData replayData, final Runnable callback) {
if (mIsReplaying) {
return;
}
@@ -72,7 +81,7 @@ public class Replayer {
// The adjustment needed to translate times from the original recorded time to the current
// time.
final long timeAdjustment = currentStartTime - origStartTime;
- final Handler handler = new Handler() {
+ final Handler handler = new Handler(Looper.getMainLooper()) {
// Track the time of the most recent DOWN event, to be passed as a parameter when
// constructing a MotionEvent. It's initialized here to the origStartTime, but this is
// only a precaution. The value should be overwritten by the first ACTION_DOWN event
@@ -113,8 +122,12 @@ public class Replayer {
Log.d(TAG, "queuing event at " + msgTime);
}
}
+
final long presentDoneTime = replayData.mTimes.get(numActions - 1) + timeAdjustment
+ COMPLETION_TIME_MS;
handler.sendMessageAtTime(Message.obtain(handler, MSG_DONE), presentDoneTime);
+ if (callback != null) {
+ handler.postAtTime(callback, presentDoneTime + 1);
+ }
}
}
diff --git a/java/src/com/android/inputmethod/research/ReplayerService.java b/java/src/com/android/inputmethod/research/ReplayerService.java
new file mode 100644
index 000000000..88d9033cf
--- /dev/null
+++ b/java/src/com/android/inputmethod/research/ReplayerService.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.android.inputmethod.research;
+
+import android.app.IntentService;
+import android.content.Intent;
+import android.util.Log;
+
+import com.android.inputmethod.research.MotionEventReader.ReplayData;
+
+import java.io.File;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Provide a mechanism to invoke the replayer from outside.
+ *
+ * In particular, makes access from a host possible through {@code adb am startservice}.
+ */
+public class ReplayerService extends IntentService {
+ private static final String TAG = ReplayerService.class.getSimpleName();
+ private static final String EXTRA_FILENAME = "com.android.inputmethod.research.extra.FILENAME";
+ private static final long MAX_REPLAY_TIME = TimeUnit.SECONDS.toMillis(60);
+
+ public ReplayerService() {
+ super(ReplayerService.class.getSimpleName());
+ }
+
+ @Override
+ protected void onHandleIntent(final Intent intent) {
+ final String filename = intent.getStringExtra(EXTRA_FILENAME);
+ if (filename == null) return;
+
+ final ReplayData replayData = new MotionEventReader().readMotionEventData(
+ new File(filename));
+ synchronized (this) {
+ Replayer.getInstance().replay(replayData, new Runnable() {
+ @Override
+ public void run() {
+ synchronized (ReplayerService.this) {
+ ReplayerService.this.notify();
+ }
+ }
+ });
+ try {
+ wait(MAX_REPLAY_TIME);
+ } catch (InterruptedException e) {
+ Log.e(TAG, "Timeout while replaying.", e);
+ }
+ }
+ }
+}
diff --git a/java/src/com/android/inputmethod/research/ResearchLogger.java b/java/src/com/android/inputmethod/research/ResearchLogger.java
index 096f03202..da410010f 100644
--- a/java/src/com/android/inputmethod/research/ResearchLogger.java
+++ b/java/src/com/android/inputmethod/research/ResearchLogger.java
@@ -184,10 +184,10 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
private Suggest mSuggest;
private MainKeyboardView mMainKeyboardView;
// TODO: Check whether a superclass can be used instead of LatinIME.
- private LatinIME mLatinIME;
+ /* package for test */ LatinIME mLatinIME;
private final Statistics mStatistics;
private final MotionEventReader mMotionEventReader = new MotionEventReader();
- private final Replayer mReplayer = new Replayer();
+ private final Replayer mReplayer = Replayer.getInstance();
private Intent mUploadIntent;
private Intent mUploadNowIntent;
@@ -783,7 +783,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
public void run() {
final ReplayData replayData =
mMotionEventReader.readMotionEventData(mUserRecordingFile);
- mReplayer.replay(replayData);
+ mReplayer.replay(replayData, null);
}
}, 1000);
}
@@ -1162,7 +1162,8 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
*
*/
private static final LogStatement LOGSTATEMENT_MAIN_KEYBOARD_VIEW_PROCESS_MOTION_EVENT =
- new LogStatement("MotionEvent", true, false, "action", "MotionEvent", "loggingRelated");
+ new LogStatement("MotionEvent", true, false, "action",
+ LogStatement.KEY_IS_LOGGING_RELATED, "motionEvent");
public static void mainKeyboardView_processMotionEvent(final MotionEvent me, final int action,
final long eventTime, final int index, final int id, final int x, final int y) {
if (me != null) {
@@ -1179,7 +1180,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
}
final ResearchLogger researchLogger = getInstance();
researchLogger.enqueueEvent(LOGSTATEMENT_MAIN_KEYBOARD_VIEW_PROCESS_MOTION_EVENT,
- actionString, MotionEvent.obtain(me), false);
+ actionString, false /* IS_LOGGING_RELATED */, MotionEvent.obtain(me));
if (action == MotionEvent.ACTION_DOWN) {
// Subtract 1 from eventTime so the down event is included in the later
// LogUnit, not the earlier (the test is for inequality).
diff --git a/native/jni/src/dictionary.h b/native/jni/src/dictionary.h
index 83676b204..ecdddd771 100644
--- a/native/jni/src/dictionary.h
+++ b/native/jni/src/dictionary.h
@@ -31,15 +31,15 @@ class UnigramDictionary;
class Dictionary {
public:
// Taken from SuggestedWords.java
- const static int KIND_TYPED = 0; // What user typed
- const static int KIND_CORRECTION = 1; // Simple correction/suggestion
- const static int KIND_COMPLETION = 2; // Completion (suggestion with appended chars)
- const static int KIND_WHITELIST = 3; // Whitelisted word
- const static int KIND_BLACKLIST = 4; // Blacklisted word
- const static int KIND_HARDCODED = 5; // Hardcoded suggestion, e.g. punctuation
- const static int KIND_APP_DEFINED = 6; // Suggested by the application
- const static int KIND_SHORTCUT = 7; // A shortcut
- const static int KIND_PREDICTION = 8; // A prediction (== a suggestion with no input)
+ static const int KIND_TYPED = 0; // What user typed
+ static const int KIND_CORRECTION = 1; // Simple correction/suggestion
+ static const int KIND_COMPLETION = 2; // Completion (suggestion with appended chars)
+ static const int KIND_WHITELIST = 3; // Whitelisted word
+ static const int KIND_BLACKLIST = 4; // Blacklisted word
+ static const int KIND_HARDCODED = 5; // Hardcoded suggestion, e.g. punctuation
+ static const int KIND_APP_DEFINED = 6; // Suggested by the application
+ static const int KIND_SHORTCUT = 7; // A shortcut
+ static const int KIND_PREDICTION = 8; // A prediction (== a suggestion with no input)
Dictionary(void *dict, int dictSize, int mmapFd, int dictBufAdjust);
diff --git a/native/jni/src/proximity_info.cpp b/native/jni/src/proximity_info.cpp
index a0bad1af4..d812745ca 100644
--- a/native/jni/src/proximity_info.cpp
+++ b/native/jni/src/proximity_info.cpp
@@ -24,11 +24,10 @@
#include "geometry_utils.h"
#include "jni.h"
#include "proximity_info.h"
+#include "proximity_info_params.h"
namespace latinime {
-/* static */ const float ProximityInfo::NOT_A_DISTANCE_FLOAT = -1.0f;
-
static AK_FORCE_INLINE void safeGetOrFillZeroIntArrayRegion(JNIEnv *env, jintArray jArray,
jsize len, jint *buffer) {
if (jArray && buffer) {
@@ -129,17 +128,15 @@ bool ProximityInfo::hasSpaceProximity(const int x, const int y) const {
float ProximityInfo::getNormalizedSquaredDistanceFromCenterFloatG(
const int keyId, const int x, const int y) const {
- const static float verticalSweetSpotScaleForGeometric = 1.1f;
const bool correctTouchPosition = hasTouchPositionCorrectionData();
- const float centerX = static_cast<float>(correctTouchPosition
- ? getSweetSpotCenterXAt(keyId)
+ const float centerX = static_cast<float>(correctTouchPosition ? getSweetSpotCenterXAt(keyId)
: getKeyCenterXOfKeyIdG(keyId));
const float visualKeyCenterY = static_cast<float>(getKeyCenterYOfKeyIdG(keyId));
float centerY;
if (correctTouchPosition) {
const float sweetSpotCenterY = static_cast<float>(getSweetSpotCenterYAt(keyId));
const float gapY = sweetSpotCenterY - visualKeyCenterY;
- centerY = visualKeyCenterY + gapY * verticalSweetSpotScaleForGeometric;
+ centerY = visualKeyCenterY + gapY * ProximityInfoParams::VERTICAL_SWEET_SPOT_SCALE_G;
} else {
centerY = visualKeyCenterY;
}
diff --git a/native/jni/src/proximity_info.h b/native/jni/src/proximity_info.h
index f3a68e4f2..d42c72391 100644
--- a/native/jni/src/proximity_info.h
+++ b/native/jni/src/proximity_info.h
@@ -83,7 +83,6 @@ class ProximityInfo {
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(ProximityInfo);
- static const float NOT_A_DISTANCE_FLOAT;
void initializeG();
float calculateNormalizedSquaredDistance(const int keyIndex, const int inputIndex) const;
diff --git a/native/jni/src/proximity_info_params.cpp b/native/jni/src/proximity_info_params.cpp
index f7b3d4d71..1410ab575 100644
--- a/native/jni/src/proximity_info_params.cpp
+++ b/native/jni/src/proximity_info_params.cpp
@@ -14,22 +14,25 @@
* limitations under the License.
*/
+#include "defines.h"
#include "proximity_info_params.h"
namespace latinime {
-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;
+const int ProximityInfoParams::MIN_DOUBLE_LETTER_BEELINE_SPEED_PERCENTILE = 5;
+const float ProximityInfoParams::VERTICAL_SWEET_SPOT_SCALE_G = 1.1f;
-// 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 +42,62 @@ 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;
+
+// Used by ProximityInfoStateUtils::updateSampledSearchKeysVector()
// TODO: Investigate if this is required
const float ProximityInfoParams::SEARCH_KEY_RADIUS_RATIO = 0.95f;
+
+// Used by ProximityInfoStateUtils::calculateBeelineSpeedRate()
+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;
+
+// Used by ProximityInfoStateUtils::calculateNormalizedSquaredDistance()
+const int ProximityInfoParams::NORMALIZED_SQUARED_DISTANCE_SCALING_FACTOR = 1 << 10;
+
} // namespace latinime
diff --git a/native/jni/src/proximity_info_params.h b/native/jni/src/proximity_info_params.h
index 978b99917..7c26208a8 100644
--- a/native/jni/src/proximity_info_params.h
+++ b/native/jni/src/proximity_info_params.h
@@ -23,13 +23,9 @@ namespace latinime {
class ProximityInfoParams {
public:
- static const int LOOKUP_RADIUS_PERCENTILE;
- 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;
- static const float SEARCH_KEY_RADIUS_RATIO;
+ static const int MIN_DOUBLE_LETTER_BEELINE_SPEED_PERCENTILE;
+ static const float VERTICAL_SWEET_SPOT_SCALE_G;
// Used by ProximityInfoStateUtils::initGeometricDistanceInfos()
static const float NEAR_KEY_NORMALIZED_SQUARED_THRESHOLD;
@@ -50,9 +46,63 @@ 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;
+
+ // Used by ProximityInfoStateUtils::updateSampledSearchKeysVector()
+ static const float SEARCH_KEY_RADIUS_RATIO;
+
+ // Used by ProximityInfoStateUtils::calculateBeelineSpeedRate()
+ static const int LOOKUP_RADIUS_PERCENTILE;
+ static const int FIRST_POINT_TIME_OFFSET_MILLIS;
+ static const int STRONG_DOUBLE_LETTER_TIME_MILLIS;
+
+ // Used by ProximityInfoStateUtils::calculateNormalizedSquaredDistance()
+ static const int NORMALIZED_SQUARED_DISTANCE_SCALING_FACTOR;
+
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(ProximityInfoParams);
- static const int NORMALIZED_SQUARED_DISTANCE_SCALING_FACTOR_LOG_2;
};
} // namespace latinime
#endif // LATINIME_PROXIMITY_INFO_PARAMS_H
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<int> *const sampledInputXs,
const std::vector<int> *const sampledInputYs,
std::vector<NearKeycodesSet> *SampledNearKeysVector,
std::vector<float> *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<int> *sampledInputXs, std::vector<int> *sampledInputYs,
std::vector<int> *sampledInputTimes, std::vector<int> *sampledLengthCache,
std::vector<int> *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<float> *const SampledDistanceCache_G,
std::vector<NearKeycodesSet> *SampledNearKeysVector,
std::vector<hash_map_compat<int, float> > *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<int, float>::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<hash_map_compat<int, float> > *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<float>(mostCommonKeyWidth);
const float diff = fabsf(static_cast<float>((*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<int, float>::iterator it = (*charProbabilities)[index0].begin();
it != (*charProbabilities)[index0].end(); ++it) {
hash_map_compat<int, float>::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<int, float>::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<int> *sampledInputXs,
std::vector<int> *sampledInputYs, std::vector<int> *sampledInputTimes,
std::vector<int> *sampledLengthCache, std::vector<int> *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<int> *beelineSpeedPercentiles);
static float getDirection(const std::vector<int> *const sampledInputXs,
const std::vector<int> *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<int> *const sampledInputXs,
+ static void updateAlignPointProbabilities(const float maxPointToKeyLength,
+ const int mostCommonKeyWidth, const int keyCount, const int start,
+ 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 sampledLengthCache,
const std::vector<float> *const SampledDistanceCache_G,
std::vector<NearKeycodesSet> *SampledNearKeysVector,
std::vector<hash_map_compat<int, float> > *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<int> *const sampledLengthCache,
const std::vector<NearKeycodesSet> *const SampledNearKeysVector,
std::vector<NearKeycodesSet> *sampledSearchKeysVector);
@@ -87,22 +84,18 @@ class ProximityInfoStateUtils {
static float getPointToKeyByIdLength(const float maxPointToKeyLength,
const std::vector<float> *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<int> *const sampledInputXs,
const std::vector<int> *const sampledInputYs,
std::vector<NearKeycodesSet> *SampledNearKeysVector,
std::vector<float> *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<int> *const sampledInputXs,
- const std::vector<int> *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<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,
@@ -117,8 +110,8 @@ class ProximityInfoStateUtils {
const std::vector<int> *const sampledTimes,
const std::vector<int> *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<hash_map_compat<int, float> > *const charProbabilities,
int *const codePointBuf);
@@ -137,11 +130,10 @@ class ProximityInfoStateUtils {
const NearKeysDistanceMap *const prevNearKeysDistances,
const NearKeysDistanceMap *const prevPrevNearKeysDistances,
std::vector<int> *sampledInputXs, std::vector<int> *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<int> *sampledInputXs, std::vector<int> *sampledInputYs,
@@ -153,23 +145,20 @@ class ProximityInfoStateUtils {
const std::vector<int> *const sampledInputXs,
const std::vector<int> *const sampledInputYs,
const std::vector<int> *const inputIndice);
- static float getPointAngle(
- const std::vector<int> *const sampledInputXs,
+ static float getPointAngle(const std::vector<int> *const sampledInputXs,
const std::vector<int> *const sampledInputYs, const int index);
- static float getPointsAngle(
- const std::vector<int> *const sampledInputXs,
- const std::vector<int> *const sampledInputYs,
- const int index0, const int index1, const int index2);
+ static float getPointsAngle(const std::vector<int> *const sampledInputXs,
+ const std::vector<int> *const sampledInputYs, const int index0, const int index1,
+ const int index2);
static bool suppressCharProbabilities(const int mostCommonKeyWidth,
- const int sampledInputSize, const std::vector<int> *const lengthCache,
- const int index0, const int index1,
- std::vector<hash_map_compat<int, float> > *charProbabilities);
+ 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,
+ 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