dic_traverse_session.h revision 2fa3693c264a4c150ac307d9bb7f6f8f18cc4ffc
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 <stdint.h>
21#include <vector>
22
23#include "defines.h"
24#include "jni.h"
25#include "suggest/core/dicnode/dic_nodes_cache.h"
26#include "suggest/core/dictionary/multi_bigram_map.h"
27#include "suggest/core/layout/proximity_info_state.h"
28
29namespace latinime {
30
31class Dictionary;
32class DictionaryStructureWithBufferPolicy;
33class ProximityInfo;
34class SuggestOptions;
35
36class 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 initSessionInstance(DicTraverseSession *traverseSession,
49            const Dictionary *const dictionary, const int *prevWord, const int prevWordLength,
50            const SuggestOptions *const suggestOptions) {
51        if (traverseSession) {
52            DicTraverseSession *tSession = static_cast<DicTraverseSession *>(traverseSession);
53            tSession->init(dictionary, prevWord, prevWordLength, suggestOptions);
54        }
55    }
56
57    static AK_FORCE_INLINE void releaseSessionInstance(DicTraverseSession *traverseSession) {
58        delete traverseSession;
59    }
60
61    AK_FORCE_INLINE DicTraverseSession(JNIEnv *env, jstring localeStr, bool usesLargeCache)
62            : mPrevWordPtNodePos(NOT_A_DICT_POS), mProximityInfo(0),
63              mDictionary(0), mSuggestOptions(0), mDicNodesCache(usesLargeCache),
64              mMultiBigramMap(), mInputSize(0), mPartiallyCommited(false), mMaxPointerCount(1),
65              mMultiWordCostMultiplier(1.0f) {
66        // NOTE: mProximityInfoStates is an array of instances.
67        // No need to initialize it explicitly here.
68    }
69
70    // Non virtual inline destructor -- never inherit this class
71    AK_FORCE_INLINE ~DicTraverseSession() {}
72
73    void init(const Dictionary *dictionary, const int *prevWord, int prevWordLength,
74            const SuggestOptions *const suggestOptions);
75    // TODO: Remove and merge into init
76    void setupForGetSuggestions(const ProximityInfo *pInfo, const int *inputCodePoints,
77            const int inputSize, const int *const inputXs, const int *const inputYs,
78            const int *const times, const int *const pointerIds, const float maxSpatialDistance,
79            const int maxPointerCount);
80    void resetCache(const int thresholdForNextActiveDicNodes, const int maxWords);
81
82    const DictionaryStructureWithBufferPolicy *getDictionaryStructurePolicy() const;
83
84    //--------------------
85    // getters and setters
86    //--------------------
87    const ProximityInfo *getProximityInfo() const { return mProximityInfo; }
88    const SuggestOptions *getSuggestOptions() const { return mSuggestOptions; }
89    int getPrevWordPtNodePos() const { return mPrevWordPtNodePos; }
90    // TODO: REMOVE
91    void setPrevWordPtNodePos(const int ptNodePos) { mPrevWordPtNodePos = ptNodePos; }
92    DicNodesCache *getDicTraverseCache() { return &mDicNodesCache; }
93    MultiBigramMap *getMultiBigramMap() { return &mMultiBigramMap; }
94    const ProximityInfoState *getProximityInfoState(int id) const {
95        return &mProximityInfoStates[id];
96    }
97    int getInputSize() const { return mInputSize; }
98    void setPartiallyCommited() { mPartiallyCommited = true; }
99    bool isPartiallyCommited() const { return mPartiallyCommited; }
100
101    bool isOnlyOnePointerUsed(int *pointerId) const {
102        // Not in the dictionary word
103        int usedPointerCount = 0;
104        int usedPointerId = 0;
105        for (int i = 0; i < mMaxPointerCount; ++i) {
106            if (mProximityInfoStates[i].isUsed()) {
107                ++usedPointerCount;
108                usedPointerId = i;
109            }
110        }
111        if (usedPointerCount != 1) {
112            return false;
113        }
114        if (pointerId) {
115            *pointerId = usedPointerId;
116        }
117        return true;
118    }
119
120    ProximityType getProximityTypeG(const DicNode *const dicNode, const int childCodePoint) const {
121        ProximityType proximityType = UNRELATED_CHAR;
122        for (int i = 0; i < MAX_POINTER_COUNT_G; ++i) {
123            if (!mProximityInfoStates[i].isUsed()) {
124                continue;
125            }
126            const int pointerId = dicNode->getInputIndex(i);
127            proximityType = mProximityInfoStates[i].getProximityTypeG(pointerId, childCodePoint);
128            ASSERT(proximityType == UNRELATED_CHAR || proximityType == MATCH_CHAR);
129            // TODO: Make this more generic
130            // Currently we assume there are only two types here -- UNRELATED_CHAR
131            // and MATCH_CHAR
132            if (proximityType != UNRELATED_CHAR) {
133                return proximityType;
134            }
135        }
136        return proximityType;
137    }
138
139    AK_FORCE_INLINE bool isCacheBorderForTyping(const int inputSize) const {
140        return mDicNodesCache.isCacheBorderForTyping(inputSize);
141    }
142
143    /**
144     * Returns whether or not it is possible to continue suggestion from the previous search.
145     */
146    // TODO: Remove. No need to check once the session is fully implemented.
147    bool isContinuousSuggestionPossible() const {
148        if (!mDicNodesCache.hasCachedDicNodesForContinuousSuggestion()) {
149            return false;
150        }
151        ASSERT(mMaxPointerCount <= MAX_POINTER_COUNT_G);
152        for (int i = 0; i < mMaxPointerCount; ++i) {
153            const ProximityInfoState *const pInfoState = getProximityInfoState(i);
154            // If a proximity info state is not continuous suggestion possible,
155            // do not continue searching.
156            if (pInfoState->isUsed() && !pInfoState->isContinuousSuggestionPossible()) {
157                return false;
158            }
159        }
160        return true;
161    }
162
163    bool isTouchPositionCorrectionEnabled() const {
164        return mProximityInfoStates[0].touchPositionCorrectionEnabled();
165    }
166
167    float getMultiWordCostMultiplier() const {
168        return mMultiWordCostMultiplier;
169    }
170
171 private:
172    DISALLOW_IMPLICIT_CONSTRUCTORS(DicTraverseSession);
173    // threshold to start caching
174    static const int CACHE_START_INPUT_LENGTH_THRESHOLD;
175    static const int DICTIONARY_SIZE_THRESHOLD_TO_USE_LARGE_CACHE_FOR_SUGGESTION;
176    void initializeProximityInfoStates(const int *const inputCodePoints, const int *const inputXs,
177            const int *const inputYs, const int *const times, const int *const pointerIds,
178            const int inputSize, const float maxSpatialDistance, const int maxPointerCount);
179
180    int mPrevWordPtNodePos;
181    const ProximityInfo *mProximityInfo;
182    const Dictionary *mDictionary;
183    const SuggestOptions *mSuggestOptions;
184
185    DicNodesCache mDicNodesCache;
186    // Temporary cache for bigram frequencies
187    MultiBigramMap mMultiBigramMap;
188    ProximityInfoState mProximityInfoStates[MAX_POINTER_COUNT_G];
189
190    int mInputSize;
191    bool mPartiallyCommited;
192    int mMaxPointerCount;
193
194    /////////////////////////////////
195    // Configuration per dictionary
196    float mMultiWordCostMultiplier;
197
198};
199} // namespace latinime
200#endif // LATINIME_DIC_TRAVERSE_SESSION_H
201