31 - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy |
31 - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy |
32 - Public forum : https://groups.google.com/forum/#!forum/lz4c |
32 - Public forum : https://groups.google.com/forum/#!forum/lz4c |
33 ****************************************************************** */ |
33 ****************************************************************** */ |
34 |
34 |
35 /* ************************************************************** |
35 /* ************************************************************** |
36 * Compiler specifics |
|
37 ****************************************************************/ |
|
38 #ifdef _MSC_VER /* Visual Studio */ |
|
39 # define FORCE_INLINE static __forceinline |
|
40 # include <intrin.h> /* For Visual 2005 */ |
|
41 # pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */ |
|
42 # pragma warning(disable : 4214) /* disable: C4214: non-int bitfields */ |
|
43 #else |
|
44 # if defined (__cplusplus) || defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */ |
|
45 # ifdef __GNUC__ |
|
46 # define FORCE_INLINE static inline __attribute__((always_inline)) |
|
47 # else |
|
48 # define FORCE_INLINE static inline |
|
49 # endif |
|
50 # else |
|
51 # define FORCE_INLINE static |
|
52 # endif /* __STDC_VERSION__ */ |
|
53 #endif |
|
54 |
|
55 |
|
56 /* ************************************************************** |
|
57 * Includes |
36 * Includes |
58 ****************************************************************/ |
37 ****************************************************************/ |
59 #include <stdlib.h> /* malloc, free, qsort */ |
38 #include <stdlib.h> /* malloc, free, qsort */ |
60 #include <string.h> /* memcpy, memset */ |
39 #include <string.h> /* memcpy, memset */ |
61 #include <stdio.h> /* printf (debug) */ |
40 #include <stdio.h> /* printf (debug) */ |
62 #include "bitstream.h" |
41 #include "bitstream.h" |
|
42 #include "compiler.h" |
63 #define FSE_STATIC_LINKING_ONLY |
43 #define FSE_STATIC_LINKING_ONLY |
64 #include "fse.h" |
44 #include "fse.h" |
|
45 #include "error_private.h" |
65 |
46 |
66 |
47 |
67 /* ************************************************************** |
48 /* ************************************************************** |
68 * Error Management |
49 * Error Management |
69 ****************************************************************/ |
50 ****************************************************************/ |
|
51 #define FSE_isError ERR_isError |
70 #define FSE_STATIC_ASSERT(c) { enum { FSE_static_assert = 1/(int)(!!(c)) }; } /* use only *after* variable declarations */ |
52 #define FSE_STATIC_ASSERT(c) { enum { FSE_static_assert = 1/(int)(!!(c)) }; } /* use only *after* variable declarations */ |
71 |
53 |
72 |
54 |
73 /* ************************************************************** |
55 /* ************************************************************** |
74 * Templates |
56 * Templates |
198 size_t FSE_NCountWriteBound(unsigned maxSymbolValue, unsigned tableLog) |
180 size_t FSE_NCountWriteBound(unsigned maxSymbolValue, unsigned tableLog) |
199 { |
181 { |
200 size_t const maxHeaderSize = (((maxSymbolValue+1) * tableLog) >> 3) + 3; |
182 size_t const maxHeaderSize = (((maxSymbolValue+1) * tableLog) >> 3) + 3; |
201 return maxSymbolValue ? maxHeaderSize : FSE_NCOUNTBOUND; /* maxSymbolValue==0 ? use default */ |
183 return maxSymbolValue ? maxHeaderSize : FSE_NCOUNTBOUND; /* maxSymbolValue==0 ? use default */ |
202 } |
184 } |
203 |
|
204 static short FSE_abs(short a) { return (short)(a<0 ? -a : a); } |
|
205 |
185 |
206 static size_t FSE_writeNCount_generic (void* header, size_t headerBufferSize, |
186 static size_t FSE_writeNCount_generic (void* header, size_t headerBufferSize, |
207 const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog, |
187 const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog, |
208 unsigned writeIsSafe) |
188 unsigned writeIsSafe) |
209 { |
189 { |
256 out[1] = (BYTE)(bitStream>>8); |
236 out[1] = (BYTE)(bitStream>>8); |
257 out += 2; |
237 out += 2; |
258 bitStream >>= 16; |
238 bitStream >>= 16; |
259 bitCount -= 16; |
239 bitCount -= 16; |
260 } } |
240 } } |
261 { short count = normalizedCounter[charnum++]; |
241 { int count = normalizedCounter[charnum++]; |
262 const short max = (short)((2*threshold-1)-remaining); |
242 int const max = (2*threshold-1)-remaining; |
263 remaining -= FSE_abs(count); |
243 remaining -= count < 0 ? -count : count; |
264 if (remaining<1) return ERROR(GENERIC); |
|
265 count++; /* +1 for extra accuracy */ |
244 count++; /* +1 for extra accuracy */ |
266 if (count>=threshold) count += max; /* [0..max[ [max..threshold[ (...) [threshold+max 2*threshold[ */ |
245 if (count>=threshold) count += max; /* [0..max[ [max..threshold[ (...) [threshold+max 2*threshold[ */ |
267 bitStream += count << bitCount; |
246 bitStream += count << bitCount; |
268 bitCount += nbBits; |
247 bitCount += nbBits; |
269 bitCount -= (count<max); |
248 bitCount -= (count<max); |
270 previous0 = (count==1); |
249 previous0 = (count==1); |
271 while (remaining<threshold) nbBits--, threshold>>=1; |
250 if (remaining<1) return ERROR(GENERIC); |
|
251 while (remaining<threshold) { nbBits--; threshold>>=1; } |
272 } |
252 } |
273 if (bitCount>16) { |
253 if (bitCount>16) { |
274 if ((!writeIsSafe) && (out > oend - 2)) return ERROR(dstSize_tooSmall); /* Buffer overflow */ |
254 if ((!writeIsSafe) && (out > oend - 2)) return ERROR(dstSize_tooSmall); /* Buffer overflow */ |
275 out[0] = (BYTE)bitStream; |
255 out[0] = (BYTE)bitStream; |
276 out[1] = (BYTE)(bitStream>>8); |
256 out[1] = (BYTE)(bitStream>>8); |
291 } |
271 } |
292 |
272 |
293 |
273 |
294 size_t FSE_writeNCount (void* buffer, size_t bufferSize, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog) |
274 size_t FSE_writeNCount (void* buffer, size_t bufferSize, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog) |
295 { |
275 { |
296 if (tableLog > FSE_MAX_TABLELOG) return ERROR(GENERIC); /* Unsupported */ |
276 if (tableLog > FSE_MAX_TABLELOG) return ERROR(tableLog_tooLarge); /* Unsupported */ |
297 if (tableLog < FSE_MIN_TABLELOG) return ERROR(GENERIC); /* Unsupported */ |
277 if (tableLog < FSE_MIN_TABLELOG) return ERROR(GENERIC); /* Unsupported */ |
298 |
278 |
299 if (bufferSize < FSE_NCountWriteBound(maxSymbolValue, tableLog)) |
279 if (bufferSize < FSE_NCountWriteBound(maxSymbolValue, tableLog)) |
300 return FSE_writeNCount_generic(buffer, bufferSize, normalizedCounter, maxSymbolValue, tableLog, 0); |
280 return FSE_writeNCount_generic(buffer, bufferSize, normalizedCounter, maxSymbolValue, tableLog, 0); |
301 |
281 |
310 /*! FSE_count_simple |
290 /*! FSE_count_simple |
311 This function counts byte values within `src`, and store the histogram into table `count`. |
291 This function counts byte values within `src`, and store the histogram into table `count`. |
312 It doesn't use any additional memory. |
292 It doesn't use any additional memory. |
313 But this function is unsafe : it doesn't check that all values within `src` can fit into `count`. |
293 But this function is unsafe : it doesn't check that all values within `src` can fit into `count`. |
314 For this reason, prefer using a table `count` with 256 elements. |
294 For this reason, prefer using a table `count` with 256 elements. |
315 @return : count of most numerous element |
295 @return : count of most numerous element. |
316 */ |
296 */ |
317 size_t FSE_count_simple(unsigned* count, unsigned* maxSymbolValuePtr, |
297 size_t FSE_count_simple(unsigned* count, unsigned* maxSymbolValuePtr, |
318 const void* src, size_t srcSize) |
298 const void* src, size_t srcSize) |
319 { |
299 { |
320 const BYTE* ip = (const BYTE*)src; |
300 const BYTE* ip = (const BYTE*)src; |
323 unsigned max=0; |
303 unsigned max=0; |
324 |
304 |
325 memset(count, 0, (maxSymbolValue+1)*sizeof(*count)); |
305 memset(count, 0, (maxSymbolValue+1)*sizeof(*count)); |
326 if (srcSize==0) { *maxSymbolValuePtr = 0; return 0; } |
306 if (srcSize==0) { *maxSymbolValuePtr = 0; return 0; } |
327 |
307 |
328 while (ip<end) count[*ip++]++; |
308 while (ip<end) { |
|
309 assert(*ip <= maxSymbolValue); |
|
310 count[*ip++]++; |
|
311 } |
329 |
312 |
330 while (!count[maxSymbolValue]) maxSymbolValue--; |
313 while (!count[maxSymbolValue]) maxSymbolValue--; |
331 *maxSymbolValuePtr = maxSymbolValue; |
314 *maxSymbolValuePtr = maxSymbolValue; |
332 |
315 |
333 { U32 s; for (s=0; s<=maxSymbolValue; s++) if (count[s] > max) max = count[s]; } |
316 { U32 s; for (s=0; s<=maxSymbolValue; s++) if (count[s] > max) max = count[s]; } |
336 } |
319 } |
337 |
320 |
338 |
321 |
339 /* FSE_count_parallel_wksp() : |
322 /* FSE_count_parallel_wksp() : |
340 * Same as FSE_count_parallel(), but using an externally provided scratch buffer. |
323 * Same as FSE_count_parallel(), but using an externally provided scratch buffer. |
341 * `workSpace` size must be a minimum of `1024 * sizeof(unsigned)`` */ |
324 * `workSpace` size must be a minimum of `1024 * sizeof(unsigned)`. |
|
325 * @return : largest histogram frequency, or an error code (notably when histogram would be larger than *maxSymbolValuePtr). */ |
342 static size_t FSE_count_parallel_wksp( |
326 static size_t FSE_count_parallel_wksp( |
343 unsigned* count, unsigned* maxSymbolValuePtr, |
327 unsigned* count, unsigned* maxSymbolValuePtr, |
344 const void* source, size_t sourceSize, |
328 const void* source, size_t sourceSize, |
345 unsigned checkMax, unsigned* const workSpace) |
329 unsigned checkMax, unsigned* const workSpace) |
346 { |
330 { |
351 U32* const Counting1 = workSpace; |
335 U32* const Counting1 = workSpace; |
352 U32* const Counting2 = Counting1 + 256; |
336 U32* const Counting2 = Counting1 + 256; |
353 U32* const Counting3 = Counting2 + 256; |
337 U32* const Counting3 = Counting2 + 256; |
354 U32* const Counting4 = Counting3 + 256; |
338 U32* const Counting4 = Counting3 + 256; |
355 |
339 |
356 memset(Counting1, 0, 4*256*sizeof(unsigned)); |
340 memset(workSpace, 0, 4*256*sizeof(unsigned)); |
357 |
341 |
358 /* safety checks */ |
342 /* safety checks */ |
359 if (!sourceSize) { |
343 if (!sourceSize) { |
360 memset(count, 0, maxSymbolValue + 1); |
344 memset(count, 0, maxSymbolValue + 1); |
361 *maxSymbolValuePtr = 0; |
345 *maxSymbolValuePtr = 0; |
397 U32 s; for (s=255; s>maxSymbolValue; s--) { |
381 U32 s; for (s=255; s>maxSymbolValue; s--) { |
398 Counting1[s] += Counting2[s] + Counting3[s] + Counting4[s]; |
382 Counting1[s] += Counting2[s] + Counting3[s] + Counting4[s]; |
399 if (Counting1[s]) return ERROR(maxSymbolValue_tooSmall); |
383 if (Counting1[s]) return ERROR(maxSymbolValue_tooSmall); |
400 } } |
384 } } |
401 |
385 |
402 { U32 s; for (s=0; s<=maxSymbolValue; s++) { |
386 { U32 s; |
|
387 if (maxSymbolValue > 255) maxSymbolValue = 255; |
|
388 for (s=0; s<=maxSymbolValue; s++) { |
403 count[s] = Counting1[s] + Counting2[s] + Counting3[s] + Counting4[s]; |
389 count[s] = Counting1[s] + Counting2[s] + Counting3[s] + Counting4[s]; |
404 if (count[s] > max) max = count[s]; |
390 if (count[s] > max) max = count[s]; |
405 } } |
391 } } |
406 |
392 |
407 while (!count[maxSymbolValue]) maxSymbolValue--; |
393 while (!count[maxSymbolValue]) maxSymbolValue--; |
411 |
397 |
412 /* FSE_countFast_wksp() : |
398 /* FSE_countFast_wksp() : |
413 * Same as FSE_countFast(), but using an externally provided scratch buffer. |
399 * Same as FSE_countFast(), but using an externally provided scratch buffer. |
414 * `workSpace` size must be table of >= `1024` unsigned */ |
400 * `workSpace` size must be table of >= `1024` unsigned */ |
415 size_t FSE_countFast_wksp(unsigned* count, unsigned* maxSymbolValuePtr, |
401 size_t FSE_countFast_wksp(unsigned* count, unsigned* maxSymbolValuePtr, |
416 const void* source, size_t sourceSize, unsigned* workSpace) |
402 const void* source, size_t sourceSize, |
417 { |
403 unsigned* workSpace) |
418 if (sourceSize < 1500) return FSE_count_simple(count, maxSymbolValuePtr, source, sourceSize); |
404 { |
|
405 if (sourceSize < 1500) /* heuristic threshold */ |
|
406 return FSE_count_simple(count, maxSymbolValuePtr, source, sourceSize); |
419 return FSE_count_parallel_wksp(count, maxSymbolValuePtr, source, sourceSize, 0, workSpace); |
407 return FSE_count_parallel_wksp(count, maxSymbolValuePtr, source, sourceSize, 0, workSpace); |
420 } |
408 } |
421 |
409 |
422 /* fast variant (unsafe : won't check if src contains values beyond count[] limit) */ |
410 /* fast variant (unsafe : won't check if src contains values beyond count[] limit) */ |
423 size_t FSE_countFast(unsigned* count, unsigned* maxSymbolValuePtr, |
411 size_t FSE_countFast(unsigned* count, unsigned* maxSymbolValuePtr, |
476 void FSE_freeCTable (FSE_CTable* ct) { free(ct); } |
464 void FSE_freeCTable (FSE_CTable* ct) { free(ct); } |
477 |
465 |
478 /* provides the minimum logSize to safely represent a distribution */ |
466 /* provides the minimum logSize to safely represent a distribution */ |
479 static unsigned FSE_minTableLog(size_t srcSize, unsigned maxSymbolValue) |
467 static unsigned FSE_minTableLog(size_t srcSize, unsigned maxSymbolValue) |
480 { |
468 { |
481 U32 minBitsSrc = BIT_highbit32((U32)(srcSize - 1)) + 1; |
469 U32 minBitsSrc = BIT_highbit32((U32)(srcSize - 1)) + 1; |
482 U32 minBitsSymbols = BIT_highbit32(maxSymbolValue) + 2; |
470 U32 minBitsSymbols = BIT_highbit32(maxSymbolValue) + 2; |
483 U32 minBits = minBitsSrc < minBitsSymbols ? minBitsSrc : minBitsSymbols; |
471 U32 minBits = minBitsSrc < minBitsSymbols ? minBitsSrc : minBitsSymbols; |
484 return minBits; |
472 assert(srcSize > 1); /* Not supported, RLE should be used instead */ |
|
473 return minBits; |
485 } |
474 } |
486 |
475 |
487 unsigned FSE_optimalTableLog_internal(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue, unsigned minus) |
476 unsigned FSE_optimalTableLog_internal(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue, unsigned minus) |
488 { |
477 { |
489 U32 maxBitsSrc = BIT_highbit32((U32)(srcSize - 1)) - minus; |
478 U32 maxBitsSrc = BIT_highbit32((U32)(srcSize - 1)) - minus; |
490 U32 tableLog = maxTableLog; |
479 U32 tableLog = maxTableLog; |
491 U32 minBits = FSE_minTableLog(srcSize, maxSymbolValue); |
480 U32 minBits = FSE_minTableLog(srcSize, maxSymbolValue); |
|
481 assert(srcSize > 1); /* Not supported, RLE should be used instead */ |
492 if (tableLog==0) tableLog = FSE_DEFAULT_TABLELOG; |
482 if (tableLog==0) tableLog = FSE_DEFAULT_TABLELOG; |
493 if (maxBitsSrc < tableLog) tableLog = maxBitsSrc; /* Accuracy can be reduced */ |
483 if (maxBitsSrc < tableLog) tableLog = maxBitsSrc; /* Accuracy can be reduced */ |
494 if (minBits > tableLog) tableLog = minBits; /* Need a minimum to safely represent all symbol values */ |
484 if (minBits > tableLog) tableLog = minBits; /* Need a minimum to safely represent all symbol values */ |
495 if (tableLog < FSE_MIN_TABLELOG) tableLog = FSE_MIN_TABLELOG; |
485 if (tableLog < FSE_MIN_TABLELOG) tableLog = FSE_MIN_TABLELOG; |
496 if (tableLog > FSE_MAX_TABLELOG) tableLog = FSE_MAX_TABLELOG; |
486 if (tableLog > FSE_MAX_TABLELOG) tableLog = FSE_MAX_TABLELOG; |
497 return tableLog; |
487 return tableLog; |
498 } |
488 } |
499 |
489 |
506 /* Secondary normalization method. |
496 /* Secondary normalization method. |
507 To be used when primary method fails. */ |
497 To be used when primary method fails. */ |
508 |
498 |
509 static size_t FSE_normalizeM2(short* norm, U32 tableLog, const unsigned* count, size_t total, U32 maxSymbolValue) |
499 static size_t FSE_normalizeM2(short* norm, U32 tableLog, const unsigned* count, size_t total, U32 maxSymbolValue) |
510 { |
500 { |
|
501 short const NOT_YET_ASSIGNED = -2; |
511 U32 s; |
502 U32 s; |
512 U32 distributed = 0; |
503 U32 distributed = 0; |
513 U32 ToDistribute; |
504 U32 ToDistribute; |
514 |
505 |
515 /* Init */ |
506 /* Init */ |
531 norm[s] = 1; |
522 norm[s] = 1; |
532 distributed++; |
523 distributed++; |
533 total -= count[s]; |
524 total -= count[s]; |
534 continue; |
525 continue; |
535 } |
526 } |
536 norm[s]=-2; |
527 |
|
528 norm[s]=NOT_YET_ASSIGNED; |
537 } |
529 } |
538 ToDistribute = (1 << tableLog) - distributed; |
530 ToDistribute = (1 << tableLog) - distributed; |
539 |
531 |
540 if ((total / ToDistribute) > lowOne) { |
532 if ((total / ToDistribute) > lowOne) { |
541 /* risk of rounding to zero */ |
533 /* risk of rounding to zero */ |
542 lowOne = (U32)((total * 3) / (ToDistribute * 2)); |
534 lowOne = (U32)((total * 3) / (ToDistribute * 2)); |
543 for (s=0; s<=maxSymbolValue; s++) { |
535 for (s=0; s<=maxSymbolValue; s++) { |
544 if ((norm[s] == -2) && (count[s] <= lowOne)) { |
536 if ((norm[s] == NOT_YET_ASSIGNED) && (count[s] <= lowOne)) { |
545 norm[s] = 1; |
537 norm[s] = 1; |
546 distributed++; |
538 distributed++; |
547 total -= count[s]; |
539 total -= count[s]; |
548 continue; |
540 continue; |
549 } } |
541 } } |
554 /* all values are pretty poor; |
546 /* all values are pretty poor; |
555 probably incompressible data (should have already been detected); |
547 probably incompressible data (should have already been detected); |
556 find max, then give all remaining points to max */ |
548 find max, then give all remaining points to max */ |
557 U32 maxV = 0, maxC = 0; |
549 U32 maxV = 0, maxC = 0; |
558 for (s=0; s<=maxSymbolValue; s++) |
550 for (s=0; s<=maxSymbolValue; s++) |
559 if (count[s] > maxC) maxV=s, maxC=count[s]; |
551 if (count[s] > maxC) { maxV=s; maxC=count[s]; } |
560 norm[maxV] += (short)ToDistribute; |
552 norm[maxV] += (short)ToDistribute; |
|
553 return 0; |
|
554 } |
|
555 |
|
556 if (total == 0) { |
|
557 /* all of the symbols were low enough for the lowOne or lowThreshold */ |
|
558 for (s=0; ToDistribute > 0; s = (s+1)%(maxSymbolValue+1)) |
|
559 if (norm[s] > 0) { ToDistribute--; norm[s]++; } |
561 return 0; |
560 return 0; |
562 } |
561 } |
563 |
562 |
564 { U64 const vStepLog = 62 - tableLog; |
563 { U64 const vStepLog = 62 - tableLog; |
565 U64 const mid = (1ULL << (vStepLog-1)) - 1; |
564 U64 const mid = (1ULL << (vStepLog-1)) - 1; |
566 U64 const rStep = ((((U64)1<<vStepLog) * ToDistribute) + mid) / total; /* scale on remaining */ |
565 U64 const rStep = ((((U64)1<<vStepLog) * ToDistribute) + mid) / total; /* scale on remaining */ |
567 U64 tmpTotal = mid; |
566 U64 tmpTotal = mid; |
568 for (s=0; s<=maxSymbolValue; s++) { |
567 for (s=0; s<=maxSymbolValue; s++) { |
569 if (norm[s]==-2) { |
568 if (norm[s]==NOT_YET_ASSIGNED) { |
570 U64 const end = tmpTotal + (count[s] * rStep); |
569 U64 const end = tmpTotal + (count[s] * rStep); |
571 U32 const sStart = (U32)(tmpTotal >> vStepLog); |
570 U32 const sStart = (U32)(tmpTotal >> vStepLog); |
572 U32 const sEnd = (U32)(end >> vStepLog); |
571 U32 const sEnd = (U32)(end >> vStepLog); |
573 U32 const weight = sEnd - sStart; |
572 U32 const weight = sEnd - sStart; |
574 if (weight < 1) |
573 if (weight < 1) |
589 if (tableLog==0) tableLog = FSE_DEFAULT_TABLELOG; |
588 if (tableLog==0) tableLog = FSE_DEFAULT_TABLELOG; |
590 if (tableLog < FSE_MIN_TABLELOG) return ERROR(GENERIC); /* Unsupported size */ |
589 if (tableLog < FSE_MIN_TABLELOG) return ERROR(GENERIC); /* Unsupported size */ |
591 if (tableLog > FSE_MAX_TABLELOG) return ERROR(tableLog_tooLarge); /* Unsupported size */ |
590 if (tableLog > FSE_MAX_TABLELOG) return ERROR(tableLog_tooLarge); /* Unsupported size */ |
592 if (tableLog < FSE_minTableLog(total, maxSymbolValue)) return ERROR(GENERIC); /* Too small tableLog, compression potentially impossible */ |
591 if (tableLog < FSE_minTableLog(total, maxSymbolValue)) return ERROR(GENERIC); /* Too small tableLog, compression potentially impossible */ |
593 |
592 |
594 { U32 const rtbTable[] = { 0, 473195, 504333, 520860, 550000, 700000, 750000, 830000 }; |
593 { static U32 const rtbTable[] = { 0, 473195, 504333, 520860, 550000, 700000, 750000, 830000 }; |
595 U64 const scale = 62 - tableLog; |
594 U64 const scale = 62 - tableLog; |
596 U64 const step = ((U64)1<<62) / total; /* <== here, one division ! */ |
595 U64 const step = ((U64)1<<62) / total; /* <== here, one division ! */ |
597 U64 const vStep = 1ULL<<(scale-20); |
596 U64 const vStep = 1ULL<<(scale-20); |
598 int stillToDistribute = 1<<tableLog; |
597 int stillToDistribute = 1<<tableLog; |
599 unsigned s; |
598 unsigned s; |
611 short proba = (short)((count[s]*step) >> scale); |
610 short proba = (short)((count[s]*step) >> scale); |
612 if (proba<8) { |
611 if (proba<8) { |
613 U64 restToBeat = vStep * rtbTable[proba]; |
612 U64 restToBeat = vStep * rtbTable[proba]; |
614 proba += (count[s]*step) - ((U64)proba<<scale) > restToBeat; |
613 proba += (count[s]*step) - ((U64)proba<<scale) > restToBeat; |
615 } |
614 } |
616 if (proba > largestP) largestP=proba, largest=s; |
615 if (proba > largestP) { largestP=proba; largest=s; } |
617 normalizedCounter[s] = proba; |
616 normalizedCounter[s] = proba; |
618 stillToDistribute -= proba; |
617 stillToDistribute -= proba; |
619 } } |
618 } } |
620 if (-stillToDistribute >= (normalizedCounter[largest] >> 1)) { |
619 if (-stillToDistribute >= (normalizedCounter[largest] >> 1)) { |
621 /* corner case, need another normalization method */ |
620 /* corner case, need another normalization method */ |
772 } |
771 } |
773 |
772 |
774 |
773 |
775 size_t FSE_compressBound(size_t size) { return FSE_COMPRESSBOUND(size); } |
774 size_t FSE_compressBound(size_t size) { return FSE_COMPRESSBOUND(size); } |
776 |
775 |
777 #define CHECK_V_F(e, f) size_t const e = f; if (ERR_isError(e)) return f |
776 #define CHECK_V_F(e, f) size_t const e = f; if (ERR_isError(e)) return e |
778 #define CHECK_F(f) { CHECK_V_F(_var_err__, f); } |
777 #define CHECK_F(f) { CHECK_V_F(_var_err__, f); } |
779 |
778 |
780 /* FSE_compress_wksp() : |
779 /* FSE_compress_wksp() : |
781 * Same as FSE_compress2(), but using an externally allocated scratch buffer (`workSpace`). |
780 * Same as FSE_compress2(), but using an externally allocated scratch buffer (`workSpace`). |
782 * `wkspSize` size must be `(1<<tableLog)`. |
781 * `wkspSize` size must be `(1<<tableLog)`. |
799 if (srcSize <= 1) return 0; /* Not compressible */ |
798 if (srcSize <= 1) return 0; /* Not compressible */ |
800 if (!maxSymbolValue) maxSymbolValue = FSE_MAX_SYMBOL_VALUE; |
799 if (!maxSymbolValue) maxSymbolValue = FSE_MAX_SYMBOL_VALUE; |
801 if (!tableLog) tableLog = FSE_DEFAULT_TABLELOG; |
800 if (!tableLog) tableLog = FSE_DEFAULT_TABLELOG; |
802 |
801 |
803 /* Scan input and build symbol stats */ |
802 /* Scan input and build symbol stats */ |
804 { CHECK_V_F(maxCount, FSE_count(count, &maxSymbolValue, src, srcSize) ); |
803 { CHECK_V_F(maxCount, FSE_count_wksp(count, &maxSymbolValue, src, srcSize, (unsigned*)scratchBuffer) ); |
805 if (maxCount == srcSize) return 1; /* only a single symbol in src : rle */ |
804 if (maxCount == srcSize) return 1; /* only a single symbol in src : rle */ |
806 if (maxCount == 1) return 0; /* each symbol present maximum once => not compressible */ |
805 if (maxCount == 1) return 0; /* each symbol present maximum once => not compressible */ |
807 if (maxCount < (srcSize >> 7)) return 0; /* Heuristic : not compressible enough */ |
806 if (maxCount < (srcSize >> 7)) return 0; /* Heuristic : not compressible enough */ |
808 } |
807 } |
809 |
808 |