void Ver4BigramListPolicy::getNextBigram(int *const outBigramPos, int *const outProbability, bool *const outHasNext, int *const bigramEntryPos) const { const BigramEntry bigramEntry = mBigramDictContent->getBigramEntryAndAdvancePosition(bigramEntryPos); if (outBigramPos) { // Lookup target PtNode position. *outBigramPos = mTerminalPositionLookupTable->getTerminalPtNodePosition( bigramEntry.getTargetTerminalId()); } if (outProbability) { if (bigramEntry.hasHistoricalInfo()) { *outProbability = ForgettingCurveUtils::decodeProbability(bigramEntry.getHistoricalInfo(), mHeaderPolicy); } else { *outProbability = bigramEntry.getProbability(); } } if (outHasNext) { *outHasNext = bigramEntry.hasNext(); } }
bool Ver4BigramListPolicy::addNewEntry(const int terminalId, const int newTargetTerminalId, const BigramProperty *const bigramProperty, bool *const outAddedNewEntry) { // 1. The word has no bigrams yet. // 2. The word has bigrams, and there is the target in the list. // 3. The word has bigrams, and there is an invalid entry that can be reclaimed. // 4. The word has bigrams. We have to append new bigram entry to the list. // 5. Same as 4, but the list is the last entry of the content file. if (outAddedNewEntry) { *outAddedNewEntry = false; } const int bigramListPos = mBigramDictContent->getBigramListHeadPos(terminalId); if (bigramListPos == NOT_A_DICT_POS) { // Case 1. PtNode that doesn't have a bigram list. // Create new bigram list. if (!mBigramDictContent->createNewBigramList(terminalId)) { return false; } const BigramEntry newBigramEntry(false /* hasNext */, NOT_A_PROBABILITY, newTargetTerminalId); const BigramEntry bigramEntryToWrite = createUpdatedBigramEntryFrom(&newBigramEntry, bigramProperty); // Write an entry. int writingPos = mBigramDictContent->getBigramListHeadPos(terminalId); if (!mBigramDictContent->writeBigramEntryAndAdvancePosition(&bigramEntryToWrite, &writingPos)) { AKLOGE("Cannot write bigram entry. pos: %d.", writingPos); return false; } if (!mBigramDictContent->writeTerminator(writingPos)) { AKLOGE("Cannot write bigram list terminator. pos: %d.", writingPos); return false; } if (outAddedNewEntry) { *outAddedNewEntry = true; } return true; } int tailEntryPos = NOT_A_DICT_POS; const int entryPosToUpdate = getEntryPosToUpdate(newTargetTerminalId, bigramListPos, &tailEntryPos); if (entryPosToUpdate == NOT_A_DICT_POS) { // Case 4, 5. Add new entry to the bigram list. const int contentTailPos = mBigramDictContent->getContentTailPos(); // If the tail entry is at the tail of content buffer, the new entry can be written without // link (Case 5). const bool canAppendEntry = contentTailPos == tailEntryPos + mBigramDictContent->getBigramEntrySize(); const int newEntryPos = canAppendEntry ? tailEntryPos : contentTailPos; int writingPos = newEntryPos; // Write new entry at the tail position of the bigram content. const BigramEntry newBigramEntry(false /* hasNext */, NOT_A_PROBABILITY, newTargetTerminalId); const BigramEntry bigramEntryToWrite = createUpdatedBigramEntryFrom( &newBigramEntry, bigramProperty); if (!mBigramDictContent->writeBigramEntryAndAdvancePosition(&bigramEntryToWrite, &writingPos)) { AKLOGE("Cannot write bigram entry. pos: %d.", writingPos); return false; } if (!mBigramDictContent->writeTerminator(writingPos)) { AKLOGE("Cannot write bigram list terminator. pos: %d.", writingPos); return false; } if (!canAppendEntry) { // Update link of the current tail entry. if (!mBigramDictContent->writeLink(newEntryPos, tailEntryPos)) { AKLOGE("Cannot update bigram entry link. pos: %d, linked entry pos: %d.", tailEntryPos, newEntryPos); return false; } } if (outAddedNewEntry) { *outAddedNewEntry = true; } return true; } // Case 2. Overwrite the existing entry. Case 3. Reclaim and reuse the existing invalid entry. const BigramEntry originalBigramEntry = mBigramDictContent->getBigramEntry(entryPosToUpdate); if (!originalBigramEntry.isValid()) { // Case 3. Reuse the existing invalid entry. outAddedNewEntry is false when an existing // entry is updated. if (outAddedNewEntry) { *outAddedNewEntry = true; } } const BigramEntry updatedBigramEntry = originalBigramEntry.updateTargetTerminalIdAndGetEntry(newTargetTerminalId); const BigramEntry bigramEntryToWrite = createUpdatedBigramEntryFrom( &updatedBigramEntry, bigramProperty); return mBigramDictContent->writeBigramEntry(&bigramEntryToWrite, entryPosToUpdate); }
bool Ver4BigramListPolicy::addNewEntry(const int terminalId, const int newTargetTerminalId, const BigramProperty *const bigramProperty, bool *const outAddedNewEntry) { // 1. The word has no bigrams yet. // 2. The word has bigrams, and there is the target in the list. // 3. The word has bigrams, and there is an invalid entry that can be reclaimed. // 4. The word has bigrams. We have to append new bigram entry to the list. // 5. Same as 4, but the list is the last entry of the content file. if (outAddedNewEntry) { *outAddedNewEntry = false; } const int bigramListPos = mBigramDictContent->getBigramListHeadPos(terminalId); if (bigramListPos == NOT_A_DICT_POS) { // Case 1. PtNode that doesn't have a bigram list. // Create new bigram list. if (!mBigramDictContent->createNewBigramList(terminalId)) { return false; } const BigramEntry newBigramEntry(false /* hasNext */, NOT_A_PROBABILITY, newTargetTerminalId); const BigramEntry bigramEntryToWrite = createUpdatedBigramEntryFrom(&newBigramEntry, bigramProperty); // Write an entry. const int writingPos = mBigramDictContent->getBigramListHeadPos(terminalId); if (!mBigramDictContent->writeBigramEntry(&bigramEntryToWrite, writingPos)) { return false; } if (outAddedNewEntry) { *outAddedNewEntry = true; } return true; } int tailEntryPos = NOT_A_DICT_POS; const int entryPosToUpdate = getEntryPosToUpdate(newTargetTerminalId, bigramListPos, &tailEntryPos); if (tailEntryPos != NOT_A_DICT_POS || entryPosToUpdate == NOT_A_DICT_POS) { // Case 4, 5. // Add new entry to the bigram list. if (tailEntryPos == NOT_A_DICT_POS) { // Case 4. Create new bigram list. if (!mBigramDictContent->createNewBigramList(terminalId)) { return false; } const int destPos = mBigramDictContent->getBigramListHeadPos(terminalId); // Copy existing bigram list. if (!mBigramDictContent->copyBigramList(bigramListPos, destPos, &tailEntryPos)) { return false; } } // Write new entry at the tail position of the bigram content. const BigramEntry newBigramEntry(false /* hasNext */, NOT_A_PROBABILITY, newTargetTerminalId); const BigramEntry bigramEntryToWrite = createUpdatedBigramEntryFrom( &newBigramEntry, bigramProperty); if (!mBigramDictContent->writeBigramEntryAtTail(&bigramEntryToWrite)) { return false; } // Update has next flag of the tail entry. if (!updateHasNextFlag(true /* hasNext */, tailEntryPos)) { return false; } if (outAddedNewEntry) { *outAddedNewEntry = true; } return true; } // Case 2. Overwrite the existing entry. Case 3. Reclaim and reuse the existing invalid entry. const BigramEntry originalBigramEntry = mBigramDictContent->getBigramEntry(entryPosToUpdate); if (!originalBigramEntry.isValid()) { // Case 3. Reuse the existing invalid entry. outAddedNewEntry is false when an existing // entry is updated. if (outAddedNewEntry) { *outAddedNewEntry = true; } } const BigramEntry updatedBigramEntry = originalBigramEntry.updateTargetTerminalIdAndGetEntry(newTargetTerminalId); const BigramEntry bigramEntryToWrite = createUpdatedBigramEntryFrom( &updatedBigramEntry, bigramProperty); return mBigramDictContent->writeBigramEntry(&bigramEntryToWrite, entryPosToUpdate); }
bool Ver4BigramListPolicy::updateHasNextFlag(const bool hasNext, const int bigramEntryPos) { const BigramEntry bigramEntry = mBigramDictContent->getBigramEntry(bigramEntryPos); const BigramEntry updatedBigramEntry = bigramEntry.updateHasNextAndGetEntry(hasNext); return mBigramDictContent->writeBigramEntry(&updatedBigramEntry, bigramEntryPos); }