1 /* ******************************************************************
2 * FSE : Finite State Entropy encoder
3 * Copyright (c) 2013-2020, Yann Collet, Facebook, Inc.
5 * You can contact the author at :
6 * - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy
7 * - Public forum : https://groups.google.com/forum/#!forum/lz4c
9 * This source code is licensed under both the BSD-style license (found in the
10 * LICENSE file in the root directory of this source tree) and the GPLv2 (found
11 * in the COPYING file in the root directory of this source tree).
12 * You may select, at your option, one of the above-listed licenses.
13 ****************************************************************** */
15 /* **************************************************************
17 ****************************************************************/
18 #include <stdlib.h> /* malloc, free, qsort */
19 #include <string.h> /* memcpy, memset */
20 #include "../common/compiler.h"
21 #include "../common/mem.h" /* U32, U16, etc. */
22 #include "../common/debug.h" /* assert, DEBUGLOG */
23 #include "hist.h" /* HIST_count_wksp */
24 #include "../common/bitstream.h"
25 #define FSE_STATIC_LINKING_ONLY
26 #include "../common/fse.h"
27 #include "../common/error_private.h"
30 /* **************************************************************
32 ****************************************************************/
33 #define FSE_isError ERR_isError
36 /* **************************************************************
38 ****************************************************************/
40 designed to be included
41 for type-specific functions (template emulation in C)
42 Objective is to write these functions only once, for improved maintenance
46 #ifndef FSE_FUNCTION_EXTENSION
47 # error "FSE_FUNCTION_EXTENSION must be defined"
49 #ifndef FSE_FUNCTION_TYPE
50 # error "FSE_FUNCTION_TYPE must be defined"
54 #define FSE_CAT(X,Y) X##Y
55 #define FSE_FUNCTION_NAME(X,Y) FSE_CAT(X,Y)
56 #define FSE_TYPE_NAME(X,Y) FSE_CAT(X,Y)
59 /* Function templates */
61 /* FSE_buildCTable_wksp() :
62 * Same as FSE_buildCTable(), but using an externally allocated scratch buffer (`workSpace`).
63 * wkspSize should be sized to handle worst case situation, which is `1<<max_tableLog * sizeof(FSE_FUNCTION_TYPE)`
64 * workSpace must also be properly aligned with FSE_FUNCTION_TYPE requirements
66 size_t FSE_buildCTable_wksp(FSE_CTable
* ct
,
67 const short* normalizedCounter
, unsigned maxSymbolValue
, unsigned tableLog
,
68 void* workSpace
, size_t wkspSize
)
70 U32
const tableSize
= 1 << tableLog
;
71 U32
const tableMask
= tableSize
- 1;
73 U16
* const tableU16
= ( (U16
*) ptr
) + 2;
74 void* const FSCT
= ((U32
*)ptr
) + 1 /* header */ + (tableLog
? tableSize
>>1 : 1) ;
75 FSE_symbolCompressionTransform
* const symbolTT
= (FSE_symbolCompressionTransform
*) (FSCT
);
76 U32
const step
= FSE_TABLESTEP(tableSize
);
77 U32 cumul
[FSE_MAX_SYMBOL_VALUE
+2];
79 FSE_FUNCTION_TYPE
* const tableSymbol
= (FSE_FUNCTION_TYPE
*)workSpace
;
80 U32 highThreshold
= tableSize
-1;
83 if (((size_t)1 << tableLog
) * sizeof(FSE_FUNCTION_TYPE
) > wkspSize
) return ERROR(tableLog_tooLarge
);
84 tableU16
[-2] = (U16
) tableLog
;
85 tableU16
[-1] = (U16
) maxSymbolValue
;
86 assert(tableLog
< 16); /* required for threshold strategy to work */
88 /* For explanations on how to distribute symbol values over the table :
89 * http://fastcompression.blogspot.fr/2014/02/fse-distributing-symbol-values.html */
91 #ifdef __clang_analyzer__
92 memset(tableSymbol
, 0, sizeof(*tableSymbol
) * tableSize
); /* useless initialization, just to keep scan-build happy */
95 /* symbol start positions */
98 for (u
=1; u
<= maxSymbolValue
+1; u
++) {
99 if (normalizedCounter
[u
-1]==-1) { /* Low proba symbol */
100 cumul
[u
] = cumul
[u
-1] + 1;
101 tableSymbol
[highThreshold
--] = (FSE_FUNCTION_TYPE
)(u
-1);
103 cumul
[u
] = cumul
[u
-1] + normalizedCounter
[u
-1];
105 cumul
[maxSymbolValue
+1] = tableSize
+1;
111 for (symbol
=0; symbol
<=maxSymbolValue
; symbol
++) {
113 int const freq
= normalizedCounter
[symbol
];
114 for (nbOccurrences
=0; nbOccurrences
<freq
; nbOccurrences
++) {
115 tableSymbol
[position
] = (FSE_FUNCTION_TYPE
)symbol
;
116 position
= (position
+ step
) & tableMask
;
117 while (position
> highThreshold
)
118 position
= (position
+ step
) & tableMask
; /* Low proba area */
121 assert(position
==0); /* Must have initialized all positions */
125 { U32 u
; for (u
=0; u
<tableSize
; u
++) {
126 FSE_FUNCTION_TYPE s
= tableSymbol
[u
]; /* note : static analyzer may not understand tableSymbol is properly initialized */
127 tableU16
[cumul
[s
]++] = (U16
) (tableSize
+u
); /* TableU16 : sorted by symbol order; gives next state value */
130 /* Build Symbol Transformation Table */
131 { unsigned total
= 0;
133 for (s
=0; s
<=maxSymbolValue
; s
++) {
134 switch (normalizedCounter
[s
])
137 /* filling nonetheless, for compatibility with FSE_getMaxNbBits() */
138 symbolTT
[s
].deltaNbBits
= ((tableLog
+1) << 16) - (1<<tableLog
);
143 symbolTT
[s
].deltaNbBits
= (tableLog
<< 16) - (1<<tableLog
);
144 symbolTT
[s
].deltaFindState
= total
- 1;
149 U32
const maxBitsOut
= tableLog
- BIT_highbit32 (normalizedCounter
[s
]-1);
150 U32
const minStatePlus
= normalizedCounter
[s
] << maxBitsOut
;
151 symbolTT
[s
].deltaNbBits
= (maxBitsOut
<< 16) - minStatePlus
;
152 symbolTT
[s
].deltaFindState
= total
- normalizedCounter
[s
];
153 total
+= normalizedCounter
[s
];
156 #if 0 /* debug : symbol costs */
157 DEBUGLOG(5, "\n --- table statistics : ");
159 for (symbol
=0; symbol
<=maxSymbolValue
; symbol
++) {
160 DEBUGLOG(5, "%3u: w=%3i, maxBits=%u, fracBits=%.2f",
161 symbol
, normalizedCounter
[symbol
],
162 FSE_getMaxNbBits(symbolTT
, symbol
),
163 (double)FSE_bitCost(symbolTT
, tableLog
, symbol
, 8) / 256);
172 size_t FSE_buildCTable(FSE_CTable
* ct
, const short* normalizedCounter
, unsigned maxSymbolValue
, unsigned tableLog
)
174 FSE_FUNCTION_TYPE tableSymbol
[FSE_MAX_TABLESIZE
]; /* memset() is not necessary, even if static analyzer complain about it */
175 return FSE_buildCTable_wksp(ct
, normalizedCounter
, maxSymbolValue
, tableLog
, tableSymbol
, sizeof(tableSymbol
));
180 #ifndef FSE_COMMONDEFS_ONLY
183 /*-**************************************************************
184 * FSE NCount encoding
185 ****************************************************************/
186 size_t FSE_NCountWriteBound(unsigned maxSymbolValue
, unsigned tableLog
)
188 size_t const maxHeaderSize
= (((maxSymbolValue
+1) * tableLog
) >> 3) + 3;
189 return maxSymbolValue
? maxHeaderSize
: FSE_NCOUNTBOUND
; /* maxSymbolValue==0 ? use default */
193 FSE_writeNCount_generic (void* header
, size_t headerBufferSize
,
194 const short* normalizedCounter
, unsigned maxSymbolValue
, unsigned tableLog
,
195 unsigned writeIsSafe
)
197 BYTE
* const ostart
= (BYTE
*) header
;
199 BYTE
* const oend
= ostart
+ headerBufferSize
;
201 const int tableSize
= 1 << tableLog
;
207 unsigned const alphabetSize
= maxSymbolValue
+ 1;
211 bitStream
+= (tableLog
-FSE_MIN_TABLELOG
) << bitCount
;
215 remaining
= tableSize
+1; /* +1 for extra accuracy */
216 threshold
= tableSize
;
219 while ((symbol
< alphabetSize
) && (remaining
>1)) { /* stops at 1 */
221 unsigned start
= symbol
;
222 while ((symbol
< alphabetSize
) && !normalizedCounter
[symbol
]) symbol
++;
223 if (symbol
== alphabetSize
) break; /* incorrect distribution */
224 while (symbol
>= start
+24) {
226 bitStream
+= 0xFFFFU
<< bitCount
;
227 if ((!writeIsSafe
) && (out
> oend
-2))
228 return ERROR(dstSize_tooSmall
); /* Buffer overflow */
229 out
[0] = (BYTE
) bitStream
;
230 out
[1] = (BYTE
)(bitStream
>>8);
234 while (symbol
>= start
+3) {
236 bitStream
+= 3 << bitCount
;
239 bitStream
+= (symbol
-start
) << bitCount
;
242 if ((!writeIsSafe
) && (out
> oend
- 2))
243 return ERROR(dstSize_tooSmall
); /* Buffer overflow */
244 out
[0] = (BYTE
)bitStream
;
245 out
[1] = (BYTE
)(bitStream
>>8);
250 { int count
= normalizedCounter
[symbol
++];
251 int const max
= (2*threshold
-1) - remaining
;
252 remaining
-= count
< 0 ? -count
: count
;
253 count
++; /* +1 for extra accuracy */
254 if (count
>=threshold
)
255 count
+= max
; /* [0..max[ [max..threshold[ (...) [threshold+max 2*threshold[ */
256 bitStream
+= count
<< bitCount
;
258 bitCount
-= (count
<max
);
259 previousIs0
= (count
==1);
260 if (remaining
<1) return ERROR(GENERIC
);
261 while (remaining
<threshold
) { nbBits
--; threshold
>>=1; }
264 if ((!writeIsSafe
) && (out
> oend
- 2))
265 return ERROR(dstSize_tooSmall
); /* Buffer overflow */
266 out
[0] = (BYTE
)bitStream
;
267 out
[1] = (BYTE
)(bitStream
>>8);
274 return ERROR(GENERIC
); /* incorrect normalized distribution */
275 assert(symbol
<= alphabetSize
);
277 /* flush remaining bitStream */
278 if ((!writeIsSafe
) && (out
> oend
- 2))
279 return ERROR(dstSize_tooSmall
); /* Buffer overflow */
280 out
[0] = (BYTE
)bitStream
;
281 out
[1] = (BYTE
)(bitStream
>>8);
282 out
+= (bitCount
+7) /8;
288 size_t FSE_writeNCount (void* buffer
, size_t bufferSize
,
289 const short* normalizedCounter
, unsigned maxSymbolValue
, unsigned tableLog
)
291 if (tableLog
> FSE_MAX_TABLELOG
) return ERROR(tableLog_tooLarge
); /* Unsupported */
292 if (tableLog
< FSE_MIN_TABLELOG
) return ERROR(GENERIC
); /* Unsupported */
294 if (bufferSize
< FSE_NCountWriteBound(maxSymbolValue
, tableLog
))
295 return FSE_writeNCount_generic(buffer
, bufferSize
, normalizedCounter
, maxSymbolValue
, tableLog
, 0);
297 return FSE_writeNCount_generic(buffer
, bufferSize
, normalizedCounter
, maxSymbolValue
, tableLog
, 1 /* write in buffer is safe */);
301 /*-**************************************************************
302 * FSE Compression Code
303 ****************************************************************/
305 FSE_CTable
* FSE_createCTable (unsigned maxSymbolValue
, unsigned tableLog
)
307 size_t size
__attribute__ ((unused
));
308 if (tableLog
> FSE_TABLELOG_ABSOLUTE_MAX
) tableLog
= FSE_TABLELOG_ABSOLUTE_MAX
;
309 size
= FSE_CTABLE_SIZE_U32 (tableLog
, maxSymbolValue
) * sizeof(U32
);
310 return (FSE_CTable
*)malloc(size
);
313 void FSE_freeCTable (FSE_CTable
* ct
) { free(ct
); }
315 /* provides the minimum logSize to safely represent a distribution */
316 static unsigned FSE_minTableLog(size_t srcSize
, unsigned maxSymbolValue
)
318 U32 minBitsSrc
= BIT_highbit32((U32
)(srcSize
)) + 1;
319 U32 minBitsSymbols
= BIT_highbit32(maxSymbolValue
) + 2;
320 U32 minBits
= minBitsSrc
< minBitsSymbols
? minBitsSrc
: minBitsSymbols
;
321 assert(srcSize
> 1); /* Not supported, RLE should be used instead */
325 unsigned FSE_optimalTableLog_internal(unsigned maxTableLog
, size_t srcSize
, unsigned maxSymbolValue
, unsigned minus
)
327 U32 maxBitsSrc
= BIT_highbit32((U32
)(srcSize
- 1)) - minus
;
328 U32 tableLog
= maxTableLog
;
329 U32 minBits
= FSE_minTableLog(srcSize
, maxSymbolValue
);
330 assert(srcSize
> 1); /* Not supported, RLE should be used instead */
331 if (tableLog
==0) tableLog
= FSE_DEFAULT_TABLELOG
;
332 if (maxBitsSrc
< tableLog
) tableLog
= maxBitsSrc
; /* Accuracy can be reduced */
333 if (minBits
> tableLog
) tableLog
= minBits
; /* Need a minimum to safely represent all symbol values */
334 if (tableLog
< FSE_MIN_TABLELOG
) tableLog
= FSE_MIN_TABLELOG
;
335 if (tableLog
> FSE_MAX_TABLELOG
) tableLog
= FSE_MAX_TABLELOG
;
339 unsigned FSE_optimalTableLog(unsigned maxTableLog
, size_t srcSize
, unsigned maxSymbolValue
)
341 return FSE_optimalTableLog_internal(maxTableLog
, srcSize
, maxSymbolValue
, 2);
345 /* Secondary normalization method.
346 To be used when primary method fails. */
348 static size_t FSE_normalizeM2(short* norm
, U32 tableLog
, const unsigned* count
, size_t total
, U32 maxSymbolValue
)
350 short const NOT_YET_ASSIGNED
= -2;
356 U32
const lowThreshold
= (U32
)(total
>> tableLog
);
357 U32 lowOne
= (U32
)((total
* 3) >> (tableLog
+ 1));
359 for (s
=0; s
<=maxSymbolValue
; s
++) {
364 if (count
[s
] <= lowThreshold
) {
370 if (count
[s
] <= lowOne
) {
377 norm
[s
]=NOT_YET_ASSIGNED
;
379 ToDistribute
= (1 << tableLog
) - distributed
;
381 if (ToDistribute
== 0)
384 if ((total
/ ToDistribute
) > lowOne
) {
385 /* risk of rounding to zero */
386 lowOne
= (U32
)((total
* 3) / (ToDistribute
* 2));
387 for (s
=0; s
<=maxSymbolValue
; s
++) {
388 if ((norm
[s
] == NOT_YET_ASSIGNED
) && (count
[s
] <= lowOne
)) {
394 ToDistribute
= (1 << tableLog
) - distributed
;
397 if (distributed
== maxSymbolValue
+1) {
398 /* all values are pretty poor;
399 probably incompressible data (should have already been detected);
400 find max, then give all remaining points to max */
401 U32 maxV
= 0, maxC
= 0;
402 for (s
=0; s
<=maxSymbolValue
; s
++)
403 if (count
[s
] > maxC
) { maxV
=s
; maxC
=count
[s
]; }
404 norm
[maxV
] += (short)ToDistribute
;
409 /* all of the symbols were low enough for the lowOne or lowThreshold */
410 for (s
=0; ToDistribute
> 0; s
= (s
+1)%(maxSymbolValue
+1))
411 if (norm
[s
] > 0) { ToDistribute
--; norm
[s
]++; }
415 { U64
const vStepLog
= 62 - tableLog
;
416 U64
const mid
= (1ULL << (vStepLog
-1)) - 1;
417 U64
const rStep
= ((((U64
)1<<vStepLog
) * ToDistribute
) + mid
) / total
; /* scale on remaining */
419 for (s
=0; s
<=maxSymbolValue
; s
++) {
420 if (norm
[s
]==NOT_YET_ASSIGNED
) {
421 U64
const end
= tmpTotal
+ (count
[s
] * rStep
);
422 U32
const sStart
= (U32
)(tmpTotal
>> vStepLog
);
423 U32
const sEnd
= (U32
)(end
>> vStepLog
);
424 U32
const weight
= sEnd
- sStart
;
426 return ERROR(GENERIC
);
427 norm
[s
] = (short)weight
;
435 size_t FSE_normalizeCount (short* normalizedCounter
, unsigned tableLog
,
436 const unsigned* count
, size_t total
,
437 unsigned maxSymbolValue
)
440 if (tableLog
==0) tableLog
= FSE_DEFAULT_TABLELOG
;
441 if (tableLog
< FSE_MIN_TABLELOG
) return ERROR(GENERIC
); /* Unsupported size */
442 if (tableLog
> FSE_MAX_TABLELOG
) return ERROR(tableLog_tooLarge
); /* Unsupported size */
443 if (tableLog
< FSE_minTableLog(total
, maxSymbolValue
)) return ERROR(GENERIC
); /* Too small tableLog, compression potentially impossible */
445 { static U32
const rtbTable
[] = { 0, 473195, 504333, 520860, 550000, 700000, 750000, 830000 };
446 U64
const scale
= 62 - tableLog
;
447 U64
const step
= ((U64
)1<<62) / total
; /* <== here, one division ! */
448 U64
const vStep
= 1ULL<<(scale
-20);
449 int stillToDistribute
= 1<<tableLog
;
453 U32 lowThreshold
= (U32
)(total
>> tableLog
);
455 for (s
=0; s
<=maxSymbolValue
; s
++) {
456 if (count
[s
] == total
) return 0; /* rle special case */
457 if (count
[s
] == 0) { normalizedCounter
[s
]=0; continue; }
458 if (count
[s
] <= lowThreshold
) {
459 normalizedCounter
[s
] = -1;
462 short proba
= (short)((count
[s
]*step
) >> scale
);
464 U64 restToBeat
= vStep
* rtbTable
[proba
];
465 proba
+= (count
[s
]*step
) - ((U64
)proba
<<scale
) > restToBeat
;
467 if (proba
> largestP
) { largestP
=proba
; largest
=s
; }
468 normalizedCounter
[s
] = proba
;
469 stillToDistribute
-= proba
;
471 if (-stillToDistribute
>= (normalizedCounter
[largest
] >> 1)) {
472 /* corner case, need another normalization method */
473 size_t const errorCode
= FSE_normalizeM2(normalizedCounter
, tableLog
, count
, total
, maxSymbolValue
);
474 if (FSE_isError(errorCode
)) return errorCode
;
476 else normalizedCounter
[largest
] += (short)stillToDistribute
;
480 { /* Print Table (debug) */
483 for (s
=0; s
<=maxSymbolValue
; s
++)
484 RAWLOG(2, "%3i: %4i \n", s
, normalizedCounter
[s
]);
485 for (s
=0; s
<=maxSymbolValue
; s
++)
486 nTotal
+= abs(normalizedCounter
[s
]);
487 if (nTotal
!= (1U<<tableLog
))
488 RAWLOG(2, "Warning !!! Total == %u != %u !!!", nTotal
, 1U<<tableLog
);
497 /* fake FSE_CTable, for raw (uncompressed) input */
498 size_t FSE_buildCTable_raw (FSE_CTable
* ct
, unsigned nbBits
)
500 const unsigned tableSize
= 1 << nbBits
;
501 const unsigned tableMask
= tableSize
- 1;
502 const unsigned maxSymbolValue
= tableMask
;
503 void* const ptr
= ct
;
504 U16
* const tableU16
= ( (U16
*) ptr
) + 2;
505 void* const FSCT
= ((U32
*)ptr
) + 1 /* header */ + (tableSize
>>1); /* assumption : tableLog >= 1 */
506 FSE_symbolCompressionTransform
* const symbolTT
= (FSE_symbolCompressionTransform
*) (FSCT
);
510 if (nbBits
< 1) return ERROR(GENERIC
); /* min size */
513 tableU16
[-2] = (U16
) nbBits
;
514 tableU16
[-1] = (U16
) maxSymbolValue
;
517 for (s
=0; s
<tableSize
; s
++)
518 tableU16
[s
] = (U16
)(tableSize
+ s
);
520 /* Build Symbol Transformation Table */
521 { const U32 deltaNbBits
= (nbBits
<< 16) - (1 << nbBits
);
522 for (s
=0; s
<=maxSymbolValue
; s
++) {
523 symbolTT
[s
].deltaNbBits
= deltaNbBits
;
524 symbolTT
[s
].deltaFindState
= s
-1;
530 /* fake FSE_CTable, for rle input (always same symbol) */
531 size_t FSE_buildCTable_rle (FSE_CTable
* ct
, BYTE symbolValue
)
534 U16
* tableU16
= ( (U16
*) ptr
) + 2;
535 void* FSCTptr
= (U32
*)ptr
+ 2;
536 FSE_symbolCompressionTransform
* symbolTT
= (FSE_symbolCompressionTransform
*) FSCTptr
;
539 tableU16
[-2] = (U16
) 0;
540 tableU16
[-1] = (U16
) symbolValue
;
544 tableU16
[1] = 0; /* just in case */
546 /* Build Symbol Transformation Table */
547 symbolTT
[symbolValue
].deltaNbBits
= 0;
548 symbolTT
[symbolValue
].deltaFindState
= 0;
554 static size_t FSE_compress_usingCTable_generic (void* dst
, size_t dstSize
,
555 const void* src
, size_t srcSize
,
556 const FSE_CTable
* ct
, const unsigned fast
)
558 const BYTE
* const istart
= (const BYTE
*) src
;
559 const BYTE
* const iend
= istart
+ srcSize
;
563 FSE_CState_t CState1
, CState2
;
566 if (srcSize
<= 2) return 0;
567 { size_t const initError
= BIT_initCStream(&bitC
, dst
, dstSize
);
568 if (FSE_isError(initError
)) return 0; /* not enough space available to write a bitstream */ }
570 #define FSE_FLUSHBITS(s) (fast ? BIT_flushBitsFast(s) : BIT_flushBits(s))
573 FSE_initCState2(&CState1
, ct
, *--ip
);
574 FSE_initCState2(&CState2
, ct
, *--ip
);
575 FSE_encodeSymbol(&bitC
, &CState1
, *--ip
);
576 FSE_FLUSHBITS(&bitC
);
578 FSE_initCState2(&CState2
, ct
, *--ip
);
579 FSE_initCState2(&CState1
, ct
, *--ip
);
584 if ((sizeof(bitC
.bitContainer
)*8 > FSE_MAX_TABLELOG
*4+7 ) && (srcSize
& 2)) { /* test bit 2 */
585 FSE_encodeSymbol(&bitC
, &CState2
, *--ip
);
586 FSE_encodeSymbol(&bitC
, &CState1
, *--ip
);
587 FSE_FLUSHBITS(&bitC
);
590 /* 2 or 4 encoding per loop */
591 while ( ip
>istart
) {
593 FSE_encodeSymbol(&bitC
, &CState2
, *--ip
);
595 if (sizeof(bitC
.bitContainer
)*8 < FSE_MAX_TABLELOG
*2+7 ) /* this test must be static */
596 FSE_FLUSHBITS(&bitC
);
598 FSE_encodeSymbol(&bitC
, &CState1
, *--ip
);
600 if (sizeof(bitC
.bitContainer
)*8 > FSE_MAX_TABLELOG
*4+7 ) { /* this test must be static */
601 FSE_encodeSymbol(&bitC
, &CState2
, *--ip
);
602 FSE_encodeSymbol(&bitC
, &CState1
, *--ip
);
605 FSE_FLUSHBITS(&bitC
);
608 FSE_flushCState(&bitC
, &CState2
);
609 FSE_flushCState(&bitC
, &CState1
);
610 return BIT_closeCStream(&bitC
);
613 size_t FSE_compress_usingCTable (void* dst
, size_t dstSize
,
614 const void* src
, size_t srcSize
,
615 const FSE_CTable
* ct
)
617 unsigned const fast
= (dstSize
>= FSE_BLOCKBOUND(srcSize
));
620 return FSE_compress_usingCTable_generic(dst
, dstSize
, src
, srcSize
, ct
, 1);
622 return FSE_compress_usingCTable_generic(dst
, dstSize
, src
, srcSize
, ct
, 0);
626 size_t FSE_compressBound(size_t size
) { return FSE_COMPRESSBOUND(size
); }
628 /* FSE_compress_wksp() :
629 * Same as FSE_compress2(), but using an externally allocated scratch buffer (`workSpace`).
630 * `wkspSize` size must be `(1<<tableLog)`.
632 size_t FSE_compress_wksp (void* dst
, size_t dstSize
, const void* src
, size_t srcSize
, unsigned maxSymbolValue
, unsigned tableLog
, void* workSpace
, size_t wkspSize
)
634 BYTE
* const ostart
= (BYTE
*) dst
;
636 BYTE
* const oend
= ostart
+ dstSize
;
638 unsigned count
[FSE_MAX_SYMBOL_VALUE
+1];
639 S16 norm
[FSE_MAX_SYMBOL_VALUE
+1];
640 FSE_CTable
* CTable
= (FSE_CTable
*)workSpace
;
641 size_t const CTableSize
= FSE_CTABLE_SIZE_U32(tableLog
, maxSymbolValue
);
642 void* scratchBuffer
= (void*)(CTable
+ CTableSize
);
643 size_t const scratchBufferSize
= wkspSize
- (CTableSize
* sizeof(FSE_CTable
));
645 /* init conditions */
646 if (wkspSize
< FSE_WKSP_SIZE_U32(tableLog
, maxSymbolValue
)) return ERROR(tableLog_tooLarge
);
647 if (srcSize
<= 1) return 0; /* Not compressible */
648 if (!maxSymbolValue
) maxSymbolValue
= FSE_MAX_SYMBOL_VALUE
;
649 if (!tableLog
) tableLog
= FSE_DEFAULT_TABLELOG
;
651 /* Scan input and build symbol stats */
652 { CHECK_V_F(maxCount
, HIST_count_wksp(count
, &maxSymbolValue
, src
, srcSize
, scratchBuffer
, scratchBufferSize
) );
653 if (maxCount
== srcSize
) return 1; /* only a single symbol in src : rle */
654 if (maxCount
== 1) return 0; /* each symbol present maximum once => not compressible */
655 if (maxCount
< (srcSize
>> 7)) return 0; /* Heuristic : not compressible enough */
658 tableLog
= FSE_optimalTableLog(tableLog
, srcSize
, maxSymbolValue
);
659 CHECK_F( FSE_normalizeCount(norm
, tableLog
, count
, srcSize
, maxSymbolValue
) );
661 /* Write table description header */
662 { CHECK_V_F(nc_err
, FSE_writeNCount(op
, oend
-op
, norm
, maxSymbolValue
, tableLog
) );
667 CHECK_F( FSE_buildCTable_wksp(CTable
, norm
, maxSymbolValue
, tableLog
, scratchBuffer
, scratchBufferSize
) );
668 { CHECK_V_F(cSize
, FSE_compress_usingCTable(op
, oend
- op
, src
, srcSize
, CTable
) );
669 if (cSize
== 0) return 0; /* not enough space for compressed data */
673 /* check compressibility */
674 if ( (size_t)(op
-ostart
) >= srcSize
-1 ) return 0;
680 FSE_CTable CTable_max
[FSE_CTABLE_SIZE_U32(FSE_MAX_TABLELOG
, FSE_MAX_SYMBOL_VALUE
)];
681 BYTE scratchBuffer
[1 << FSE_MAX_TABLELOG
];
684 size_t FSE_compress2 (void* dst
, size_t dstCapacity
, const void* src
, size_t srcSize
, unsigned maxSymbolValue
, unsigned tableLog
)
686 fseWkspMax_t scratchBuffer
;
687 DEBUG_STATIC_ASSERT(sizeof(scratchBuffer
) >= FSE_WKSP_SIZE_U32(FSE_MAX_TABLELOG
, FSE_MAX_SYMBOL_VALUE
)); /* compilation failures here means scratchBuffer is not large enough */
688 if (tableLog
> FSE_MAX_TABLELOG
) return ERROR(tableLog_tooLarge
);
689 return FSE_compress_wksp(dst
, dstCapacity
, src
, srcSize
, maxSymbolValue
, tableLog
, &scratchBuffer
, sizeof(scratchBuffer
));
692 size_t FSE_compress (void* dst
, size_t dstCapacity
, const void* src
, size_t srcSize
)
694 return FSE_compress2(dst
, dstCapacity
, src
, srcSize
, FSE_MAX_SYMBOL_VALUE
, FSE_DEFAULT_TABLELOG
);
698 #endif /* FSE_COMMONDEFS_ONLY */