• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2011 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_WORDS_PRIORITY_QUEUE_H
18 #define LATINIME_WORDS_PRIORITY_QUEUE_H
19 
20 #include <cstring> // for memcpy()
21 #include <iostream>
22 #include <queue>
23 #include "defines.h"
24 
25 namespace latinime {
26 
27 class WordsPriorityQueue {
28  public:
29     class SuggestedWord {
30     public:
31         int mScore;
32         unsigned short mWord[MAX_WORD_LENGTH_INTERNAL];
33         int mWordLength;
34         bool mUsed;
35 
setParams(int score,unsigned short * word,int wordLength)36         void setParams(int score, unsigned short* word, int wordLength) {
37             mScore = score;
38             mWordLength = wordLength;
39             memcpy(mWord, word, sizeof(unsigned short) * wordLength);
40             mUsed = true;
41         }
42     };
43 
WordsPriorityQueue(int maxWords,int maxWordLength)44     WordsPriorityQueue(int maxWords, int maxWordLength) :
45             MAX_WORDS((unsigned int) maxWords), MAX_WORD_LENGTH(
46                     (unsigned int) maxWordLength) {
47         mSuggestedWords = new SuggestedWord[maxWordLength];
48         for (int i = 0; i < maxWordLength; ++i) {
49             mSuggestedWords[i].mUsed = false;
50         }
51         mHighestSuggestedWord = 0;
52     }
53 
~WordsPriorityQueue()54     ~WordsPriorityQueue() {
55         delete[] mSuggestedWords;
56     }
57 
push(int score,unsigned short * word,int wordLength)58     void push(int score, unsigned short* word, int wordLength) {
59         SuggestedWord* sw = 0;
60         if (mSuggestions.size() >= MAX_WORDS) {
61             sw = mSuggestions.top();
62             const int minScore = sw->mScore;
63             if (minScore >= score) {
64                 return;
65             } else {
66                 sw->mUsed = false;
67                 mSuggestions.pop();
68             }
69         }
70         if (sw == 0) {
71             sw = getFreeSuggestedWord(score, word, wordLength);
72         } else {
73             sw->setParams(score, word, wordLength);
74         }
75         if (sw == 0) {
76             AKLOGE("SuggestedWord is accidentally null.");
77             return;
78         }
79         if (DEBUG_WORDS_PRIORITY_QUEUE) {
80             AKLOGI("Push word. %d, %d", score, wordLength);
81             DUMP_WORD(word, wordLength);
82         }
83         mSuggestions.push(sw);
84         if (!mHighestSuggestedWord || mHighestSuggestedWord->mScore < sw->mScore) {
85             mHighestSuggestedWord = sw;
86         }
87     }
88 
top()89     SuggestedWord* top() {
90         if (mSuggestions.empty()) return 0;
91         SuggestedWord* sw = mSuggestions.top();
92         return sw;
93     }
94 
outputSuggestions(const unsigned short * before,const int beforeLength,int * frequencies,unsigned short * outputChars)95     int outputSuggestions(const unsigned short* before, const int beforeLength,
96             int *frequencies, unsigned short *outputChars) {
97         mHighestSuggestedWord = 0;
98         const unsigned int size = min(
99               MAX_WORDS, static_cast<unsigned int>(mSuggestions.size()));
100         SuggestedWord* swBuffer[size];
101         int index = size - 1;
102         while (!mSuggestions.empty() && index >= 0) {
103             SuggestedWord* sw = mSuggestions.top();
104             if (DEBUG_WORDS_PRIORITY_QUEUE) {
105                 AKLOGI("dump word. %d", sw->mScore);
106                 DUMP_WORD(sw->mWord, sw->mWordLength);
107             }
108             swBuffer[index] = sw;
109             mSuggestions.pop();
110             --index;
111         }
112         if (size >= 2) {
113             SuggestedWord* nsMaxSw = 0;
114             unsigned int maxIndex = 0;
115             float maxNs = 0;
116             for (unsigned int i = 0; i < size; ++i) {
117                 SuggestedWord* tempSw = swBuffer[i];
118                 if (!tempSw) {
119                     continue;
120                 }
121                 const float tempNs = getNormalizedScore(tempSw, before, beforeLength, 0, 0, 0);
122                 if (tempNs >= maxNs) {
123                     maxNs = tempNs;
124                     maxIndex = i;
125                     nsMaxSw = tempSw;
126                 }
127             }
128             if (maxIndex > 0 && nsMaxSw) {
129                 memmove(&swBuffer[1], &swBuffer[0], maxIndex * sizeof(SuggestedWord*));
130                 swBuffer[0] = nsMaxSw;
131             }
132         }
133         for (unsigned int i = 0; i < size; ++i) {
134             SuggestedWord* sw = swBuffer[i];
135             if (!sw) {
136                 AKLOGE("SuggestedWord is null %d", i);
137                 continue;
138             }
139             const unsigned int wordLength = sw->mWordLength;
140             char* targetAdr = (char*) outputChars + i * MAX_WORD_LENGTH * sizeof(short);
141             frequencies[i] = sw->mScore;
142             memcpy(targetAdr, sw->mWord, (wordLength) * sizeof(short));
143             if (wordLength < MAX_WORD_LENGTH) {
144                 ((unsigned short*) targetAdr)[wordLength] = 0;
145             }
146             sw->mUsed = false;
147         }
148         return size;
149     }
150 
size()151     int size() const {
152         return mSuggestions.size();
153     }
154 
clear()155     void clear() {
156         mHighestSuggestedWord = 0;
157         while (!mSuggestions.empty()) {
158             SuggestedWord* sw = mSuggestions.top();
159             if (DEBUG_WORDS_PRIORITY_QUEUE) {
160                 AKLOGI("Clear word. %d", sw->mScore);
161                 DUMP_WORD(sw->mWord, sw->mWordLength);
162             }
163             sw->mUsed = false;
164             mSuggestions.pop();
165         }
166     }
167 
dumpTopWord()168     void dumpTopWord() {
169         if (size() <= 0) {
170             return;
171         }
172         DUMP_WORD(mHighestSuggestedWord->mWord, mHighestSuggestedWord->mWordLength);
173     }
174 
getHighestNormalizedScore(const unsigned short * before,const int beforeLength,unsigned short ** outWord,int * outScore,int * outLength)175     float getHighestNormalizedScore(const unsigned short* before, const int beforeLength,
176             unsigned short** outWord, int *outScore, int *outLength) {
177         if (!mHighestSuggestedWord) {
178             return 0.0;
179         }
180         return getNormalizedScore(
181                 mHighestSuggestedWord, before, beforeLength, outWord, outScore, outLength);
182     }
183 
184  private:
185     struct wordComparator {
operatorwordComparator186         bool operator ()(SuggestedWord * left, SuggestedWord * right) {
187             return left->mScore > right->mScore;
188         }
189     };
190 
getFreeSuggestedWord(int score,unsigned short * word,int wordLength)191     SuggestedWord* getFreeSuggestedWord(int score, unsigned short* word,
192             int wordLength) {
193         for (unsigned int i = 0; i < MAX_WORD_LENGTH; ++i) {
194             if (!mSuggestedWords[i].mUsed) {
195                 mSuggestedWords[i].setParams(score, word, wordLength);
196                 return &mSuggestedWords[i];
197             }
198         }
199         return 0;
200     }
201 
getNormalizedScore(SuggestedWord * sw,const unsigned short * before,const int beforeLength,unsigned short ** outWord,int * outScore,int * outLength)202     static float getNormalizedScore(SuggestedWord* sw, const unsigned short* before,
203             const int beforeLength, unsigned short** outWord, int *outScore, int *outLength) {
204         const int score = sw->mScore;
205         unsigned short* word = sw->mWord;
206         const int wordLength = sw->mWordLength;
207         if (outScore) {
208             *outScore = score;
209         }
210         if (outWord) {
211             *outWord = word;
212         }
213         if (outLength) {
214             *outLength = wordLength;
215         }
216         return Correction::RankingAlgorithm::calcNormalizedScore(
217                 before, beforeLength, word, wordLength, score);
218     }
219 
220     typedef std::priority_queue<SuggestedWord*, std::vector<SuggestedWord*>,
221             wordComparator> Suggestions;
222     Suggestions mSuggestions;
223     const unsigned int MAX_WORDS;
224     const unsigned int MAX_WORD_LENGTH;
225     SuggestedWord* mSuggestedWords;
226     SuggestedWord* mHighestSuggestedWord;
227 };
228 }
229 
230 #endif // LATINIME_WORDS_PRIORITY_QUEUE_H
231