1 /* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef LATINIME_DIC_TRAVERSE_SESSION_H 18 #define LATINIME_DIC_TRAVERSE_SESSION_H 19 20 #include <vector> 21 22 #include "defines.h" 23 #include "jni.h" 24 #include "suggest/core/dicnode/dic_nodes_cache.h" 25 #include "suggest/core/dictionary/multi_bigram_map.h" 26 #include "suggest/core/layout/proximity_info_state.h" 27 28 namespace latinime { 29 30 class Dictionary; 31 class DictionaryStructureWithBufferPolicy; 32 class PrevWordsInfo; 33 class ProximityInfo; 34 class SuggestOptions; 35 36 class DicTraverseSession { 37 public: 38 39 // A factory method for DicTraverseSession 40 static AK_FORCE_INLINE void *getSessionInstance(JNIEnv *env, jstring localeStr, 41 jlong dictSize) { 42 // To deal with the trade-off between accuracy and memory space, large cache is used for 43 // dictionaries larger that the threshold 44 return new DicTraverseSession(env, localeStr, 45 dictSize >= DICTIONARY_SIZE_THRESHOLD_TO_USE_LARGE_CACHE_FOR_SUGGESTION); 46 } 47 48 static AK_FORCE_INLINE void releaseSessionInstance(DicTraverseSession *traverseSession) { 49 delete traverseSession; 50 } 51 52 AK_FORCE_INLINE DicTraverseSession(JNIEnv *env, jstring localeStr, bool usesLargeCache) 53 : mProximityInfo(nullptr), mDictionary(nullptr), mSuggestOptions(nullptr), 54 mDicNodesCache(usesLargeCache), mMultiBigramMap(), mInputSize(0), mMaxPointerCount(1), 55 mMultiWordCostMultiplier(1.0f) { 56 // NOTE: mProximityInfoStates is an array of instances. 57 // No need to initialize it explicitly here. 58 for (size_t i = 0; i < NELEMS(mPrevWordsPtNodePos); ++i) { 59 mPrevWordsPtNodePos[i] = NOT_A_DICT_POS; 60 } 61 } 62 63 // Non virtual inline destructor -- never inherit this class 64 AK_FORCE_INLINE ~DicTraverseSession() {} 65 66 void init(const Dictionary *dictionary, const PrevWordsInfo *const prevWordsInfo, 67 const SuggestOptions *const suggestOptions); 68 // TODO: Remove and merge into init 69 void setupForGetSuggestions(const ProximityInfo *pInfo, const int *inputCodePoints, 70 const int inputSize, const int *const inputXs, const int *const inputYs, 71 const int *const times, const int *const pointerIds, const float maxSpatialDistance, 72 const int maxPointerCount); 73 void resetCache(const int thresholdForNextActiveDicNodes, const int maxWords); 74 75 const DictionaryStructureWithBufferPolicy *getDictionaryStructurePolicy() const; 76 77 //-------------------- 78 // getters and setters 79 //-------------------- 80 const ProximityInfo *getProximityInfo() const { return mProximityInfo; } 81 const SuggestOptions *getSuggestOptions() const { return mSuggestOptions; } 82 const int *getPrevWordsPtNodePos() const { return mPrevWordsPtNodePos; } 83 DicNodesCache *getDicTraverseCache() { return &mDicNodesCache; } 84 MultiBigramMap *getMultiBigramMap() { return &mMultiBigramMap; } 85 const ProximityInfoState *getProximityInfoState(int id) const { 86 return &mProximityInfoStates[id]; 87 } 88 int getInputSize() const { return mInputSize; } 89 90 bool isOnlyOnePointerUsed(int *pointerId) const { 91 // Not in the dictionary word 92 int usedPointerCount = 0; 93 int usedPointerId = 0; 94 for (int i = 0; i < mMaxPointerCount; ++i) { 95 if (mProximityInfoStates[i].isUsed()) { 96 ++usedPointerCount; 97 usedPointerId = i; 98 } 99 } 100 if (usedPointerCount != 1) { 101 return false; 102 } 103 if (pointerId) { 104 *pointerId = usedPointerId; 105 } 106 return true; 107 } 108 109 ProximityType getProximityTypeG(const DicNode *const dicNode, const int childCodePoint) const { 110 ProximityType proximityType = UNRELATED_CHAR; 111 for (int i = 0; i < MAX_POINTER_COUNT_G; ++i) { 112 if (!mProximityInfoStates[i].isUsed()) { 113 continue; 114 } 115 const int pointerId = dicNode->getInputIndex(i); 116 proximityType = mProximityInfoStates[i].getProximityTypeG(pointerId, childCodePoint); 117 ASSERT(proximityType == UNRELATED_CHAR || proximityType == MATCH_CHAR); 118 // TODO: Make this more generic 119 // Currently we assume there are only two types here -- UNRELATED_CHAR 120 // and MATCH_CHAR 121 if (proximityType != UNRELATED_CHAR) { 122 return proximityType; 123 } 124 } 125 return proximityType; 126 } 127 128 AK_FORCE_INLINE bool isCacheBorderForTyping(const int inputSize) const { 129 return mDicNodesCache.isCacheBorderForTyping(inputSize); 130 } 131 132 /** 133 * Returns whether or not it is possible to continue suggestion from the previous search. 134 */ 135 // TODO: Remove. No need to check once the session is fully implemented. 136 bool isContinuousSuggestionPossible() const { 137 if (!mDicNodesCache.hasCachedDicNodesForContinuousSuggestion()) { 138 return false; 139 } 140 ASSERT(mMaxPointerCount <= MAX_POINTER_COUNT_G); 141 for (int i = 0; i < mMaxPointerCount; ++i) { 142 const ProximityInfoState *const pInfoState = getProximityInfoState(i); 143 // If a proximity info state is not continuous suggestion possible, 144 // do not continue searching. 145 if (pInfoState->isUsed() && !pInfoState->isContinuousSuggestionPossible()) { 146 return false; 147 } 148 } 149 return true; 150 } 151 152 bool isTouchPositionCorrectionEnabled() const { 153 return mProximityInfoStates[0].touchPositionCorrectionEnabled(); 154 } 155 156 float getMultiWordCostMultiplier() const { 157 return mMultiWordCostMultiplier; 158 } 159 160 private: 161 DISALLOW_IMPLICIT_CONSTRUCTORS(DicTraverseSession); 162 // threshold to start caching 163 static const int CACHE_START_INPUT_LENGTH_THRESHOLD; 164 static const int DICTIONARY_SIZE_THRESHOLD_TO_USE_LARGE_CACHE_FOR_SUGGESTION; 165 void initializeProximityInfoStates(const int *const inputCodePoints, const int *const inputXs, 166 const int *const inputYs, const int *const times, const int *const pointerIds, 167 const int inputSize, const float maxSpatialDistance, const int maxPointerCount); 168 169 int mPrevWordsPtNodePos[MAX_PREV_WORD_COUNT_FOR_N_GRAM]; 170 const ProximityInfo *mProximityInfo; 171 const Dictionary *mDictionary; 172 const SuggestOptions *mSuggestOptions; 173 174 DicNodesCache mDicNodesCache; 175 // Temporary cache for bigram frequencies 176 MultiBigramMap mMultiBigramMap; 177 ProximityInfoState mProximityInfoStates[MAX_POINTER_COUNT_G]; 178 179 int mInputSize; 180 int mMaxPointerCount; 181 182 ///////////////////////////////// 183 // Configuration per dictionary 184 float mMultiWordCostMultiplier; 185 186 }; 187 } // namespace latinime 188 #endif // LATINIME_DIC_TRAVERSE_SESSION_H 189