OLD | NEW |
(Empty) | |
| 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_NODE_H |
| 18 #define LATINIME_DIC_NODE_H |
| 19 |
| 20 #include "third_party/prediction/defines.h" |
| 21 #include "third_party/prediction/suggest/core/dicnode/dic_node_profiler.h" |
| 22 #include "third_party/prediction/suggest/core/dicnode/dic_node_utils.h" |
| 23 #include "third_party/prediction/suggest/core/dicnode/internal/dic_node_state.h" |
| 24 #include "third_party/prediction/suggest/core/dicnode/internal/dic_node_properti
es.h" |
| 25 #include "third_party/prediction/suggest/core/dictionary/digraph_utils.h" |
| 26 #include "third_party/prediction/suggest/core/dictionary/error_type_utils.h" |
| 27 #include "third_party/prediction/suggest/core/layout/proximity_info_state.h" |
| 28 #include "third_party/prediction/utils/char_utils.h" |
| 29 |
| 30 #if DEBUG_DICT |
| 31 #define LOGI_SHOW_ADD_COST_PROP \ |
| 32 do { \ |
| 33 char charBuf[50]; \ |
| 34 INTS_TO_CHARS(getOutputWordBuf(), getNodeCodePointCount(), charBuf, \ |
| 35 NELEMS(charBuf)); \ |
| 36 AKLOGI( \ |
| 37 "%20s, \"%c\", size = %03d, total = %03d, index(0) = %02d, dist = " \ |
| 38 "%.4f, %s,,", \ |
| 39 __FUNCTION__, getNodeCodePoint(), inputSize, getTotalInputIndex(), \ |
| 40 getInputIndex(0), getNormalizedCompoundDistance(), charBuf); \ |
| 41 } while (0) |
| 42 #define DUMP_WORD_AND_SCORE(header) \ |
| 43 do { \ |
| 44 char charBuf[50]; \ |
| 45 INTS_TO_CHARS(getOutputWordBuf(), \ |
| 46 getNodeCodePointCount() + \ |
| 47 mDicNodeState.mDicNodeStateOutput.getPrevWordsLength(), \ |
| 48 charBuf, NELEMS(charBuf)); \ |
| 49 AKLOGI("#%8s, %5f, %5f, %5f, %5f, %s, %d, %5f,", header, \ |
| 50 getSpatialDistanceForScoring(), \ |
| 51 mDicNodeState.mDicNodeStateScoring.getLanguageDistance(), \ |
| 52 getNormalizedCompoundDistance(), getRawLength(), charBuf, \ |
| 53 getInputIndex(0), getNormalizedCompoundDistanceAfterFirstWord()); \ |
| 54 } while (0) |
| 55 #else |
| 56 #define LOGI_SHOW_ADD_COST_PROP |
| 57 #define DUMP_WORD_AND_SCORE(header) |
| 58 #endif |
| 59 |
| 60 namespace latinime { |
| 61 |
| 62 // This struct is purely a bucket to return values. No instances of this struct |
| 63 // should be kept. |
| 64 struct DicNode_InputStateG { |
| 65 DicNode_InputStateG() |
| 66 : mNeedsToUpdateInputStateG(false), |
| 67 mPointerId(0), |
| 68 mInputIndex(0), |
| 69 mPrevCodePoint(0), |
| 70 mTerminalDiffCost(0.0f), |
| 71 mRawLength(0.0f), |
| 72 mDoubleLetterLevel(NOT_A_DOUBLE_LETTER) {} |
| 73 |
| 74 bool mNeedsToUpdateInputStateG; |
| 75 int mPointerId; |
| 76 int16_t mInputIndex; |
| 77 int mPrevCodePoint; |
| 78 float mTerminalDiffCost; |
| 79 float mRawLength; |
| 80 DoubleLetterLevel mDoubleLetterLevel; |
| 81 }; |
| 82 |
| 83 class DicNode { |
| 84 // Caveat: We define Weighting as a friend class of DicNode to let Weighting |
| 85 // change |
| 86 // the distance of DicNode. |
| 87 // Caution!!! In general, we avoid using the "friend" access modifier. |
| 88 // This is an exception to explicitly hide DicNode::addCost() from all classes |
| 89 // but Weighting. |
| 90 friend class Weighting; |
| 91 |
| 92 public: |
| 93 #if DEBUG_DICT |
| 94 DicNodeProfiler mProfiler; |
| 95 #endif |
| 96 |
| 97 AK_FORCE_INLINE DicNode() |
| 98 : |
| 99 #if DEBUG_DICT |
| 100 mProfiler(), |
| 101 #endif |
| 102 mDicNodeProperties(), |
| 103 mDicNodeState(), |
| 104 mIsCachedForNextSuggestion(false) { |
| 105 } |
| 106 |
| 107 DicNode(const DicNode& dicNode); |
| 108 DicNode& operator=(const DicNode& dicNode); |
| 109 ~DicNode() {} |
| 110 |
| 111 // Init for copy |
| 112 void initByCopy(const DicNode* const dicNode) { |
| 113 mIsCachedForNextSuggestion = dicNode->mIsCachedForNextSuggestion; |
| 114 mDicNodeProperties.initByCopy(&dicNode->mDicNodeProperties); |
| 115 mDicNodeState.initByCopy(&dicNode->mDicNodeState); |
| 116 PROF_NODE_COPY(&dicNode->mProfiler, mProfiler); |
| 117 } |
| 118 |
| 119 // Init for root with prevWordsPtNodePos which is used for n-gram |
| 120 void initAsRoot(const int rootPtNodeArrayPos, |
| 121 const int* const prevWordsPtNodePos) { |
| 122 mIsCachedForNextSuggestion = false; |
| 123 mDicNodeProperties.init(rootPtNodeArrayPos, prevWordsPtNodePos); |
| 124 mDicNodeState.init(); |
| 125 PROF_NODE_RESET(mProfiler); |
| 126 } |
| 127 |
| 128 // Init for root with previous word |
| 129 void initAsRootWithPreviousWord(const DicNode* const dicNode, |
| 130 const int rootPtNodeArrayPos) { |
| 131 mIsCachedForNextSuggestion = dicNode->mIsCachedForNextSuggestion; |
| 132 int newPrevWordsPtNodePos[MAX_PREV_WORD_COUNT_FOR_N_GRAM]; |
| 133 newPrevWordsPtNodePos[0] = dicNode->mDicNodeProperties.getPtNodePos(); |
| 134 for (size_t i = 1; i < NELEMS(newPrevWordsPtNodePos); ++i) { |
| 135 newPrevWordsPtNodePos[i] = |
| 136 dicNode->getPrevWordsTerminalPtNodePos()[i - 1]; |
| 137 } |
| 138 mDicNodeProperties.init(rootPtNodeArrayPos, newPrevWordsPtNodePos); |
| 139 mDicNodeState.initAsRootWithPreviousWord( |
| 140 &dicNode->mDicNodeState, dicNode->mDicNodeProperties.getDepth()); |
| 141 PROF_NODE_COPY(&dicNode->mProfiler, mProfiler); |
| 142 } |
| 143 |
| 144 void initAsPassingChild(const DicNode* parentDicNode) { |
| 145 mIsCachedForNextSuggestion = parentDicNode->mIsCachedForNextSuggestion; |
| 146 const int codePoint = |
| 147 parentDicNode->mDicNodeState.mDicNodeStateOutput |
| 148 .getCurrentWordCodePointAt(parentDicNode->getNodeCodePointCount()); |
| 149 mDicNodeProperties.init(&parentDicNode->mDicNodeProperties, codePoint); |
| 150 mDicNodeState.initByCopy(&parentDicNode->mDicNodeState); |
| 151 PROF_NODE_COPY(&parentDicNode->mProfiler, mProfiler); |
| 152 } |
| 153 |
| 154 void initAsChild(const DicNode* const dicNode, |
| 155 const int ptNodePos, |
| 156 const int childrenPtNodeArrayPos, |
| 157 const int probability, |
| 158 const bool isTerminal, |
| 159 const bool hasChildren, |
| 160 const bool isBlacklistedOrNotAWord, |
| 161 const uint16_t mergedNodeCodePointCount, |
| 162 const int* const mergedNodeCodePoints) { |
| 163 uint16_t newDepth = |
| 164 static_cast<uint16_t>(dicNode->getNodeCodePointCount() + 1); |
| 165 mIsCachedForNextSuggestion = dicNode->mIsCachedForNextSuggestion; |
| 166 const uint16_t newLeavingDepth = |
| 167 static_cast<uint16_t>(dicNode->mDicNodeProperties.getLeavingDepth() + |
| 168 mergedNodeCodePointCount); |
| 169 mDicNodeProperties.init( |
| 170 ptNodePos, childrenPtNodeArrayPos, mergedNodeCodePoints[0], probability, |
| 171 isTerminal, hasChildren, isBlacklistedOrNotAWord, newDepth, |
| 172 newLeavingDepth, |
| 173 dicNode->mDicNodeProperties.getPrevWordsTerminalPtNodePos()); |
| 174 mDicNodeState.init(&dicNode->mDicNodeState, mergedNodeCodePointCount, |
| 175 mergedNodeCodePoints); |
| 176 PROF_NODE_COPY(&dicNode->mProfiler, mProfiler); |
| 177 } |
| 178 |
| 179 bool isRoot() const { return getNodeCodePointCount() == 0; } |
| 180 |
| 181 bool hasChildren() const { return mDicNodeProperties.hasChildren(); } |
| 182 |
| 183 bool isLeavingNode() const { |
| 184 ASSERT(getNodeCodePointCount() <= mDicNodeProperties.getLeavingDepth()); |
| 185 return getNodeCodePointCount() == mDicNodeProperties.getLeavingDepth(); |
| 186 } |
| 187 |
| 188 AK_FORCE_INLINE bool isFirstLetter() const { |
| 189 return getNodeCodePointCount() == 1; |
| 190 } |
| 191 |
| 192 bool isCached() const { return mIsCachedForNextSuggestion; } |
| 193 |
| 194 void setCached() { mIsCachedForNextSuggestion = true; } |
| 195 |
| 196 // Check if the current word and the previous word can be considered as a |
| 197 // valid multiple word |
| 198 // suggestion. |
| 199 bool isValidMultipleWordSuggestion() const { |
| 200 if (isBlacklistedOrNotAWord()) { |
| 201 return false; |
| 202 } |
| 203 // Treat suggestion as invalid if the current and the previous word are |
| 204 // single character |
| 205 // words. |
| 206 const int prevWordLen = |
| 207 mDicNodeState.mDicNodeStateOutput.getPrevWordsLength() - |
| 208 mDicNodeState.mDicNodeStateOutput.getPrevWordStart() - 1; |
| 209 const int currentWordLen = getNodeCodePointCount(); |
| 210 return (prevWordLen != 1 || currentWordLen != 1); |
| 211 } |
| 212 |
| 213 bool isFirstCharUppercase() const { |
| 214 const int c = |
| 215 mDicNodeState.mDicNodeStateOutput.getCurrentWordCodePointAt(0); |
| 216 return CharUtils::isAsciiUpper(c); |
| 217 } |
| 218 |
| 219 bool isCompletion(const int inputSize) const { |
| 220 return mDicNodeState.mDicNodeStateInput.getInputIndex(0) >= inputSize; |
| 221 } |
| 222 |
| 223 bool canDoLookAheadCorrection(const int inputSize) const { |
| 224 return mDicNodeState.mDicNodeStateInput.getInputIndex(0) < inputSize - 1; |
| 225 } |
| 226 |
| 227 // Used to get n-gram probability in DicNodeUtils. |
| 228 int getPtNodePos() const { return mDicNodeProperties.getPtNodePos(); } |
| 229 |
| 230 // TODO: Use view class to return PtNodePos array. |
| 231 const int* getPrevWordsTerminalPtNodePos() const { |
| 232 return mDicNodeProperties.getPrevWordsTerminalPtNodePos(); |
| 233 } |
| 234 |
| 235 // Used in DicNodeUtils |
| 236 int getChildrenPtNodeArrayPos() const { |
| 237 return mDicNodeProperties.getChildrenPtNodeArrayPos(); |
| 238 } |
| 239 |
| 240 int getProbability() const { return mDicNodeProperties.getProbability(); } |
| 241 |
| 242 AK_FORCE_INLINE bool isTerminalDicNode() const { |
| 243 const bool isTerminalPtNode = mDicNodeProperties.isTerminal(); |
| 244 const int currentDicNodeDepth = getNodeCodePointCount(); |
| 245 const int terminalDicNodeDepth = mDicNodeProperties.getLeavingDepth(); |
| 246 return isTerminalPtNode && currentDicNodeDepth > 0 && |
| 247 currentDicNodeDepth == terminalDicNodeDepth; |
| 248 } |
| 249 |
| 250 bool shouldBeFilteredBySafetyNetForBigram() const { |
| 251 const uint16_t currentDepth = getNodeCodePointCount(); |
| 252 const int prevWordLen = |
| 253 mDicNodeState.mDicNodeStateOutput.getPrevWordsLength() - |
| 254 mDicNodeState.mDicNodeStateOutput.getPrevWordStart() - 1; |
| 255 return !(currentDepth > 0 && (currentDepth != 1 || prevWordLen != 1)); |
| 256 } |
| 257 |
| 258 bool hasMatchedOrProximityCodePoints() const { |
| 259 // This DicNode does not have matched or proximity code points when all code |
| 260 // points have |
| 261 // been handled as edit corrections or completion so far. |
| 262 const int editCorrectionCount = |
| 263 mDicNodeState.mDicNodeStateScoring.getEditCorrectionCount(); |
| 264 const int completionCount = |
| 265 mDicNodeState.mDicNodeStateScoring.getCompletionCount(); |
| 266 return (editCorrectionCount + completionCount) < getNodeCodePointCount(); |
| 267 } |
| 268 |
| 269 bool isTotalInputSizeExceedingLimit() const { |
| 270 // TODO: 3 can be 2? Needs to be investigated. |
| 271 // TODO: Have a const variable for 3 (or 2) |
| 272 return getTotalNodeCodePointCount() > MAX_WORD_LENGTH - 3; |
| 273 } |
| 274 |
| 275 void outputResult(int* dest) const { |
| 276 memmove(dest, getOutputWordBuf(), |
| 277 getTotalNodeCodePointCount() * sizeof(dest[0])); |
| 278 DUMP_WORD_AND_SCORE("OUTPUT"); |
| 279 } |
| 280 |
| 281 // "Total" in this context (and other methods in this class) means the whole |
| 282 // suggestion. When |
| 283 // this represents a multi-word suggestion, the referenced PtNode (in |
| 284 // mDicNodeState) is only |
| 285 // the one that corresponds to the last word of the suggestion, and all the |
| 286 // previous words |
| 287 // are concatenated together in mDicNodeStateOutput. |
| 288 int getTotalNodeSpaceCount() const { |
| 289 if (!hasMultipleWords()) { |
| 290 return 0; |
| 291 } |
| 292 return CharUtils::getSpaceCount( |
| 293 mDicNodeState.mDicNodeStateOutput.getCodePointBuf(), |
| 294 mDicNodeState.mDicNodeStateOutput.getPrevWordsLength()); |
| 295 } |
| 296 |
| 297 int getSecondWordFirstInputIndex( |
| 298 const ProximityInfoState* const pInfoState) const { |
| 299 const int inputIndex = |
| 300 mDicNodeState.mDicNodeStateOutput.getSecondWordFirstInputIndex(); |
| 301 if (inputIndex == NOT_AN_INDEX) { |
| 302 return NOT_AN_INDEX; |
| 303 } else { |
| 304 return pInfoState->getInputIndexOfSampledPoint(inputIndex); |
| 305 } |
| 306 } |
| 307 |
| 308 bool hasMultipleWords() const { |
| 309 return mDicNodeState.mDicNodeStateOutput.getPrevWordCount() > 0; |
| 310 } |
| 311 |
| 312 int getProximityCorrectionCount() const { |
| 313 return mDicNodeState.mDicNodeStateScoring.getProximityCorrectionCount(); |
| 314 } |
| 315 |
| 316 int getEditCorrectionCount() const { |
| 317 return mDicNodeState.mDicNodeStateScoring.getEditCorrectionCount(); |
| 318 } |
| 319 |
| 320 // Used to prune nodes |
| 321 float getNormalizedCompoundDistance() const { |
| 322 return mDicNodeState.mDicNodeStateScoring.getNormalizedCompoundDistance(); |
| 323 } |
| 324 |
| 325 // Used to prune nodes |
| 326 float getNormalizedSpatialDistance() const { |
| 327 return mDicNodeState.mDicNodeStateScoring.getSpatialDistance() / |
| 328 static_cast<float>(getInputIndex(0) + 1); |
| 329 } |
| 330 |
| 331 // Used to prune nodes |
| 332 float getCompoundDistance() const { |
| 333 return mDicNodeState.mDicNodeStateScoring.getCompoundDistance(); |
| 334 } |
| 335 |
| 336 // Used to prune nodes |
| 337 float getCompoundDistance(const float languageWeight) const { |
| 338 return mDicNodeState.mDicNodeStateScoring.getCompoundDistance( |
| 339 languageWeight); |
| 340 } |
| 341 |
| 342 AK_FORCE_INLINE const int* getOutputWordBuf() const { |
| 343 return mDicNodeState.mDicNodeStateOutput.getCodePointBuf(); |
| 344 } |
| 345 |
| 346 int getPrevCodePointG(int pointerId) const { |
| 347 return mDicNodeState.mDicNodeStateInput.getPrevCodePoint(pointerId); |
| 348 } |
| 349 |
| 350 // Whether the current codepoint can be an intentional omission, in which case |
| 351 // the traversal |
| 352 // algorithm will always check for a possible omission here. |
| 353 bool canBeIntentionalOmission() const { |
| 354 return CharUtils::isIntentionalOmissionCodePoint(getNodeCodePoint()); |
| 355 } |
| 356 |
| 357 // Whether the omission is so frequent that it should incur zero cost. |
| 358 bool isZeroCostOmission() const { |
| 359 // TODO: do not hardcode and read from header |
| 360 return (getNodeCodePoint() == KEYCODE_SINGLE_QUOTE); |
| 361 } |
| 362 |
| 363 // TODO: remove |
| 364 float getTerminalDiffCostG(int path) const { |
| 365 return mDicNodeState.mDicNodeStateInput.getTerminalDiffCost(path); |
| 366 } |
| 367 |
| 368 ////////////////////// |
| 369 // Temporary getter // |
| 370 // TODO: Remove // |
| 371 ////////////////////// |
| 372 // TODO: Remove once touch path is merged into ProximityInfoState |
| 373 // Note: Returned codepoint may be a digraph codepoint if the node is in a |
| 374 // composite glyph. |
| 375 int getNodeCodePoint() const { |
| 376 const int codePoint = mDicNodeProperties.getDicNodeCodePoint(); |
| 377 const DigraphUtils::DigraphCodePointIndex digraphIndex = |
| 378 mDicNodeState.mDicNodeStateScoring.getDigraphIndex(); |
| 379 if (digraphIndex == DigraphUtils::NOT_A_DIGRAPH_INDEX) { |
| 380 return codePoint; |
| 381 } |
| 382 return DigraphUtils::getDigraphCodePointForIndex(codePoint, digraphIndex); |
| 383 } |
| 384 |
| 385 //////////////////////////////// |
| 386 // Utils for cost calculation // |
| 387 //////////////////////////////// |
| 388 AK_FORCE_INLINE bool isSameNodeCodePoint(const DicNode* const dicNode) const { |
| 389 return mDicNodeProperties.getDicNodeCodePoint() == |
| 390 dicNode->mDicNodeProperties.getDicNodeCodePoint(); |
| 391 } |
| 392 |
| 393 // TODO: remove |
| 394 // TODO: rename getNextInputIndex |
| 395 int16_t getInputIndex(int pointerId) const { |
| 396 return mDicNodeState.mDicNodeStateInput.getInputIndex(pointerId); |
| 397 } |
| 398 |
| 399 //////////////////////////////////// |
| 400 // Getter of features for scoring // |
| 401 //////////////////////////////////// |
| 402 float getSpatialDistanceForScoring() const { |
| 403 return mDicNodeState.mDicNodeStateScoring.getSpatialDistance(); |
| 404 } |
| 405 |
| 406 // For space-aware gestures, we store the normalized distance at the char |
| 407 // index |
| 408 // that ends the first word of the suggestion. We call this the distance after |
| 409 // first word. |
| 410 float getNormalizedCompoundDistanceAfterFirstWord() const { |
| 411 return mDicNodeState.mDicNodeStateScoring |
| 412 .getNormalizedCompoundDistanceAfterFirstWord(); |
| 413 } |
| 414 |
| 415 float getRawLength() const { |
| 416 return mDicNodeState.mDicNodeStateScoring.getRawLength(); |
| 417 } |
| 418 |
| 419 DoubleLetterLevel getDoubleLetterLevel() const { |
| 420 return mDicNodeState.mDicNodeStateScoring.getDoubleLetterLevel(); |
| 421 } |
| 422 |
| 423 void setDoubleLetterLevel(DoubleLetterLevel doubleLetterLevel) { |
| 424 mDicNodeState.mDicNodeStateScoring.setDoubleLetterLevel(doubleLetterLevel); |
| 425 } |
| 426 |
| 427 bool isInDigraph() const { |
| 428 return mDicNodeState.mDicNodeStateScoring.getDigraphIndex() != |
| 429 DigraphUtils::NOT_A_DIGRAPH_INDEX; |
| 430 } |
| 431 |
| 432 void advanceDigraphIndex() { |
| 433 mDicNodeState.mDicNodeStateScoring.advanceDigraphIndex(); |
| 434 } |
| 435 |
| 436 ErrorTypeUtils::ErrorType getContainedErrorTypes() const { |
| 437 return mDicNodeState.mDicNodeStateScoring.getContainedErrorTypes(); |
| 438 } |
| 439 |
| 440 bool isBlacklistedOrNotAWord() const { |
| 441 return mDicNodeProperties.isBlacklistedOrNotAWord(); |
| 442 } |
| 443 |
| 444 inline uint16_t getNodeCodePointCount() const { |
| 445 return mDicNodeProperties.getDepth(); |
| 446 } |
| 447 |
| 448 // Returns code point count including spaces |
| 449 inline uint16_t getTotalNodeCodePointCount() const { |
| 450 return getNodeCodePointCount() + |
| 451 mDicNodeState.mDicNodeStateOutput.getPrevWordsLength(); |
| 452 } |
| 453 |
| 454 AK_FORCE_INLINE void dump(const char* tag) const { |
| 455 #if DEBUG_DICT |
| 456 DUMP_WORD_AND_SCORE(tag); |
| 457 #if DEBUG_DUMP_ERROR |
| 458 mProfiler.dump(); |
| 459 #endif |
| 460 #endif |
| 461 } |
| 462 |
| 463 AK_FORCE_INLINE bool compare(const DicNode* right) const { |
| 464 // Promote exact matches to prevent them from being pruned. |
| 465 const bool leftExactMatch = |
| 466 ErrorTypeUtils::isExactMatch(getContainedErrorTypes()); |
| 467 const bool rightExactMatch = |
| 468 ErrorTypeUtils::isExactMatch(right->getContainedErrorTypes()); |
| 469 if (leftExactMatch != rightExactMatch) { |
| 470 return leftExactMatch; |
| 471 } |
| 472 const float diff = right->getNormalizedCompoundDistance() - |
| 473 getNormalizedCompoundDistance(); |
| 474 static const float MIN_DIFF = 0.000001f; |
| 475 if (diff > MIN_DIFF) { |
| 476 return true; |
| 477 } else if (diff < -MIN_DIFF) { |
| 478 return false; |
| 479 } |
| 480 const int depth = getNodeCodePointCount(); |
| 481 const int depthDiff = right->getNodeCodePointCount() - depth; |
| 482 if (depthDiff != 0) { |
| 483 return depthDiff > 0; |
| 484 } |
| 485 for (int i = 0; i < depth; ++i) { |
| 486 const int codePoint = |
| 487 mDicNodeState.mDicNodeStateOutput.getCurrentWordCodePointAt(i); |
| 488 const int rightCodePoint = |
| 489 right->mDicNodeState.mDicNodeStateOutput.getCurrentWordCodePointAt(i); |
| 490 if (codePoint != rightCodePoint) { |
| 491 return rightCodePoint > codePoint; |
| 492 } |
| 493 } |
| 494 // Compare pointer values here for stable comparison |
| 495 return this > right; |
| 496 } |
| 497 |
| 498 private: |
| 499 DicNodeProperties mDicNodeProperties; |
| 500 DicNodeState mDicNodeState; |
| 501 // TODO: Remove |
| 502 bool mIsCachedForNextSuggestion; |
| 503 |
| 504 AK_FORCE_INLINE int getTotalInputIndex() const { |
| 505 int index = 0; |
| 506 for (int i = 0; i < MAX_POINTER_COUNT_G; i++) { |
| 507 index += mDicNodeState.mDicNodeStateInput.getInputIndex(i); |
| 508 } |
| 509 return index; |
| 510 } |
| 511 |
| 512 // Caveat: Must not be called outside Weighting |
| 513 // This restriction is guaranteed by "friend" |
| 514 AK_FORCE_INLINE void addCost(const float spatialCost, |
| 515 const float languageCost, |
| 516 const bool doNormalization, |
| 517 const int inputSize, |
| 518 const ErrorTypeUtils::ErrorType errorType) { |
| 519 if (DEBUG_GEO_FULL) { |
| 520 LOGI_SHOW_ADD_COST_PROP; |
| 521 } |
| 522 mDicNodeState.mDicNodeStateScoring.addCost(spatialCost, languageCost, |
| 523 doNormalization, inputSize, |
| 524 getTotalInputIndex(), errorType); |
| 525 } |
| 526 |
| 527 // Saves the current normalized compound distance for space-aware gestures. |
| 528 // See getNormalizedCompoundDistanceAfterFirstWord for details. |
| 529 AK_FORCE_INLINE void saveNormalizedCompoundDistanceAfterFirstWordIfNoneYet() { |
| 530 mDicNodeState.mDicNodeStateScoring |
| 531 .saveNormalizedCompoundDistanceAfterFirstWordIfNoneYet(); |
| 532 } |
| 533 |
| 534 // Caveat: Must not be called outside Weighting |
| 535 // This restriction is guaranteed by "friend" |
| 536 AK_FORCE_INLINE void forwardInputIndex( |
| 537 const int pointerId, |
| 538 const int count, |
| 539 const bool overwritesPrevCodePointByNodeCodePoint) { |
| 540 if (count == 0) { |
| 541 return; |
| 542 } |
| 543 mDicNodeState.mDicNodeStateInput.forwardInputIndex(pointerId, count); |
| 544 if (overwritesPrevCodePointByNodeCodePoint) { |
| 545 mDicNodeState.mDicNodeStateInput.setPrevCodePoint(0, getNodeCodePoint()); |
| 546 } |
| 547 } |
| 548 |
| 549 AK_FORCE_INLINE void updateInputIndexG( |
| 550 const DicNode_InputStateG* const inputStateG) { |
| 551 if (mDicNodeState.mDicNodeStateOutput.getPrevWordCount() == 1 && |
| 552 isFirstLetter()) { |
| 553 mDicNodeState.mDicNodeStateOutput.setSecondWordFirstInputIndex( |
| 554 inputStateG->mInputIndex); |
| 555 } |
| 556 mDicNodeState.mDicNodeStateInput.updateInputIndexG( |
| 557 inputStateG->mPointerId, inputStateG->mInputIndex, |
| 558 inputStateG->mPrevCodePoint, inputStateG->mTerminalDiffCost, |
| 559 inputStateG->mRawLength); |
| 560 mDicNodeState.mDicNodeStateScoring.addRawLength(inputStateG->mRawLength); |
| 561 mDicNodeState.mDicNodeStateScoring.setDoubleLetterLevel( |
| 562 inputStateG->mDoubleLetterLevel); |
| 563 } |
| 564 }; |
| 565 } // namespace latinime |
| 566 #endif // LATINIME_DIC_NODE_H |
OLD | NEW |