Use JNI Region calls also in getSuggestions()

Change-Id: I9cc0208397c202aeb6f7b5bb5ad59e00c5afbd80
This commit is contained in:
Ken Wakasa 2012-08-10 17:16:39 +09:00
parent f6c2200890
commit f3850e5543
3 changed files with 73 additions and 52 deletions

View file

@ -51,7 +51,8 @@ public class BinaryDictionary extends Dictionary {
private static final int TYPED_LETTER_MULTIPLIER = 2; private static final int TYPED_LETTER_MULTIPLIER = 2;
private long mNativeDict; private long mNativeDict;
private final int[] mInputCodes = new int[MAX_WORD_LENGTH]; private final int[] mInputCodePoints = new int[MAX_WORD_LENGTH];
// TODO: The below should be int[] mOutputCodePoints
private final char[] mOutputChars = new char[MAX_WORD_LENGTH * MAX_RESULTS]; private final char[] mOutputChars = new char[MAX_WORD_LENGTH * MAX_RESULTS];
private final int[] mSpaceIndices = new int[MAX_SPACES]; private final int[] mSpaceIndices = new int[MAX_SPACES];
private final int[] mOutputScores = new int[MAX_RESULTS]; private final int[] mOutputScores = new int[MAX_RESULTS];
@ -92,7 +93,7 @@ public class BinaryDictionary extends Dictionary {
private native boolean isValidBigramNative(long dict, int[] word1, int[] word2); private native boolean isValidBigramNative(long dict, int[] word1, int[] word2);
private native int getSuggestionsNative(long dict, long proximityInfo, long traverseSession, private native int getSuggestionsNative(long dict, long proximityInfo, long traverseSession,
int[] xCoordinates, int[] yCoordinates, int[] times, int[] pointerIds, int[] xCoordinates, int[] yCoordinates, int[] times, int[] pointerIds,
int[] inputCodes, int codesSize, int commitPoint, boolean isGesture, int[] inputCodePoints, int codesSize, int commitPoint, boolean isGesture,
int[] prevWordCodePointArray, boolean useFullEditDistance, char[] outputChars, int[] prevWordCodePointArray, boolean useFullEditDistance, char[] outputChars,
int[] outputScores, int[] outputIndices, int[] outputTypes); int[] outputScores, int[] outputIndices, int[] outputTypes);
private static native float calcNormalizedScoreNative(char[] before, char[] after, int score); private static native float calcNormalizedScoreNative(char[] before, char[] after, int score);
@ -108,9 +109,7 @@ public class BinaryDictionary extends Dictionary {
public ArrayList<SuggestedWordInfo> getSuggestions(final WordComposer composer, public ArrayList<SuggestedWordInfo> getSuggestions(final WordComposer composer,
final CharSequence prevWord, final ProximityInfo proximityInfo) { final CharSequence prevWord, final ProximityInfo proximityInfo) {
if (!isValidDictionary()) return null; if (!isValidDictionary()) return null;
Arrays.fill(mInputCodes, WordComposer.NOT_A_CODE); Arrays.fill(mInputCodePoints, WordComposer.NOT_A_CODE);
Arrays.fill(mOutputChars, (char) 0);
Arrays.fill(mOutputScores, 0);
// TODO: toLowerCase in the native code // TODO: toLowerCase in the native code
final int[] prevWordCodePointArray = (null == prevWord) final int[] prevWordCodePointArray = (null == prevWord)
? null : StringUtils.toCodePointArray(prevWord.toString()); ? null : StringUtils.toCodePointArray(prevWord.toString());
@ -120,7 +119,7 @@ public class BinaryDictionary extends Dictionary {
if (composerSize <= 1 || !isGesture) { if (composerSize <= 1 || !isGesture) {
if (composerSize > MAX_WORD_LENGTH - 1) return null; if (composerSize > MAX_WORD_LENGTH - 1) return null;
for (int i = 0; i < composerSize; i++) { for (int i = 0; i < composerSize; i++) {
mInputCodes[i] = composer.getCodeAt(i); mInputCodePoints[i] = composer.getCodeAt(i);
} }
} }
@ -128,10 +127,9 @@ public class BinaryDictionary extends Dictionary {
final int codesSize = isGesture ? ips.getPointerSize() : composerSize; final int codesSize = isGesture ? ips.getPointerSize() : composerSize;
// proximityInfo and/or prevWordForBigrams may not be null. // proximityInfo and/or prevWordForBigrams may not be null.
final int tmpCount = getSuggestionsNative(mNativeDict, final int tmpCount = getSuggestionsNative(mNativeDict,
proximityInfo.getNativeProximityInfo(), proximityInfo.getNativeProximityInfo(), mDicTraverseSession.getSession(),
mDicTraverseSession.getSession(), ips.getXCoordinates(), ips.getXCoordinates(), ips.getYCoordinates(), ips.getTimes(), ips.getPointerIds(),
ips.getYCoordinates(), ips.getTimes(), ips.getPointerIds(), mInputCodePoints, codesSize, 0 /* commitPoint */, isGesture, prevWordCodePointArray,
mInputCodes, codesSize, 0 /* commitPoint */, isGesture, prevWordCodePointArray,
mUseFullEditDistance, mOutputChars, mOutputScores, mSpaceIndices, mOutputTypes); mUseFullEditDistance, mOutputChars, mOutputScores, mSpaceIndices, mOutputTypes);
final int count = Math.min(tmpCount, MAX_PREDICTIONS); final int count = Math.min(tmpCount, MAX_PREDICTIONS);

View file

@ -14,15 +14,12 @@
* limitations under the License. * limitations under the License.
*/ */
#include <cstring> // for memset()
#define LOG_TAG "LatinIME: jni: BinaryDictionary" #define LOG_TAG "LatinIME: jni: BinaryDictionary"
#include "binary_format.h" #include "defines.h" // for macros below
#include "com_android_inputmethod_latin_BinaryDictionary.h"
#include "correction.h"
#include "defines.h"
#include "dictionary.h"
#include "jni.h"
#include "jni_common.h"
#ifdef USE_MMAP_FOR_DICTIONARY #ifdef USE_MMAP_FOR_DICTIONARY
#include <cerrno> #include <cerrno>
@ -32,6 +29,13 @@
#include <cstdlib> #include <cstdlib>
#endif // USE_MMAP_FOR_DICTIONARY #endif // USE_MMAP_FOR_DICTIONARY
#include "binary_format.h"
#include "com_android_inputmethod_latin_BinaryDictionary.h"
#include "correction.h"
#include "dictionary.h"
#include "jni.h"
#include "jni_common.h"
namespace latinime { namespace latinime {
class ProximityInfo; class ProximityInfo;
@ -124,50 +128,71 @@ static jlong latinime_BinaryDictionary_open(JNIEnv *env, jobject object,
static int latinime_BinaryDictionary_getSuggestions(JNIEnv *env, jobject object, jlong dict, static int latinime_BinaryDictionary_getSuggestions(JNIEnv *env, jobject object, jlong dict,
jlong proximityInfo, jlong dicTraverseSession, jintArray xCoordinatesArray, jlong proximityInfo, jlong dicTraverseSession, jintArray xCoordinatesArray,
jintArray yCoordinatesArray, jintArray timesArray, jintArray pointerIdArray, jintArray yCoordinatesArray, jintArray timesArray, jintArray pointerIdsArray,
jintArray inputArray, jint arraySize, jint commitPoint, jboolean isGesture, jintArray inputCodePointsArray, jint arraySize, jint commitPoint, jboolean isGesture,
jintArray prevWordForBigrams, jboolean useFullEditDistance, jcharArray outputArray, jintArray prevWordCodePointsForBigrams, jboolean useFullEditDistance,
jintArray frequencyArray, jintArray spaceIndexArray, jintArray outputTypesArray) { jcharArray outputCharsArray, jintArray scoresArray, jintArray spaceIndicesArray,
jintArray outputTypesArray) {
Dictionary *dictionary = reinterpret_cast<Dictionary*>(dict); Dictionary *dictionary = reinterpret_cast<Dictionary*>(dict);
if (!dictionary) return 0; if (!dictionary) return 0;
ProximityInfo *pInfo = reinterpret_cast<ProximityInfo*>(proximityInfo); ProximityInfo *pInfo = reinterpret_cast<ProximityInfo*>(proximityInfo);
void *traverseSession = reinterpret_cast<void*>(dicTraverseSession); void *traverseSession = reinterpret_cast<void*>(dicTraverseSession);
int *xCoordinates = env->GetIntArrayElements(xCoordinatesArray, 0);
int *yCoordinates = env->GetIntArrayElements(yCoordinatesArray, 0); // Input values
int *times = env->GetIntArrayElements(timesArray, 0); int xCoordinates[arraySize];
int *pointerIds = env->GetIntArrayElements(pointerIdArray, 0); int yCoordinates[arraySize];
int *frequencies = env->GetIntArrayElements(frequencyArray, 0); int times[arraySize];
int *inputCodes = env->GetIntArrayElements(inputArray, 0); int pointerIds[arraySize];
jchar *outputChars = env->GetCharArrayElements(outputArray, 0); const jsize inputCodePointsLength = env->GetArrayLength(inputCodePointsArray);
int *spaceIndices = env->GetIntArrayElements(spaceIndexArray, 0); int inputCodePoints[inputCodePointsLength];
int *outputTypes = env->GetIntArrayElements(outputTypesArray, 0); const jsize prevWordCodePointsLength =
jint *prevWordChars = prevWordForBigrams prevWordCodePointsForBigrams ? env->GetArrayLength(prevWordCodePointsForBigrams) : 0;
? env->GetIntArrayElements(prevWordForBigrams, 0) : 0; int prevWordCodePointsInternal[prevWordCodePointsLength];
jsize prevWordLength = prevWordChars ? env->GetArrayLength(prevWordForBigrams) : 0; int *prevWordCodePoints = 0;
env->GetIntArrayRegion(xCoordinatesArray, 0, arraySize, xCoordinates);
env->GetIntArrayRegion(yCoordinatesArray, 0, arraySize, yCoordinates);
env->GetIntArrayRegion(timesArray, 0, arraySize, times);
env->GetIntArrayRegion(pointerIdsArray, 0, arraySize, pointerIds);
env->GetIntArrayRegion(inputCodePointsArray, 0, inputCodePointsLength, inputCodePoints);
if (prevWordCodePointsForBigrams) {
env->GetIntArrayRegion(prevWordCodePointsForBigrams, 0, prevWordCodePointsLength,
prevWordCodePointsInternal);
prevWordCodePoints = prevWordCodePointsInternal;
}
// Output values
// TODO: Should be "outputCodePointsLength" and "int outputCodePoints[]"
const jsize outputCharsLength = env->GetArrayLength(outputCharsArray);
unsigned short outputChars[outputCharsLength];
const jsize scoresLength = env->GetArrayLength(scoresArray);
int scores[scoresLength];
const jsize spaceIndicesLength = env->GetArrayLength(spaceIndicesArray);
int spaceIndices[spaceIndicesLength];
const jsize outputTypesLength = env->GetArrayLength(outputTypesArray);
int outputTypes[outputTypesLength];
memset(outputChars, 0, outputCharsLength);
memset(scores, 0, scoresLength);
memset(spaceIndices, 0, spaceIndicesLength);
memset(outputTypes, 0, outputTypesLength);
int count; int count;
if (isGesture || arraySize > 1) { if (isGesture || arraySize > 1) {
count = dictionary->getSuggestions(pInfo, traverseSession, xCoordinates, yCoordinates, count = dictionary->getSuggestions(pInfo, traverseSession, xCoordinates, yCoordinates,
times, pointerIds, inputCodes, arraySize, prevWordChars, prevWordLength, times, pointerIds, inputCodePoints, arraySize, prevWordCodePoints,
commitPoint, isGesture, useFullEditDistance, (unsigned short*) outputChars, prevWordCodePointsLength, commitPoint, isGesture, useFullEditDistance, outputChars,
frequencies, spaceIndices, outputTypes); scores, spaceIndices, outputTypes);
} else { } else {
count = dictionary->getBigrams(prevWordChars, prevWordLength, inputCodes, count = dictionary->getBigrams(prevWordCodePoints, prevWordCodePointsLength,
arraySize, (unsigned short*) outputChars, frequencies, outputTypes); inputCodePoints, arraySize, outputChars, scores, outputTypes);
} }
if (prevWordChars) { // Copy back the output values
env->ReleaseIntArrayElements(prevWordForBigrams, prevWordChars, JNI_ABORT); // TODO: Should be SetIntArrayRegion()
} env->SetCharArrayRegion(outputCharsArray, 0, outputCharsLength, outputChars);
env->ReleaseIntArrayElements(outputTypesArray, outputTypes, 0); env->SetIntArrayRegion(scoresArray, 0, scoresLength, scores);
env->ReleaseIntArrayElements(spaceIndexArray, spaceIndices, 0); env->SetIntArrayRegion(spaceIndicesArray, 0, spaceIndicesLength, spaceIndices);
env->ReleaseCharArrayElements(outputArray, outputChars, 0); env->SetIntArrayRegion(outputTypesArray, 0, outputTypesLength, outputTypes);
env->ReleaseIntArrayElements(inputArray, inputCodes, JNI_ABORT);
env->ReleaseIntArrayElements(frequencyArray, frequencies, 0);
env->ReleaseIntArrayElements(pointerIdArray, pointerIds, 0);
env->ReleaseIntArrayElements(timesArray, times, 0);
env->ReleaseIntArrayElements(yCoordinatesArray, yCoordinates, 0);
env->ReleaseIntArrayElements(xCoordinatesArray, xCoordinates, 0);
return count; return count;
} }

View file

@ -154,8 +154,6 @@ void Correction::checkState() {
if (mSkipPos >= 0) ++inputCount; if (mSkipPos >= 0) ++inputCount;
if (mExcessivePos >= 0) ++inputCount; if (mExcessivePos >= 0) ++inputCount;
if (mTransposedPos >= 0) ++inputCount; if (mTransposedPos >= 0) ++inputCount;
// TODO: remove this assert
assert(inputCount <= 1);
} }
} }