| Index: third_party/android_prediction/suggest/core/dicnode/dic_node.h
|
| diff --git a/third_party/android_prediction/suggest/core/dicnode/dic_node.h b/third_party/android_prediction/suggest/core/dicnode/dic_node.h
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..f42de7f040541fb8320a0a60e0faef0f462a83b7
|
| --- /dev/null
|
| +++ b/third_party/android_prediction/suggest/core/dicnode/dic_node.h
|
| @@ -0,0 +1,519 @@
|
| +/*
|
| + * 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.
|
| + */
|
| +
|
| +#ifndef LATINIME_DIC_NODE_H
|
| +#define LATINIME_DIC_NODE_H
|
| +
|
| +#include "third_party/android_prediction/defines.h"
|
| +#include "third_party/android_prediction/suggest/core/dicnode/dic_node_profiler.h"
|
| +#include "third_party/android_prediction/suggest/core/dicnode/dic_node_utils.h"
|
| +#include "third_party/android_prediction/suggest/core/dicnode/internal/dic_node_state.h"
|
| +#include "third_party/android_prediction/suggest/core/dicnode/internal/dic_node_properties.h"
|
| +#include "third_party/android_prediction/suggest/core/dictionary/digraph_utils.h"
|
| +#include "third_party/android_prediction/suggest/core/dictionary/error_type_utils.h"
|
| +#include "third_party/android_prediction/suggest/core/layout/proximity_info_state.h"
|
| +#include "third_party/android_prediction/utils/char_utils.h"
|
| +
|
| +#if DEBUG_DICT
|
| +#define LOGI_SHOW_ADD_COST_PROP \
|
| + do { \
|
| + char charBuf[50]; \
|
| + INTS_TO_CHARS(getOutputWordBuf(), getNodeCodePointCount(), charBuf, NELEMS(charBuf)); \
|
| + AKLOGI("%20s, \"%c\", size = %03d, total = %03d, index(0) = %02d, dist = %.4f, %s,,", \
|
| + __FUNCTION__, getNodeCodePoint(), inputSize, getTotalInputIndex(), \
|
| + getInputIndex(0), getNormalizedCompoundDistance(), charBuf); \
|
| + } while (0)
|
| +#define DUMP_WORD_AND_SCORE(header) \
|
| + do { \
|
| + char charBuf[50]; \
|
| + INTS_TO_CHARS(getOutputWordBuf(), \
|
| + getNodeCodePointCount() \
|
| + + mDicNodeState.mDicNodeStateOutput.getPrevWordsLength(), \
|
| + charBuf, NELEMS(charBuf)); \
|
| + AKLOGI("#%8s, %5f, %5f, %5f, %5f, %s, %d, %5f,", header, \
|
| + getSpatialDistanceForScoring(), \
|
| + mDicNodeState.mDicNodeStateScoring.getLanguageDistance(), \
|
| + getNormalizedCompoundDistance(), getRawLength(), charBuf, \
|
| + getInputIndex(0), getNormalizedCompoundDistanceAfterFirstWord()); \
|
| + } while (0)
|
| +#else
|
| +#define LOGI_SHOW_ADD_COST_PROP
|
| +#define DUMP_WORD_AND_SCORE(header)
|
| +#endif
|
| +
|
| +namespace latinime {
|
| +
|
| +// This struct is purely a bucket to return values. No instances of this struct should be kept.
|
| +struct DicNode_InputStateG {
|
| + DicNode_InputStateG()
|
| + : mNeedsToUpdateInputStateG(false), mPointerId(0), mInputIndex(0),
|
| + mPrevCodePoint(0), mTerminalDiffCost(0.0f), mRawLength(0.0f),
|
| + mDoubleLetterLevel(NOT_A_DOUBLE_LETTER) {}
|
| +
|
| + bool mNeedsToUpdateInputStateG;
|
| + int mPointerId;
|
| + int16_t mInputIndex;
|
| + int mPrevCodePoint;
|
| + float mTerminalDiffCost;
|
| + float mRawLength;
|
| + DoubleLetterLevel mDoubleLetterLevel;
|
| +};
|
| +
|
| +class DicNode {
|
| + // Caveat: We define Weighting as a friend class of DicNode to let Weighting change
|
| + // the distance of DicNode.
|
| + // Caution!!! In general, we avoid using the "friend" access modifier.
|
| + // This is an exception to explicitly hide DicNode::addCost() from all classes but Weighting.
|
| + friend class Weighting;
|
| +
|
| + public:
|
| +#if DEBUG_DICT
|
| + DicNodeProfiler mProfiler;
|
| +#endif
|
| +
|
| + AK_FORCE_INLINE DicNode()
|
| + :
|
| +#if DEBUG_DICT
|
| + mProfiler(),
|
| +#endif
|
| + mDicNodeProperties(), mDicNodeState(), mIsCachedForNextSuggestion(false) {}
|
| +
|
| + DicNode(const DicNode &dicNode);
|
| + DicNode &operator=(const DicNode &dicNode);
|
| + ~DicNode() {}
|
| +
|
| + // Init for copy
|
| + void initByCopy(const DicNode *const dicNode) {
|
| + mIsCachedForNextSuggestion = dicNode->mIsCachedForNextSuggestion;
|
| + mDicNodeProperties.initByCopy(&dicNode->mDicNodeProperties);
|
| + mDicNodeState.initByCopy(&dicNode->mDicNodeState);
|
| + PROF_NODE_COPY(&dicNode->mProfiler, mProfiler);
|
| + }
|
| +
|
| + // Init for root with prevWordsPtNodePos which is used for n-gram
|
| + void initAsRoot(const int rootPtNodeArrayPos, const int *const prevWordsPtNodePos) {
|
| + mIsCachedForNextSuggestion = false;
|
| + mDicNodeProperties.init(rootPtNodeArrayPos, prevWordsPtNodePos);
|
| + mDicNodeState.init();
|
| + PROF_NODE_RESET(mProfiler);
|
| + }
|
| +
|
| + // Init for root with previous word
|
| + void initAsRootWithPreviousWord(const DicNode *const dicNode, const int rootPtNodeArrayPos) {
|
| + mIsCachedForNextSuggestion = dicNode->mIsCachedForNextSuggestion;
|
| + int newPrevWordsPtNodePos[MAX_PREV_WORD_COUNT_FOR_N_GRAM];
|
| + newPrevWordsPtNodePos[0] = dicNode->mDicNodeProperties.getPtNodePos();
|
| + for (size_t i = 1; i < NELEMS(newPrevWordsPtNodePos); ++i) {
|
| + newPrevWordsPtNodePos[i] = dicNode->getPrevWordsTerminalPtNodePos()[i - 1];
|
| + }
|
| + mDicNodeProperties.init(rootPtNodeArrayPos, newPrevWordsPtNodePos);
|
| + mDicNodeState.initAsRootWithPreviousWord(&dicNode->mDicNodeState,
|
| + dicNode->mDicNodeProperties.getDepth());
|
| + PROF_NODE_COPY(&dicNode->mProfiler, mProfiler);
|
| + }
|
| +
|
| + void initAsPassingChild(const DicNode *parentDicNode) {
|
| + mIsCachedForNextSuggestion = parentDicNode->mIsCachedForNextSuggestion;
|
| + const int codePoint =
|
| + parentDicNode->mDicNodeState.mDicNodeStateOutput.getCurrentWordCodePointAt(
|
| + parentDicNode->getNodeCodePointCount());
|
| + mDicNodeProperties.init(&parentDicNode->mDicNodeProperties, codePoint);
|
| + mDicNodeState.initByCopy(&parentDicNode->mDicNodeState);
|
| + PROF_NODE_COPY(&parentDicNode->mProfiler, mProfiler);
|
| + }
|
| +
|
| + void initAsChild(const DicNode *const dicNode, const int ptNodePos,
|
| + const int childrenPtNodeArrayPos, const int probability, const bool isTerminal,
|
| + const bool hasChildren, const bool isBlacklistedOrNotAWord,
|
| + const uint16_t mergedNodeCodePointCount, const int *const mergedNodeCodePoints) {
|
| + uint16_t newDepth = static_cast<uint16_t>(dicNode->getNodeCodePointCount() + 1);
|
| + mIsCachedForNextSuggestion = dicNode->mIsCachedForNextSuggestion;
|
| + const uint16_t newLeavingDepth = static_cast<uint16_t>(
|
| + dicNode->mDicNodeProperties.getLeavingDepth() + mergedNodeCodePointCount);
|
| + mDicNodeProperties.init(ptNodePos, childrenPtNodeArrayPos, mergedNodeCodePoints[0],
|
| + probability, isTerminal, hasChildren, isBlacklistedOrNotAWord, newDepth,
|
| + newLeavingDepth, dicNode->mDicNodeProperties.getPrevWordsTerminalPtNodePos());
|
| + mDicNodeState.init(&dicNode->mDicNodeState, mergedNodeCodePointCount,
|
| + mergedNodeCodePoints);
|
| + PROF_NODE_COPY(&dicNode->mProfiler, mProfiler);
|
| + }
|
| +
|
| + bool isRoot() const {
|
| + return getNodeCodePointCount() == 0;
|
| + }
|
| +
|
| + bool hasChildren() const {
|
| + return mDicNodeProperties.hasChildren();
|
| + }
|
| +
|
| + bool isLeavingNode() const {
|
| + ASSERT(getNodeCodePointCount() <= mDicNodeProperties.getLeavingDepth());
|
| + return getNodeCodePointCount() == mDicNodeProperties.getLeavingDepth();
|
| + }
|
| +
|
| + AK_FORCE_INLINE bool isFirstLetter() const {
|
| + return getNodeCodePointCount() == 1;
|
| + }
|
| +
|
| + bool isCached() const {
|
| + return mIsCachedForNextSuggestion;
|
| + }
|
| +
|
| + void setCached() {
|
| + mIsCachedForNextSuggestion = true;
|
| + }
|
| +
|
| + // Check if the current word and the previous word can be considered as a valid multiple word
|
| + // suggestion.
|
| + bool isValidMultipleWordSuggestion() const {
|
| + if (isBlacklistedOrNotAWord()) {
|
| + return false;
|
| + }
|
| + // Treat suggestion as invalid if the current and the previous word are single character
|
| + // words.
|
| + const int prevWordLen = mDicNodeState.mDicNodeStateOutput.getPrevWordsLength()
|
| + - mDicNodeState.mDicNodeStateOutput.getPrevWordStart() - 1;
|
| + const int currentWordLen = getNodeCodePointCount();
|
| + return (prevWordLen != 1 || currentWordLen != 1);
|
| + }
|
| +
|
| + bool isFirstCharUppercase() const {
|
| + const int c = mDicNodeState.mDicNodeStateOutput.getCurrentWordCodePointAt(0);
|
| + return CharUtils::isAsciiUpper(c);
|
| + }
|
| +
|
| + bool isCompletion(const int inputSize) const {
|
| + return mDicNodeState.mDicNodeStateInput.getInputIndex(0) >= inputSize;
|
| + }
|
| +
|
| + bool canDoLookAheadCorrection(const int inputSize) const {
|
| + return mDicNodeState.mDicNodeStateInput.getInputIndex(0) < inputSize - 1;
|
| + }
|
| +
|
| + // Used to get n-gram probability in DicNodeUtils.
|
| + int getPtNodePos() const {
|
| + return mDicNodeProperties.getPtNodePos();
|
| + }
|
| +
|
| + // TODO: Use view class to return PtNodePos array.
|
| + const int *getPrevWordsTerminalPtNodePos() const {
|
| + return mDicNodeProperties.getPrevWordsTerminalPtNodePos();
|
| + }
|
| +
|
| + // Used in DicNodeUtils
|
| + int getChildrenPtNodeArrayPos() const {
|
| + return mDicNodeProperties.getChildrenPtNodeArrayPos();
|
| + }
|
| +
|
| + int getProbability() const {
|
| + return mDicNodeProperties.getProbability();
|
| + }
|
| +
|
| + AK_FORCE_INLINE bool isTerminalDicNode() const {
|
| + const bool isTerminalPtNode = mDicNodeProperties.isTerminal();
|
| + const int currentDicNodeDepth = getNodeCodePointCount();
|
| + const int terminalDicNodeDepth = mDicNodeProperties.getLeavingDepth();
|
| + return isTerminalPtNode && currentDicNodeDepth > 0
|
| + && currentDicNodeDepth == terminalDicNodeDepth;
|
| + }
|
| +
|
| + bool shouldBeFilteredBySafetyNetForBigram() const {
|
| + const uint16_t currentDepth = getNodeCodePointCount();
|
| + const int prevWordLen = mDicNodeState.mDicNodeStateOutput.getPrevWordsLength()
|
| + - mDicNodeState.mDicNodeStateOutput.getPrevWordStart() - 1;
|
| + return !(currentDepth > 0 && (currentDepth != 1 || prevWordLen != 1));
|
| + }
|
| +
|
| + bool hasMatchedOrProximityCodePoints() const {
|
| + // This DicNode does not have matched or proximity code points when all code points have
|
| + // been handled as edit corrections or completion so far.
|
| + const int editCorrectionCount = mDicNodeState.mDicNodeStateScoring.getEditCorrectionCount();
|
| + const int completionCount = mDicNodeState.mDicNodeStateScoring.getCompletionCount();
|
| + return (editCorrectionCount + completionCount) < getNodeCodePointCount();
|
| + }
|
| +
|
| + bool isTotalInputSizeExceedingLimit() const {
|
| + // TODO: 3 can be 2? Needs to be investigated.
|
| + // TODO: Have a const variable for 3 (or 2)
|
| + return getTotalNodeCodePointCount() > MAX_WORD_LENGTH - 3;
|
| + }
|
| +
|
| + void outputResult(int *dest) const {
|
| + memmove(dest, getOutputWordBuf(), getTotalNodeCodePointCount() * sizeof(dest[0]));
|
| + DUMP_WORD_AND_SCORE("OUTPUT");
|
| + }
|
| +
|
| + // "Total" in this context (and other methods in this class) means the whole suggestion. When
|
| + // this represents a multi-word suggestion, the referenced PtNode (in mDicNodeState) is only
|
| + // the one that corresponds to the last word of the suggestion, and all the previous words
|
| + // are concatenated together in mDicNodeStateOutput.
|
| + int getTotalNodeSpaceCount() const {
|
| + if (!hasMultipleWords()) {
|
| + return 0;
|
| + }
|
| + return CharUtils::getSpaceCount(mDicNodeState.mDicNodeStateOutput.getCodePointBuf(),
|
| + mDicNodeState.mDicNodeStateOutput.getPrevWordsLength());
|
| + }
|
| +
|
| + int getSecondWordFirstInputIndex(const ProximityInfoState *const pInfoState) const {
|
| + const int inputIndex = mDicNodeState.mDicNodeStateOutput.getSecondWordFirstInputIndex();
|
| + if (inputIndex == NOT_AN_INDEX) {
|
| + return NOT_AN_INDEX;
|
| + } else {
|
| + return pInfoState->getInputIndexOfSampledPoint(inputIndex);
|
| + }
|
| + }
|
| +
|
| + bool hasMultipleWords() const {
|
| + return mDicNodeState.mDicNodeStateOutput.getPrevWordCount() > 0;
|
| + }
|
| +
|
| + int getProximityCorrectionCount() const {
|
| + return mDicNodeState.mDicNodeStateScoring.getProximityCorrectionCount();
|
| + }
|
| +
|
| + int getEditCorrectionCount() const {
|
| + return mDicNodeState.mDicNodeStateScoring.getEditCorrectionCount();
|
| + }
|
| +
|
| + // Used to prune nodes
|
| + float getNormalizedCompoundDistance() const {
|
| + return mDicNodeState.mDicNodeStateScoring.getNormalizedCompoundDistance();
|
| + }
|
| +
|
| + // Used to prune nodes
|
| + float getNormalizedSpatialDistance() const {
|
| + return mDicNodeState.mDicNodeStateScoring.getSpatialDistance()
|
| + / static_cast<float>(getInputIndex(0) + 1);
|
| + }
|
| +
|
| + // Used to prune nodes
|
| + float getCompoundDistance() const {
|
| + return mDicNodeState.mDicNodeStateScoring.getCompoundDistance();
|
| + }
|
| +
|
| + // Used to prune nodes
|
| + float getCompoundDistance(const float languageWeight) const {
|
| + return mDicNodeState.mDicNodeStateScoring.getCompoundDistance(languageWeight);
|
| + }
|
| +
|
| + AK_FORCE_INLINE const int *getOutputWordBuf() const {
|
| + return mDicNodeState.mDicNodeStateOutput.getCodePointBuf();
|
| + }
|
| +
|
| + int getPrevCodePointG(int pointerId) const {
|
| + return mDicNodeState.mDicNodeStateInput.getPrevCodePoint(pointerId);
|
| + }
|
| +
|
| + // Whether the current codepoint can be an intentional omission, in which case the traversal
|
| + // algorithm will always check for a possible omission here.
|
| + bool canBeIntentionalOmission() const {
|
| + return CharUtils::isIntentionalOmissionCodePoint(getNodeCodePoint());
|
| + }
|
| +
|
| + // Whether the omission is so frequent that it should incur zero cost.
|
| + bool isZeroCostOmission() const {
|
| + // TODO: do not hardcode and read from header
|
| + return (getNodeCodePoint() == KEYCODE_SINGLE_QUOTE);
|
| + }
|
| +
|
| + // TODO: remove
|
| + float getTerminalDiffCostG(int path) const {
|
| + return mDicNodeState.mDicNodeStateInput.getTerminalDiffCost(path);
|
| + }
|
| +
|
| + //////////////////////
|
| + // Temporary getter //
|
| + // TODO: Remove //
|
| + //////////////////////
|
| + // TODO: Remove once touch path is merged into ProximityInfoState
|
| + // Note: Returned codepoint may be a digraph codepoint if the node is in a composite glyph.
|
| + int getNodeCodePoint() const {
|
| + const int codePoint = mDicNodeProperties.getDicNodeCodePoint();
|
| + const DigraphUtils::DigraphCodePointIndex digraphIndex =
|
| + mDicNodeState.mDicNodeStateScoring.getDigraphIndex();
|
| + if (digraphIndex == DigraphUtils::NOT_A_DIGRAPH_INDEX) {
|
| + return codePoint;
|
| + }
|
| + return DigraphUtils::getDigraphCodePointForIndex(codePoint, digraphIndex);
|
| + }
|
| +
|
| + ////////////////////////////////
|
| + // Utils for cost calculation //
|
| + ////////////////////////////////
|
| + AK_FORCE_INLINE bool isSameNodeCodePoint(const DicNode *const dicNode) const {
|
| + return mDicNodeProperties.getDicNodeCodePoint()
|
| + == dicNode->mDicNodeProperties.getDicNodeCodePoint();
|
| + }
|
| +
|
| + // TODO: remove
|
| + // TODO: rename getNextInputIndex
|
| + int16_t getInputIndex(int pointerId) const {
|
| + return mDicNodeState.mDicNodeStateInput.getInputIndex(pointerId);
|
| + }
|
| +
|
| + ////////////////////////////////////
|
| + // Getter of features for scoring //
|
| + ////////////////////////////////////
|
| + float getSpatialDistanceForScoring() const {
|
| + return mDicNodeState.mDicNodeStateScoring.getSpatialDistance();
|
| + }
|
| +
|
| + // For space-aware gestures, we store the normalized distance at the char index
|
| + // that ends the first word of the suggestion. We call this the distance after
|
| + // first word.
|
| + float getNormalizedCompoundDistanceAfterFirstWord() const {
|
| + return mDicNodeState.mDicNodeStateScoring.getNormalizedCompoundDistanceAfterFirstWord();
|
| + }
|
| +
|
| + float getRawLength() const {
|
| + return mDicNodeState.mDicNodeStateScoring.getRawLength();
|
| + }
|
| +
|
| + DoubleLetterLevel getDoubleLetterLevel() const {
|
| + return mDicNodeState.mDicNodeStateScoring.getDoubleLetterLevel();
|
| + }
|
| +
|
| + void setDoubleLetterLevel(DoubleLetterLevel doubleLetterLevel) {
|
| + mDicNodeState.mDicNodeStateScoring.setDoubleLetterLevel(doubleLetterLevel);
|
| + }
|
| +
|
| + bool isInDigraph() const {
|
| + return mDicNodeState.mDicNodeStateScoring.getDigraphIndex()
|
| + != DigraphUtils::NOT_A_DIGRAPH_INDEX;
|
| + }
|
| +
|
| + void advanceDigraphIndex() {
|
| + mDicNodeState.mDicNodeStateScoring.advanceDigraphIndex();
|
| + }
|
| +
|
| + ErrorTypeUtils::ErrorType getContainedErrorTypes() const {
|
| + return mDicNodeState.mDicNodeStateScoring.getContainedErrorTypes();
|
| + }
|
| +
|
| + bool isBlacklistedOrNotAWord() const {
|
| + return mDicNodeProperties.isBlacklistedOrNotAWord();
|
| + }
|
| +
|
| + inline uint16_t getNodeCodePointCount() const {
|
| + return mDicNodeProperties.getDepth();
|
| + }
|
| +
|
| + // Returns code point count including spaces
|
| + inline uint16_t getTotalNodeCodePointCount() const {
|
| + return getNodeCodePointCount() + mDicNodeState.mDicNodeStateOutput.getPrevWordsLength();
|
| + }
|
| +
|
| + AK_FORCE_INLINE void dump(const char *tag) const {
|
| +#if DEBUG_DICT
|
| + DUMP_WORD_AND_SCORE(tag);
|
| +#if DEBUG_DUMP_ERROR
|
| + mProfiler.dump();
|
| +#endif
|
| +#endif
|
| + }
|
| +
|
| + AK_FORCE_INLINE bool compare(const DicNode *right) const {
|
| + // Promote exact matches to prevent them from being pruned.
|
| + const bool leftExactMatch = ErrorTypeUtils::isExactMatch(getContainedErrorTypes());
|
| + const bool rightExactMatch = ErrorTypeUtils::isExactMatch(right->getContainedErrorTypes());
|
| + if (leftExactMatch != rightExactMatch) {
|
| + return leftExactMatch;
|
| + }
|
| + const float diff =
|
| + right->getNormalizedCompoundDistance() - getNormalizedCompoundDistance();
|
| + static const float MIN_DIFF = 0.000001f;
|
| + if (diff > MIN_DIFF) {
|
| + return true;
|
| + } else if (diff < -MIN_DIFF) {
|
| + return false;
|
| + }
|
| + const int depth = getNodeCodePointCount();
|
| + const int depthDiff = right->getNodeCodePointCount() - depth;
|
| + if (depthDiff != 0) {
|
| + return depthDiff > 0;
|
| + }
|
| + for (int i = 0; i < depth; ++i) {
|
| + const int codePoint = mDicNodeState.mDicNodeStateOutput.getCurrentWordCodePointAt(i);
|
| + const int rightCodePoint =
|
| + right->mDicNodeState.mDicNodeStateOutput.getCurrentWordCodePointAt(i);
|
| + if (codePoint != rightCodePoint) {
|
| + return rightCodePoint > codePoint;
|
| + }
|
| + }
|
| + // Compare pointer values here for stable comparison
|
| + return this > right;
|
| + }
|
| +
|
| + private:
|
| + DicNodeProperties mDicNodeProperties;
|
| + DicNodeState mDicNodeState;
|
| + // TODO: Remove
|
| + bool mIsCachedForNextSuggestion;
|
| +
|
| + AK_FORCE_INLINE int getTotalInputIndex() const {
|
| + int index = 0;
|
| + for (int i = 0; i < MAX_POINTER_COUNT_G; i++) {
|
| + index += mDicNodeState.mDicNodeStateInput.getInputIndex(i);
|
| + }
|
| + return index;
|
| + }
|
| +
|
| + // Caveat: Must not be called outside Weighting
|
| + // This restriction is guaranteed by "friend"
|
| + AK_FORCE_INLINE void addCost(const float spatialCost, const float languageCost,
|
| + const bool doNormalization, const int inputSize,
|
| + const ErrorTypeUtils::ErrorType errorType) {
|
| + if (DEBUG_GEO_FULL) {
|
| + LOGI_SHOW_ADD_COST_PROP;
|
| + }
|
| + mDicNodeState.mDicNodeStateScoring.addCost(spatialCost, languageCost, doNormalization,
|
| + inputSize, getTotalInputIndex(), errorType);
|
| + }
|
| +
|
| + // Saves the current normalized compound distance for space-aware gestures.
|
| + // See getNormalizedCompoundDistanceAfterFirstWord for details.
|
| + AK_FORCE_INLINE void saveNormalizedCompoundDistanceAfterFirstWordIfNoneYet() {
|
| + mDicNodeState.mDicNodeStateScoring.saveNormalizedCompoundDistanceAfterFirstWordIfNoneYet();
|
| + }
|
| +
|
| + // Caveat: Must not be called outside Weighting
|
| + // This restriction is guaranteed by "friend"
|
| + AK_FORCE_INLINE void forwardInputIndex(const int pointerId, const int count,
|
| + const bool overwritesPrevCodePointByNodeCodePoint) {
|
| + if (count == 0) {
|
| + return;
|
| + }
|
| + mDicNodeState.mDicNodeStateInput.forwardInputIndex(pointerId, count);
|
| + if (overwritesPrevCodePointByNodeCodePoint) {
|
| + mDicNodeState.mDicNodeStateInput.setPrevCodePoint(0, getNodeCodePoint());
|
| + }
|
| + }
|
| +
|
| + AK_FORCE_INLINE void updateInputIndexG(const DicNode_InputStateG *const inputStateG) {
|
| + if (mDicNodeState.mDicNodeStateOutput.getPrevWordCount() == 1 && isFirstLetter()) {
|
| + mDicNodeState.mDicNodeStateOutput.setSecondWordFirstInputIndex(
|
| + inputStateG->mInputIndex);
|
| + }
|
| + mDicNodeState.mDicNodeStateInput.updateInputIndexG(inputStateG->mPointerId,
|
| + inputStateG->mInputIndex, inputStateG->mPrevCodePoint,
|
| + inputStateG->mTerminalDiffCost, inputStateG->mRawLength);
|
| + mDicNodeState.mDicNodeStateScoring.addRawLength(inputStateG->mRawLength);
|
| + mDicNodeState.mDicNodeStateScoring.setDoubleLetterLevel(inputStateG->mDoubleLetterLevel);
|
| + }
|
| +};
|
| +} // namespace latinime
|
| +#endif // LATINIME_DIC_NODE_H
|
|
|