@@ -182,9 +182,7 @@ int EntropyUtils::normalizeFrequencies(uint freqs[], uint alphabet[], int length
182182 const int64 prod = int64 (scaledFreq) * int64 (totalFreq);
183183 const int64 errCeiling = prod + int64 (totalFreq) - sf;
184184 const int64 errFloor = sf - prod;
185-
186- if (errCeiling < errFloor)
187- scaledFreq++;
185+ scaledFreq += (errCeiling < errFloor ? 1 : 0 );
188186 }
189187
190188 alphabet[alphabetSize++] = i;
@@ -209,70 +207,53 @@ int EntropyUtils::normalizeFrequencies(uint freqs[], uint alphabet[], int length
209207 return alphabetSize;
210208
211209 int delta = int (sumScaledFreq - scale);
210+ const int errThr = int (freqs[idxMax]) >> 4 ;
212211
213- if (abs (delta) * 16 <= int (freqs[idxMax]) ) {
212+ if (abs (delta) <= errThr ) {
214213 // Fast path (small error): just adjust the max frequency
215214 freqs[idxMax] -= delta;
216215 return alphabetSize;
217216 }
218217
219218 if (delta < 0 ) {
220- sumScaledFreq += (freqs[idxMax] >> 4 ) ;
221- freqs[idxMax] += (freqs[idxMax] >> 4 );
219+ delta += errThr ;
220+ freqs[idxMax] += uint (errThr );
222221 }
223222 else {
224- sumScaledFreq -= (freqs[idxMax] >> 4 ) ;
225- freqs[idxMax] -= (freqs[idxMax] >> 4 );
223+ delta -= errThr ;
224+ freqs[idxMax] -= uint (errThr );
226225 }
227226
228227 // Slow path: spread error across frequencies
229- deque<FreqSortData> queue;
230-
231- // Create sorted queue of present symbols
232- for (int i = 0 ; i < alphabetSize; i++) {
233- if (freqs[alphabet[i]] <= 2 ) // Do not distort small frequencies
234- continue ;
228+ const int inc = (delta < 0 ) ? 1 : -1 ;
229+ delta = abs (delta);
230+ int round = 0 ;
235231
236- queue. push_back ( FreqSortData (&freqs[alphabet[i]], uint8 (alphabet[i])));
237- }
232+ while ((++round < 6 ) && (delta > 0 )) {
233+ int adjustments = 0 ;
238234
239- const int inc = (delta > 0 ) ? - 1 : 1 ;
240- sort (queue. begin (), queue. end (), FreqDataComparator ()) ;
235+ for ( int i = 0 ; i < alphabetSize; i++) {
236+ const int idx = alphabet[i] ;
241237
242- while (queue.size () != 0 ) {
243- // Remove next symbol
244- #if __cplusplus >= 201103L
245- FreqSortData fsd = std::move (queue.front ()); // qualified move (std::) to avoid warning
246- #else
247- FreqSortData fsd = queue.front ();
248- #endif
249- queue.pop_front ();
238+ // Skip small frequencies to avoid big distortion
239+ // Do not zero out frequencies
240+ if (freqs[idx] <= 2 )
241+ continue ;
250242
251- // Do not zero out any frequency
252- if (int (*fsd._freq ) == -inc)
253- continue ;
243+ // Adjust frequency
244+ freqs[idx] += inc;
245+ adjustments++;
246+ delta--;
254247
255- // Distort frequency and re-enqueue
256- *fsd._freq += inc;
257- sumScaledFreq += inc;
258- queue.push_back (fsd);
248+ if (delta == 0 )
249+ break ;
250+ }
259251
260- if (sumScaledFreq == scale )
252+ if (adjustments == 0 )
261253 break ;
262254 }
263255
264- if (sumScaledFreq != scale) {
265- for (int i = 0 ; i < alphabetSize; i++) {
266- if (int (freqs[alphabet[i]]) != -inc) {
267- freqs[alphabet[i]] += inc;
268- sumScaledFreq += inc;
269-
270- if (sumScaledFreq == scale)
271- break ;
272- }
273- }
274- }
275-
256+ freqs[idxMax] -= delta;
276257 return alphabetSize;
277258}
278259
0 commit comments