blob: ca303db848d8423707f4c8d89924111e615cc175 [file] [log] [blame]
Yann Collet4856a002015-01-24 01:58:16 +01001/* ******************************************************************
2 FSE : Finite State Entropy coder
3 header file for static linking (only)
4 Copyright (C) 2013-2015, Yann Collet
5
6 BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
7
8 Redistribution and use in source and binary forms, with or without
9 modification, are permitted provided that the following conditions are
10 met:
11
12 * Redistributions of source code must retain the above copyright
13 notice, this list of conditions and the following disclaimer.
14 * Redistributions in binary form must reproduce the above
15 copyright notice, this list of conditions and the following disclaimer
16 in the documentation and/or other materials provided with the
17 distribution.
18
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31 You can contact the author at :
32 - Source repository : https://github.com/Cyan4973/FiniteStateEntropy
33 - Public forum : https://groups.google.com/forum/#!forum/lz4c
34****************************************************************** */
Yann Colletaa074052015-10-30 11:21:50 +010035#ifndef FSE_STATIC_H
36#define FSE_STATIC_H
Yann Collet4856a002015-01-24 01:58:16 +010037
38#if defined (__cplusplus)
39extern "C" {
40#endif
41
42
Yann Collet3b994cb2016-01-06 01:58:37 +010043/* *****************************************
44* Dependencies
45*******************************************/
Yann Collet1efa31f2015-07-04 15:56:41 -080046#include "fse.h"
Yann Colletb1f3f4b2015-10-18 22:18:32 +010047#include "bitstream.h"
Yann Collet4856a002015-01-24 01:58:16 +010048
49
Yann Collet3b994cb2016-01-06 01:58:37 +010050/* *****************************************
Yann Collet4856a002015-01-24 01:58:16 +010051* Static allocation
Yann Collet3b994cb2016-01-06 01:58:37 +010052*******************************************/
Yann Colleta7875502015-08-07 15:21:00 +010053/* FSE buffer bounds */
54#define FSE_NCOUNTBOUND 512
55#define FSE_BLOCKBOUND(size) (size + (size>>7))
56#define FSE_COMPRESSBOUND(size) (FSE_NCOUNTBOUND + FSE_BLOCKBOUND(size)) /* Macro version, useful for static allocation */
Yann Collete8c6bb12015-07-26 00:23:57 +010057
Yann Collet3b994cb2016-01-06 01:58:37 +010058/* It is possible to statically allocate FSE CTable/DTable as a table of unsigned using below macros */
Yann Collet4856a002015-01-24 01:58:16 +010059#define FSE_CTABLE_SIZE_U32(maxTableLog, maxSymbolValue) (1 + (1<<(maxTableLog-1)) + ((maxSymbolValue+1)*2))
Yann Collet1efa31f2015-07-04 15:56:41 -080060#define FSE_DTABLE_SIZE_U32(maxTableLog) (1 + (1<<maxTableLog))
Yann Collet4856a002015-01-24 01:58:16 +010061
Yann Collet4856a002015-01-24 01:58:16 +010062
Yann Collet3b994cb2016-01-06 01:58:37 +010063/* *****************************************
Yann Collet4856a002015-01-24 01:58:16 +010064* FSE advanced API
Yann Collet3b994cb2016-01-06 01:58:37 +010065*******************************************/
Yann Collet4ddb1f52016-01-28 03:24:53 +010066size_t FSE_countFast(unsigned* count, unsigned* maxSymbolValuePtr, const void* src, size_t srcSize);
67/* same as FSE_count(), but blindly trusts that all byte values within src are <= *maxSymbolValuePtr */
Yann Collet4856a002015-01-24 01:58:16 +010068
Yann Collet1efa31f2015-07-04 15:56:41 -080069size_t FSE_buildCTable_raw (FSE_CTable* ct, unsigned nbBits);
70/* build a fake FSE_CTable, designed to not compress an input, where each symbol uses nbBits */
Yann Collet4856a002015-01-24 01:58:16 +010071
Yann Collet1efa31f2015-07-04 15:56:41 -080072size_t FSE_buildCTable_rle (FSE_CTable* ct, unsigned char symbolValue);
73/* build a fake FSE_CTable, designed to compress always the same symbolValue */
Yann Collet4856a002015-01-24 01:58:16 +010074
Yann Collet1efa31f2015-07-04 15:56:41 -080075size_t FSE_buildDTable_raw (FSE_DTable* dt, unsigned nbBits);
76/* build a fake FSE_DTable, designed to read an uncompressed bitstream where each symbol uses nbBits */
Yann Collet4856a002015-01-24 01:58:16 +010077
Yann Collet1efa31f2015-07-04 15:56:41 -080078size_t FSE_buildDTable_rle (FSE_DTable* dt, unsigned char symbolValue);
79/* build a fake FSE_DTable, designed to always generate the same symbolValue */
Yann Collet4856a002015-01-24 01:58:16 +010080
81
Yann Collet3b994cb2016-01-06 01:58:37 +010082/* *****************************************
Yann Collet1efa31f2015-07-04 15:56:41 -080083* FSE symbol compression API
Yann Collet3b994cb2016-01-06 01:58:37 +010084*******************************************/
85/*!
Yann Collet1efa31f2015-07-04 15:56:41 -080086 This API consists of small unitary functions, which highly benefit from being inlined.
87 You will want to enable link-time-optimization to ensure these functions are properly inlined in your binary.
88 Visual seems to do it automatically.
89 For gcc or clang, you'll need to add -flto flag at compilation and linking stages.
Yann Colleta7875502015-08-07 15:21:00 +010090 If none of these solutions is applicable, include "fse.c" directly.
Yann Collet1efa31f2015-07-04 15:56:41 -080091*/
Yann Collet1efa31f2015-07-04 15:56:41 -080092typedef struct
93{
94 ptrdiff_t value;
95 const void* stateTable;
96 const void* symbolTT;
97 unsigned stateLog;
98} FSE_CState_t;
99
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100100static void FSE_initCState(FSE_CState_t* CStatePtr, const FSE_CTable* ct);
Yann Collet1efa31f2015-07-04 15:56:41 -0800101
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100102static void FSE_encodeSymbol(BIT_CStream_t* bitC, FSE_CState_t* CStatePtr, unsigned symbol);
Yann Collet1efa31f2015-07-04 15:56:41 -0800103
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100104static void FSE_flushCState(BIT_CStream_t* bitC, const FSE_CState_t* CStatePtr);
Yann Collet1efa31f2015-07-04 15:56:41 -0800105
Yann Collet3b994cb2016-01-06 01:58:37 +0100106/*!
Yann Collet1efa31f2015-07-04 15:56:41 -0800107These functions are inner components of FSE_compress_usingCTable().
108They allow the creation of custom streams, mixing multiple tables and bit sources.
109
110A key property to keep in mind is that encoding and decoding are done **in reverse direction**.
111So the first symbol you will encode is the last you will decode, like a LIFO stack.
112
113You will need a few variables to track your CStream. They are :
114
Yann Colleta7875502015-08-07 15:21:00 +0100115FSE_CTable ct; // Provided by FSE_buildCTable()
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100116BIT_CStream_t bitStream; // bitStream tracking structure
Yann Colleta7875502015-08-07 15:21:00 +0100117FSE_CState_t state; // State tracking structure (can have several)
Yann Collet1efa31f2015-07-04 15:56:41 -0800118
119
120The first thing to do is to init bitStream and state.
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100121 size_t errorCode = BIT_initCStream(&bitStream, dstBuffer, maxDstSize);
Yann Collet1efa31f2015-07-04 15:56:41 -0800122 FSE_initCState(&state, ct);
123
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100124Note that BIT_initCStream() can produce an error code, so its result should be tested, using FSE_isError();
Yann Collet1efa31f2015-07-04 15:56:41 -0800125You can then encode your input data, byte after byte.
Yann Colleta7875502015-08-07 15:21:00 +0100126FSE_encodeSymbol() outputs a maximum of 'tableLog' bits at a time.
Yann Collet1efa31f2015-07-04 15:56:41 -0800127Remember decoding will be done in reverse direction.
128 FSE_encodeByte(&bitStream, &state, symbol);
129
130At any time, you can also add any bit sequence.
131Note : maximum allowed nbBits is 25, for compatibility with 32-bits decoders
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100132 BIT_addBits(&bitStream, bitField, nbBits);
Yann Collet1efa31f2015-07-04 15:56:41 -0800133
134The above methods don't commit data to memory, they just store it into local register, for speed.
135Local register size is 64-bits on 64-bits systems, 32-bits on 32-bits systems (size_t).
136Writing data to memory is a manual operation, performed by the flushBits function.
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100137 BIT_flushBits(&bitStream);
Yann Collet1efa31f2015-07-04 15:56:41 -0800138
139Your last FSE encoding operation shall be to flush your last state value(s).
140 FSE_flushState(&bitStream, &state);
141
Yann Colleta7875502015-08-07 15:21:00 +0100142Finally, you must close the bitStream.
143The function returns the size of CStream in bytes.
144If data couldn't fit into dstBuffer, it will return a 0 ( == not compressible)
Yann Collet1efa31f2015-07-04 15:56:41 -0800145If there is an error, it returns an errorCode (which can be tested using FSE_isError()).
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100146 size_t size = BIT_closeCStream(&bitStream);
Yann Collet1efa31f2015-07-04 15:56:41 -0800147*/
148
149
Yann Collet3b994cb2016-01-06 01:58:37 +0100150/* *****************************************
Yann Collet1efa31f2015-07-04 15:56:41 -0800151* FSE symbol decompression API
Yann Collet3b994cb2016-01-06 01:58:37 +0100152*******************************************/
Yann Collet1efa31f2015-07-04 15:56:41 -0800153typedef struct
154{
Yann Collet1efa31f2015-07-04 15:56:41 -0800155 size_t state;
156 const void* table; /* precise table may vary, depending on U16 */
157} FSE_DState_t;
158
159
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100160static void FSE_initDState(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD, const FSE_DTable* dt);
Yann Collet1efa31f2015-07-04 15:56:41 -0800161
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100162static unsigned char FSE_decodeSymbol(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD);
Yann Collet1efa31f2015-07-04 15:56:41 -0800163
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100164static unsigned FSE_endOfDState(const FSE_DState_t* DStatePtr);
Yann Collete8c6bb12015-07-26 00:23:57 +0100165
Yann Collet3b994cb2016-01-06 01:58:37 +0100166/*!
Yann Collet1efa31f2015-07-04 15:56:41 -0800167Let's now decompose FSE_decompress_usingDTable() into its unitary components.
168You will decode FSE-encoded symbols from the bitStream,
169and also any other bitFields you put in, **in reverse order**.
170
171You will need a few variables to track your bitStream. They are :
172
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100173BIT_DStream_t DStream; // Stream context
Yann Colleta7875502015-08-07 15:21:00 +0100174FSE_DState_t DState; // State context. Multiple ones are possible
175FSE_DTable* DTablePtr; // Decoding table, provided by FSE_buildDTable()
Yann Collet1efa31f2015-07-04 15:56:41 -0800176
177The first thing to do is to init the bitStream.
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100178 errorCode = BIT_initDStream(&DStream, srcBuffer, srcSize);
Yann Collet1efa31f2015-07-04 15:56:41 -0800179
Yann Colleta7875502015-08-07 15:21:00 +0100180You should then retrieve your initial state(s)
181(in reverse flushing order if you have several ones) :
182 errorCode = FSE_initDState(&DState, &DStream, DTablePtr);
Yann Collet1efa31f2015-07-04 15:56:41 -0800183
184You can then decode your data, symbol after symbol.
185For information the maximum number of bits read by FSE_decodeSymbol() is 'tableLog'.
186Keep in mind that symbols are decoded in reverse order, like a LIFO stack (last in, first out).
187 unsigned char symbol = FSE_decodeSymbol(&DState, &DStream);
188
189You can retrieve any bitfield you eventually stored into the bitStream (in reverse order)
Yann Collete8c6bb12015-07-26 00:23:57 +0100190Note : maximum allowed nbBits is 25, for 32-bits compatibility
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100191 size_t bitField = BIT_readBits(&DStream, nbBits);
Yann Collet1efa31f2015-07-04 15:56:41 -0800192
Yann Collete8c6bb12015-07-26 00:23:57 +0100193All above operations only read from local register (which size depends on size_t).
Yann Collet1efa31f2015-07-04 15:56:41 -0800194Refueling the register from memory is manually performed by the reload method.
195 endSignal = FSE_reloadDStream(&DStream);
196
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100197BIT_reloadDStream() result tells if there is still some more data to read from DStream.
198BIT_DStream_unfinished : there is still some data left into the DStream.
199BIT_DStream_endOfBuffer : Dstream reached end of buffer. Its container may no longer be completely filled.
200BIT_DStream_completed : Dstream reached its exact end, corresponding in general to decompression completed.
201BIT_DStream_tooFar : Dstream went too far. Decompression result is corrupted.
Yann Collet1efa31f2015-07-04 15:56:41 -0800202
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100203When reaching end of buffer (BIT_DStream_endOfBuffer), progress slowly, notably if you decode multiple symbols per loop,
Yann Collet1efa31f2015-07-04 15:56:41 -0800204to properly detect the exact end of stream.
205After each decoded symbol, check if DStream is fully consumed using this simple test :
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100206 BIT_reloadDStream(&DStream) >= BIT_DStream_completed
Yann Collet1efa31f2015-07-04 15:56:41 -0800207
208When it's done, verify decompression is fully completed, by checking both DStream and the relevant states.
209Checking if DStream has reached its end is performed by :
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100210 BIT_endOfDStream(&DStream);
Yann Colleta7875502015-08-07 15:21:00 +0100211Check also the states. There might be some symbols left there, if some high probability ones (>50%) are possible.
Yann Collet1efa31f2015-07-04 15:56:41 -0800212 FSE_endOfDState(&DState);
213*/
214
215
Yann Collet3b994cb2016-01-06 01:58:37 +0100216/* *****************************************
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100217* FSE unsafe API
Yann Collet3b994cb2016-01-06 01:58:37 +0100218*******************************************/
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100219static unsigned char FSE_decodeSymbolFast(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD);
220/* faster, but works only if nbBits is always >= 1 (otherwise, result will be corrupted) */
Yann Collet4856a002015-01-24 01:58:16 +0100221
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100222
Yann Collet3b994cb2016-01-06 01:58:37 +0100223/* *****************************************
224* Implementation of inlined functions
225*******************************************/
Yann Colletfb810d62016-01-28 00:18:06 +0100226typedef struct {
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100227 int deltaFindState;
228 U32 deltaNbBits;
229} FSE_symbolCompressionTransform; /* total 8 bytes */
230
231MEM_STATIC void FSE_initCState(FSE_CState_t* statePtr, const FSE_CTable* ct)
232{
Yann Collet3b994cb2016-01-06 01:58:37 +0100233 const void* ptr = ct;
234 const U16* u16ptr = (const U16*) ptr;
Yann Collet218bd312016-01-06 02:19:55 +0100235 const U32 tableLog = MEM_read16(ptr);
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100236 statePtr->value = (ptrdiff_t)1<<tableLog;
Yann Collet3b994cb2016-01-06 01:58:37 +0100237 statePtr->stateTable = u16ptr+2;
238 statePtr->symbolTT = ((const U32*)ct + 1 + (tableLog ? (1<<(tableLog-1)) : 1));
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100239 statePtr->stateLog = tableLog;
240}
241
Yann Collete93d6ce2016-01-31 00:58:06 +0100242MEM_STATIC void FSE_initCState2(FSE_CState_t* statePtr, const FSE_CTable* ct, U32 symbol)
243{
244 FSE_initCState(statePtr, ct);
245 {
246 const FSE_symbolCompressionTransform symbolTT = ((const FSE_symbolCompressionTransform*)(statePtr->symbolTT))[symbol];
247 const U16* stateTable = (const U16*)(statePtr->stateTable);
248 U32 nbBitsOut = (U32)((symbolTT.deltaNbBits + (1<<15)) >> 16);
249 statePtr->value = (nbBitsOut << 16) - symbolTT.deltaNbBits;
250 statePtr->value = stateTable[(statePtr->value >> nbBitsOut) + symbolTT.deltaFindState];
251
252 }
253}
254
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100255MEM_STATIC void FSE_encodeSymbol(BIT_CStream_t* bitC, FSE_CState_t* statePtr, U32 symbol)
256{
257 const FSE_symbolCompressionTransform symbolTT = ((const FSE_symbolCompressionTransform*)(statePtr->symbolTT))[symbol];
258 const U16* const stateTable = (const U16*)(statePtr->stateTable);
259 U32 nbBitsOut = (U32)((statePtr->value + symbolTT.deltaNbBits) >> 16);
260 BIT_addBits(bitC, statePtr->value, nbBitsOut);
261 statePtr->value = stateTable[ (statePtr->value >> nbBitsOut) + symbolTT.deltaFindState];
262}
263
264MEM_STATIC void FSE_flushCState(BIT_CStream_t* bitC, const FSE_CState_t* statePtr)
265{
266 BIT_addBits(bitC, statePtr->value, statePtr->stateLog);
267 BIT_flushBits(bitC);
268}
269
270/* decompression */
271
272typedef struct {
273 U16 tableLog;
274 U16 fastMode;
275} FSE_DTableHeader; /* sizeof U32 */
276
277typedef struct
278{
279 unsigned short newState;
280 unsigned char symbol;
281 unsigned char nbBits;
282} FSE_decode_t; /* size == U32 */
283
284MEM_STATIC void FSE_initDState(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD, const FSE_DTable* dt)
285{
Yann Collet3b994cb2016-01-06 01:58:37 +0100286 const void* ptr = dt;
287 const FSE_DTableHeader* const DTableH = (const FSE_DTableHeader*)ptr;
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100288 DStatePtr->state = BIT_readBits(bitD, DTableH->tableLog);
289 BIT_reloadDStream(bitD);
290 DStatePtr->table = dt + 1;
291}
292
Yann Collete93d6ce2016-01-31 00:58:06 +0100293MEM_STATIC size_t FSE_getStateValue(FSE_DState_t* DStatePtr)
294{
295 return DStatePtr->state;
296}
297
298MEM_STATIC BYTE FSE_peakSymbol(FSE_DState_t* DStatePtr)
299{
300 const FSE_decode_t DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state];
301 return DInfo.symbol;
302}
303
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100304MEM_STATIC BYTE FSE_decodeSymbol(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD)
305{
306 const FSE_decode_t DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state];
307 const U32 nbBits = DInfo.nbBits;
308 BYTE symbol = DInfo.symbol;
309 size_t lowBits = BIT_readBits(bitD, nbBits);
310
311 DStatePtr->state = DInfo.newState + lowBits;
312 return symbol;
313}
314
315MEM_STATIC BYTE FSE_decodeSymbolFast(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD)
316{
317 const FSE_decode_t DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state];
318 const U32 nbBits = DInfo.nbBits;
319 BYTE symbol = DInfo.symbol;
320 size_t lowBits = BIT_readBitsFast(bitD, nbBits);
321
322 DStatePtr->state = DInfo.newState + lowBits;
323 return symbol;
324}
325
326MEM_STATIC unsigned FSE_endOfDState(const FSE_DState_t* DStatePtr)
327{
328 return DStatePtr->state == 0;
329}
Yann Collet4856a002015-01-24 01:58:16 +0100330
331
332#if defined (__cplusplus)
333}
334#endif
Yann Colletaa074052015-10-30 11:21:50 +0100335
336#endif /* FSE_STATIC_H */