10c16b537SWarner Losh /* ******************************************************************
237f1f268SConrad Meyer * FSE : Finite State Entropy codec
337f1f268SConrad Meyer * Public Prototypes declaration
4*5ff13fbcSAllan Jude * Copyright (c) Yann Collet, Facebook, Inc.
537f1f268SConrad Meyer *
637f1f268SConrad Meyer * You can contact the author at :
737f1f268SConrad Meyer * - Source repository : https://github.com/Cyan4973/FiniteStateEntropy
837f1f268SConrad Meyer *
937f1f268SConrad Meyer * This source code is licensed under both the BSD-style license (found in the
1037f1f268SConrad Meyer * LICENSE file in the root directory of this source tree) and the GPLv2 (found
1137f1f268SConrad Meyer * in the COPYING file in the root directory of this source tree).
1237f1f268SConrad Meyer * You may select, at your option, one of the above-listed licenses.
130c16b537SWarner Losh ****************************************************************** */
140c16b537SWarner Losh
150c16b537SWarner Losh #if defined (__cplusplus)
160c16b537SWarner Losh extern "C" {
170c16b537SWarner Losh #endif
180c16b537SWarner Losh
190c16b537SWarner Losh #ifndef FSE_H
200c16b537SWarner Losh #define FSE_H
210c16b537SWarner Losh
220c16b537SWarner Losh
230c16b537SWarner Losh /*-*****************************************
240c16b537SWarner Losh * Dependencies
250c16b537SWarner Losh ******************************************/
26f7cd7fe5SConrad Meyer #include "zstd_deps.h" /* size_t, ptrdiff_t */
270c16b537SWarner Losh
280c16b537SWarner Losh
290c16b537SWarner Losh /*-*****************************************
300c16b537SWarner Losh * FSE_PUBLIC_API : control library symbols visibility
310c16b537SWarner Losh ******************************************/
320c16b537SWarner Losh #if defined(FSE_DLL_EXPORT) && (FSE_DLL_EXPORT==1) && defined(__GNUC__) && (__GNUC__ >= 4)
330c16b537SWarner Losh # define FSE_PUBLIC_API __attribute__ ((visibility ("default")))
340c16b537SWarner Losh #elif defined(FSE_DLL_EXPORT) && (FSE_DLL_EXPORT==1) /* Visual expected */
350c16b537SWarner Losh # define FSE_PUBLIC_API __declspec(dllexport)
360c16b537SWarner Losh #elif defined(FSE_DLL_IMPORT) && (FSE_DLL_IMPORT==1)
370c16b537SWarner Losh # define FSE_PUBLIC_API __declspec(dllimport) /* It isn't required but allows to generate better code, saving a function pointer load from the IAT and an indirect jump.*/
380c16b537SWarner Losh #else
390c16b537SWarner Losh # define FSE_PUBLIC_API
400c16b537SWarner Losh #endif
410c16b537SWarner Losh
420c16b537SWarner Losh /*------ Version ------*/
430c16b537SWarner Losh #define FSE_VERSION_MAJOR 0
440c16b537SWarner Losh #define FSE_VERSION_MINOR 9
450c16b537SWarner Losh #define FSE_VERSION_RELEASE 0
460c16b537SWarner Losh
470c16b537SWarner Losh #define FSE_LIB_VERSION FSE_VERSION_MAJOR.FSE_VERSION_MINOR.FSE_VERSION_RELEASE
480c16b537SWarner Losh #define FSE_QUOTE(str) #str
490c16b537SWarner Losh #define FSE_EXPAND_AND_QUOTE(str) FSE_QUOTE(str)
500c16b537SWarner Losh #define FSE_VERSION_STRING FSE_EXPAND_AND_QUOTE(FSE_LIB_VERSION)
510c16b537SWarner Losh
520c16b537SWarner Losh #define FSE_VERSION_NUMBER (FSE_VERSION_MAJOR *100*100 + FSE_VERSION_MINOR *100 + FSE_VERSION_RELEASE)
530c16b537SWarner Losh FSE_PUBLIC_API unsigned FSE_versionNumber(void); /**< library version number; to be used when checking dll version */
540c16b537SWarner Losh
550f743729SConrad Meyer
560c16b537SWarner Losh /*-****************************************
570c16b537SWarner Losh * FSE simple functions
580c16b537SWarner Losh ******************************************/
590c16b537SWarner Losh /*! FSE_compress() :
600c16b537SWarner Losh Compress content of buffer 'src', of size 'srcSize', into destination buffer 'dst'.
610c16b537SWarner Losh 'dst' buffer must be already allocated. Compression runs faster is dstCapacity >= FSE_compressBound(srcSize).
620c16b537SWarner Losh @return : size of compressed data (<= dstCapacity).
630c16b537SWarner Losh Special values : if return == 0, srcData is not compressible => Nothing is stored within dst !!!
640c16b537SWarner Losh if return == 1, srcData is a single byte symbol * srcSize times. Use RLE compression instead.
650c16b537SWarner Losh if FSE_isError(return), compression failed (more details using FSE_getErrorName())
660c16b537SWarner Losh */
670c16b537SWarner Losh FSE_PUBLIC_API size_t FSE_compress(void* dst, size_t dstCapacity,
680c16b537SWarner Losh const void* src, size_t srcSize);
690c16b537SWarner Losh
700c16b537SWarner Losh /*! FSE_decompress():
710c16b537SWarner Losh Decompress FSE data from buffer 'cSrc', of size 'cSrcSize',
720c16b537SWarner Losh into already allocated destination buffer 'dst', of size 'dstCapacity'.
730c16b537SWarner Losh @return : size of regenerated data (<= maxDstSize),
740c16b537SWarner Losh or an error code, which can be tested using FSE_isError() .
750c16b537SWarner Losh
760c16b537SWarner Losh ** Important ** : FSE_decompress() does not decompress non-compressible nor RLE data !!!
770c16b537SWarner Losh Why ? : making this distinction requires a header.
780c16b537SWarner Losh Header management is intentionally delegated to the user layer, which can better manage special cases.
790c16b537SWarner Losh */
800c16b537SWarner Losh FSE_PUBLIC_API size_t FSE_decompress(void* dst, size_t dstCapacity,
810c16b537SWarner Losh const void* cSrc, size_t cSrcSize);
820c16b537SWarner Losh
830c16b537SWarner Losh
840c16b537SWarner Losh /*-*****************************************
850c16b537SWarner Losh * Tool functions
860c16b537SWarner Losh ******************************************/
870c16b537SWarner Losh FSE_PUBLIC_API size_t FSE_compressBound(size_t size); /* maximum compressed size */
880c16b537SWarner Losh
890c16b537SWarner Losh /* Error Management */
900c16b537SWarner Losh FSE_PUBLIC_API unsigned FSE_isError(size_t code); /* tells if a return value is an error code */
910c16b537SWarner Losh FSE_PUBLIC_API const char* FSE_getErrorName(size_t code); /* provides error code string (useful for debugging) */
920c16b537SWarner Losh
930c16b537SWarner Losh
940c16b537SWarner Losh /*-*****************************************
950c16b537SWarner Losh * FSE advanced functions
960c16b537SWarner Losh ******************************************/
970c16b537SWarner Losh /*! FSE_compress2() :
980c16b537SWarner Losh Same as FSE_compress(), but allows the selection of 'maxSymbolValue' and 'tableLog'
990c16b537SWarner Losh Both parameters can be defined as '0' to mean : use default value
1000c16b537SWarner Losh @return : size of compressed data
1010c16b537SWarner Losh Special values : if return == 0, srcData is not compressible => Nothing is stored within cSrc !!!
1020c16b537SWarner Losh if return == 1, srcData is a single byte symbol * srcSize times. Use RLE compression.
1030c16b537SWarner Losh if FSE_isError(return), it's an error code.
1040c16b537SWarner Losh */
1050c16b537SWarner Losh FSE_PUBLIC_API size_t FSE_compress2 (void* dst, size_t dstSize, const void* src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog);
1060c16b537SWarner Losh
1070c16b537SWarner Losh
1080c16b537SWarner Losh /*-*****************************************
1090c16b537SWarner Losh * FSE detailed API
1100c16b537SWarner Losh ******************************************/
1110c16b537SWarner Losh /*!
1120c16b537SWarner Losh FSE_compress() does the following:
1130f743729SConrad Meyer 1. count symbol occurrence from source[] into table count[] (see hist.h)
1140c16b537SWarner Losh 2. normalize counters so that sum(count[]) == Power_of_2 (2^tableLog)
1150c16b537SWarner Losh 3. save normalized counters to memory buffer using writeNCount()
1160c16b537SWarner Losh 4. build encoding table 'CTable' from normalized counters
1170c16b537SWarner Losh 5. encode the data stream using encoding table 'CTable'
1180c16b537SWarner Losh
1190c16b537SWarner Losh FSE_decompress() does the following:
1200c16b537SWarner Losh 1. read normalized counters with readNCount()
1210c16b537SWarner Losh 2. build decoding table 'DTable' from normalized counters
1220c16b537SWarner Losh 3. decode the data stream using decoding table 'DTable'
1230c16b537SWarner Losh
1240c16b537SWarner Losh The following API allows targeting specific sub-functions for advanced tasks.
1250c16b537SWarner Losh For example, it's possible to compress several blocks using the same 'CTable',
1260c16b537SWarner Losh or to save and provide normalized distribution using external method.
1270c16b537SWarner Losh */
1280c16b537SWarner Losh
1290c16b537SWarner Losh /* *** COMPRESSION *** */
1300c16b537SWarner Losh
1310c16b537SWarner Losh /*! FSE_optimalTableLog():
1320c16b537SWarner Losh dynamically downsize 'tableLog' when conditions are met.
1330c16b537SWarner Losh It saves CPU time, by using smaller tables, while preserving or even improving compression ratio.
1340c16b537SWarner Losh @return : recommended tableLog (necessarily <= 'maxTableLog') */
1350c16b537SWarner Losh FSE_PUBLIC_API unsigned FSE_optimalTableLog(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue);
1360c16b537SWarner Losh
1370c16b537SWarner Losh /*! FSE_normalizeCount():
1380c16b537SWarner Losh normalize counts so that sum(count[]) == Power_of_2 (2^tableLog)
1390c16b537SWarner Losh 'normalizedCounter' is a table of short, of minimum size (maxSymbolValue+1).
140f7cd7fe5SConrad Meyer useLowProbCount is a boolean parameter which trades off compressed size for
141f7cd7fe5SConrad Meyer faster header decoding. When it is set to 1, the compressed data will be slightly
142f7cd7fe5SConrad Meyer smaller. And when it is set to 0, FSE_readNCount() and FSE_buildDTable() will be
143f7cd7fe5SConrad Meyer faster. If you are compressing a small amount of data (< 2 KB) then useLowProbCount=0
144f7cd7fe5SConrad Meyer is a good default, since header deserialization makes a big speed difference.
145f7cd7fe5SConrad Meyer Otherwise, useLowProbCount=1 is a good default, since the speed difference is small.
1460c16b537SWarner Losh @return : tableLog,
1470c16b537SWarner Losh or an errorCode, which can be tested using FSE_isError() */
1480f743729SConrad Meyer FSE_PUBLIC_API size_t FSE_normalizeCount(short* normalizedCounter, unsigned tableLog,
149f7cd7fe5SConrad Meyer const unsigned* count, size_t srcSize, unsigned maxSymbolValue, unsigned useLowProbCount);
1500c16b537SWarner Losh
1510c16b537SWarner Losh /*! FSE_NCountWriteBound():
1520c16b537SWarner Losh Provides the maximum possible size of an FSE normalized table, given 'maxSymbolValue' and 'tableLog'.
1530c16b537SWarner Losh Typically useful for allocation purpose. */
1540c16b537SWarner Losh FSE_PUBLIC_API size_t FSE_NCountWriteBound(unsigned maxSymbolValue, unsigned tableLog);
1550c16b537SWarner Losh
1560c16b537SWarner Losh /*! FSE_writeNCount():
1570c16b537SWarner Losh Compactly save 'normalizedCounter' into 'buffer'.
1580c16b537SWarner Losh @return : size of the compressed table,
1590c16b537SWarner Losh or an errorCode, which can be tested using FSE_isError(). */
1600f743729SConrad Meyer FSE_PUBLIC_API size_t FSE_writeNCount (void* buffer, size_t bufferSize,
1610f743729SConrad Meyer const short* normalizedCounter,
1620f743729SConrad Meyer unsigned maxSymbolValue, unsigned tableLog);
1630c16b537SWarner Losh
1640c16b537SWarner Losh /*! Constructor and Destructor of FSE_CTable.
1650c16b537SWarner Losh Note that FSE_CTable size depends on 'tableLog' and 'maxSymbolValue' */
1660c16b537SWarner Losh typedef unsigned FSE_CTable; /* don't allocate that. It's only meant to be more restrictive than void* */
1670c16b537SWarner Losh FSE_PUBLIC_API FSE_CTable* FSE_createCTable (unsigned maxSymbolValue, unsigned tableLog);
1680c16b537SWarner Losh FSE_PUBLIC_API void FSE_freeCTable (FSE_CTable* ct);
1690c16b537SWarner Losh
1700c16b537SWarner Losh /*! FSE_buildCTable():
1710c16b537SWarner Losh Builds `ct`, which must be already allocated, using FSE_createCTable().
1720c16b537SWarner Losh @return : 0, or an errorCode, which can be tested using FSE_isError() */
1730c16b537SWarner Losh FSE_PUBLIC_API size_t FSE_buildCTable(FSE_CTable* ct, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog);
1740c16b537SWarner Losh
1750c16b537SWarner Losh /*! FSE_compress_usingCTable():
1760c16b537SWarner Losh Compress `src` using `ct` into `dst` which must be already allocated.
1770c16b537SWarner Losh @return : size of compressed data (<= `dstCapacity`),
1780c16b537SWarner Losh or 0 if compressed data could not fit into `dst`,
1790c16b537SWarner Losh or an errorCode, which can be tested using FSE_isError() */
1800c16b537SWarner Losh FSE_PUBLIC_API size_t FSE_compress_usingCTable (void* dst, size_t dstCapacity, const void* src, size_t srcSize, const FSE_CTable* ct);
1810c16b537SWarner Losh
1820c16b537SWarner Losh /*!
1830c16b537SWarner Losh Tutorial :
1840c16b537SWarner Losh ----------
1850c16b537SWarner Losh The first step is to count all symbols. FSE_count() does this job very fast.
1860c16b537SWarner Losh Result will be saved into 'count', a table of unsigned int, which must be already allocated, and have 'maxSymbolValuePtr[0]+1' cells.
1870c16b537SWarner Losh 'src' is a table of bytes of size 'srcSize'. All values within 'src' MUST be <= maxSymbolValuePtr[0]
1880c16b537SWarner Losh maxSymbolValuePtr[0] will be updated, with its real value (necessarily <= original value)
1890c16b537SWarner Losh FSE_count() will return the number of occurrence of the most frequent symbol.
1900c16b537SWarner Losh This can be used to know if there is a single symbol within 'src', and to quickly evaluate its compressibility.
1910c16b537SWarner Losh If there is an error, the function will return an ErrorCode (which can be tested using FSE_isError()).
1920c16b537SWarner Losh
1930c16b537SWarner Losh The next step is to normalize the frequencies.
1940c16b537SWarner Losh FSE_normalizeCount() will ensure that sum of frequencies is == 2 ^'tableLog'.
1950c16b537SWarner Losh It also guarantees a minimum of 1 to any Symbol with frequency >= 1.
1960c16b537SWarner Losh You can use 'tableLog'==0 to mean "use default tableLog value".
1970c16b537SWarner Losh If you are unsure of which tableLog value to use, you can ask FSE_optimalTableLog(),
1980c16b537SWarner Losh which will provide the optimal valid tableLog given sourceSize, maxSymbolValue, and a user-defined maximum (0 means "default").
1990c16b537SWarner Losh
2000c16b537SWarner Losh The result of FSE_normalizeCount() will be saved into a table,
2010c16b537SWarner Losh called 'normalizedCounter', which is a table of signed short.
2020c16b537SWarner Losh 'normalizedCounter' must be already allocated, and have at least 'maxSymbolValue+1' cells.
2030c16b537SWarner Losh The return value is tableLog if everything proceeded as expected.
2040c16b537SWarner Losh It is 0 if there is a single symbol within distribution.
2050c16b537SWarner Losh If there is an error (ex: invalid tableLog value), the function will return an ErrorCode (which can be tested using FSE_isError()).
2060c16b537SWarner Losh
2070c16b537SWarner Losh 'normalizedCounter' can be saved in a compact manner to a memory area using FSE_writeNCount().
2080c16b537SWarner Losh 'buffer' must be already allocated.
2090c16b537SWarner Losh For guaranteed success, buffer size must be at least FSE_headerBound().
2100c16b537SWarner Losh The result of the function is the number of bytes written into 'buffer'.
2110c16b537SWarner Losh If there is an error, the function will return an ErrorCode (which can be tested using FSE_isError(); ex : buffer size too small).
2120c16b537SWarner Losh
2130c16b537SWarner Losh 'normalizedCounter' can then be used to create the compression table 'CTable'.
2140c16b537SWarner Losh The space required by 'CTable' must be already allocated, using FSE_createCTable().
2150c16b537SWarner Losh You can then use FSE_buildCTable() to fill 'CTable'.
2160c16b537SWarner Losh If there is an error, both functions will return an ErrorCode (which can be tested using FSE_isError()).
2170c16b537SWarner Losh
2180c16b537SWarner Losh 'CTable' can then be used to compress 'src', with FSE_compress_usingCTable().
2190c16b537SWarner Losh Similar to FSE_count(), the convention is that 'src' is assumed to be a table of char of size 'srcSize'
2200c16b537SWarner Losh The function returns the size of compressed data (without header), necessarily <= `dstCapacity`.
2210c16b537SWarner Losh If it returns '0', compressed data could not fit into 'dst'.
2220c16b537SWarner Losh If there is an error, the function will return an ErrorCode (which can be tested using FSE_isError()).
2230c16b537SWarner Losh */
2240c16b537SWarner Losh
2250c16b537SWarner Losh
2260c16b537SWarner Losh /* *** DECOMPRESSION *** */
2270c16b537SWarner Losh
2280c16b537SWarner Losh /*! FSE_readNCount():
2290c16b537SWarner Losh Read compactly saved 'normalizedCounter' from 'rBuffer'.
2300c16b537SWarner Losh @return : size read from 'rBuffer',
2310c16b537SWarner Losh or an errorCode, which can be tested using FSE_isError().
2320c16b537SWarner Losh maxSymbolValuePtr[0] and tableLogPtr[0] will also be updated with their respective values */
2330f743729SConrad Meyer FSE_PUBLIC_API size_t FSE_readNCount (short* normalizedCounter,
2340f743729SConrad Meyer unsigned* maxSymbolValuePtr, unsigned* tableLogPtr,
2350f743729SConrad Meyer const void* rBuffer, size_t rBuffSize);
2360c16b537SWarner Losh
237f7cd7fe5SConrad Meyer /*! FSE_readNCount_bmi2():
238f7cd7fe5SConrad Meyer * Same as FSE_readNCount() but pass bmi2=1 when your CPU supports BMI2 and 0 otherwise.
239f7cd7fe5SConrad Meyer */
240f7cd7fe5SConrad Meyer FSE_PUBLIC_API size_t FSE_readNCount_bmi2(short* normalizedCounter,
241f7cd7fe5SConrad Meyer unsigned* maxSymbolValuePtr, unsigned* tableLogPtr,
242f7cd7fe5SConrad Meyer const void* rBuffer, size_t rBuffSize, int bmi2);
243f7cd7fe5SConrad Meyer
2440c16b537SWarner Losh /*! Constructor and Destructor of FSE_DTable.
2450c16b537SWarner Losh Note that its size depends on 'tableLog' */
2460c16b537SWarner Losh typedef unsigned FSE_DTable; /* don't allocate that. It's just a way to be more restrictive than void* */
2470c16b537SWarner Losh FSE_PUBLIC_API FSE_DTable* FSE_createDTable(unsigned tableLog);
2480c16b537SWarner Losh FSE_PUBLIC_API void FSE_freeDTable(FSE_DTable* dt);
2490c16b537SWarner Losh
2500c16b537SWarner Losh /*! FSE_buildDTable():
2510c16b537SWarner Losh Builds 'dt', which must be already allocated, using FSE_createDTable().
2520c16b537SWarner Losh return : 0, or an errorCode, which can be tested using FSE_isError() */
2530c16b537SWarner Losh FSE_PUBLIC_API size_t FSE_buildDTable (FSE_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog);
2540c16b537SWarner Losh
2550c16b537SWarner Losh /*! FSE_decompress_usingDTable():
2560c16b537SWarner Losh Decompress compressed source `cSrc` of size `cSrcSize` using `dt`
2570c16b537SWarner Losh into `dst` which must be already allocated.
2580c16b537SWarner Losh @return : size of regenerated data (necessarily <= `dstCapacity`),
2590c16b537SWarner Losh or an errorCode, which can be tested using FSE_isError() */
2600c16b537SWarner Losh FSE_PUBLIC_API size_t FSE_decompress_usingDTable(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, const FSE_DTable* dt);
2610c16b537SWarner Losh
2620c16b537SWarner Losh /*!
2630c16b537SWarner Losh Tutorial :
2640c16b537SWarner Losh ----------
2650c16b537SWarner Losh (Note : these functions only decompress FSE-compressed blocks.
2660c16b537SWarner Losh If block is uncompressed, use memcpy() instead
2670c16b537SWarner Losh If block is a single repeated byte, use memset() instead )
2680c16b537SWarner Losh
2690c16b537SWarner Losh The first step is to obtain the normalized frequencies of symbols.
2700c16b537SWarner Losh This can be performed by FSE_readNCount() if it was saved using FSE_writeNCount().
2710c16b537SWarner Losh 'normalizedCounter' must be already allocated, and have at least 'maxSymbolValuePtr[0]+1' cells of signed short.
2720c16b537SWarner Losh In practice, that means it's necessary to know 'maxSymbolValue' beforehand,
2730c16b537SWarner Losh or size the table to handle worst case situations (typically 256).
2740c16b537SWarner Losh FSE_readNCount() will provide 'tableLog' and 'maxSymbolValue'.
2750c16b537SWarner Losh The result of FSE_readNCount() is the number of bytes read from 'rBuffer'.
2760c16b537SWarner Losh Note that 'rBufferSize' must be at least 4 bytes, even if useful information is less than that.
2770c16b537SWarner Losh If there is an error, the function will return an error code, which can be tested using FSE_isError().
2780c16b537SWarner Losh
2790c16b537SWarner Losh The next step is to build the decompression tables 'FSE_DTable' from 'normalizedCounter'.
2800c16b537SWarner Losh This is performed by the function FSE_buildDTable().
2810c16b537SWarner Losh The space required by 'FSE_DTable' must be already allocated using FSE_createDTable().
2820c16b537SWarner Losh If there is an error, the function will return an error code, which can be tested using FSE_isError().
2830c16b537SWarner Losh
2840c16b537SWarner Losh `FSE_DTable` can then be used to decompress `cSrc`, with FSE_decompress_usingDTable().
2850c16b537SWarner Losh `cSrcSize` must be strictly correct, otherwise decompression will fail.
2860c16b537SWarner Losh FSE_decompress_usingDTable() result will tell how many bytes were regenerated (<=`dstCapacity`).
2870c16b537SWarner Losh If there is an error, the function will return an error code, which can be tested using FSE_isError(). (ex: dst buffer too small)
2880c16b537SWarner Losh */
2890c16b537SWarner Losh
2900c16b537SWarner Losh #endif /* FSE_H */
2910c16b537SWarner Losh
2920c16b537SWarner Losh #if defined(FSE_STATIC_LINKING_ONLY) && !defined(FSE_H_FSE_STATIC_LINKING_ONLY)
2930c16b537SWarner Losh #define FSE_H_FSE_STATIC_LINKING_ONLY
2940c16b537SWarner Losh
2950c16b537SWarner Losh /* *** Dependency *** */
2960c16b537SWarner Losh #include "bitstream.h"
2970c16b537SWarner Losh
2980c16b537SWarner Losh
2990c16b537SWarner Losh /* *****************************************
3000c16b537SWarner Losh * Static allocation
3010c16b537SWarner Losh *******************************************/
3020c16b537SWarner Losh /* FSE buffer bounds */
3030c16b537SWarner Losh #define FSE_NCOUNTBOUND 512
304f7cd7fe5SConrad Meyer #define FSE_BLOCKBOUND(size) ((size) + ((size)>>7) + 4 /* fse states */ + sizeof(size_t) /* bitContainer */)
3050c16b537SWarner Losh #define FSE_COMPRESSBOUND(size) (FSE_NCOUNTBOUND + FSE_BLOCKBOUND(size)) /* Macro version, useful for static allocation */
3060c16b537SWarner Losh
3070c16b537SWarner Losh /* It is possible to statically allocate FSE CTable/DTable as a table of FSE_CTable/FSE_DTable using below macros */
308f7cd7fe5SConrad Meyer #define FSE_CTABLE_SIZE_U32(maxTableLog, maxSymbolValue) (1 + (1<<((maxTableLog)-1)) + (((maxSymbolValue)+1)*2))
309f7cd7fe5SConrad Meyer #define FSE_DTABLE_SIZE_U32(maxTableLog) (1 + (1<<(maxTableLog)))
3100c16b537SWarner Losh
3110c16b537SWarner Losh /* or use the size to malloc() space directly. Pay attention to alignment restrictions though */
3120c16b537SWarner Losh #define FSE_CTABLE_SIZE(maxTableLog, maxSymbolValue) (FSE_CTABLE_SIZE_U32(maxTableLog, maxSymbolValue) * sizeof(FSE_CTable))
3130c16b537SWarner Losh #define FSE_DTABLE_SIZE(maxTableLog) (FSE_DTABLE_SIZE_U32(maxTableLog) * sizeof(FSE_DTable))
3140c16b537SWarner Losh
3150c16b537SWarner Losh
3160c16b537SWarner Losh /* *****************************************
3170c16b537SWarner Losh * FSE advanced API
3180f743729SConrad Meyer ***************************************** */
3190c16b537SWarner Losh
3200c16b537SWarner Losh unsigned FSE_optimalTableLog_internal(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue, unsigned minus);
3210c16b537SWarner Losh /**< same as FSE_optimalTableLog(), which used `minus==2` */
3220c16b537SWarner Losh
3230c16b537SWarner Losh /* FSE_compress_wksp() :
3240c16b537SWarner Losh * Same as FSE_compress2(), but using an externally allocated scratch buffer (`workSpace`).
325f7cd7fe5SConrad Meyer * FSE_COMPRESS_WKSP_SIZE_U32() provides the minimum size required for `workSpace` as a table of FSE_CTable.
3260c16b537SWarner Losh */
327f7cd7fe5SConrad Meyer #define FSE_COMPRESS_WKSP_SIZE_U32(maxTableLog, maxSymbolValue) ( FSE_CTABLE_SIZE_U32(maxTableLog, maxSymbolValue) + ((maxTableLog > 12) ? (1 << (maxTableLog - 2)) : 1024) )
3280c16b537SWarner Losh 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);
3290c16b537SWarner Losh
3300c16b537SWarner Losh size_t FSE_buildCTable_raw (FSE_CTable* ct, unsigned nbBits);
3310c16b537SWarner Losh /**< build a fake FSE_CTable, designed for a flat distribution, where each symbol uses nbBits */
3320c16b537SWarner Losh
3330c16b537SWarner Losh size_t FSE_buildCTable_rle (FSE_CTable* ct, unsigned char symbolValue);
3340c16b537SWarner Losh /**< build a fake FSE_CTable, designed to compress always the same symbolValue */
3350c16b537SWarner Losh
3360c16b537SWarner Losh /* FSE_buildCTable_wksp() :
3370c16b537SWarner Losh * Same as FSE_buildCTable(), but using an externally allocated scratch buffer (`workSpace`).
338f7cd7fe5SConrad Meyer * `wkspSize` must be >= `FSE_BUILD_CTABLE_WORKSPACE_SIZE_U32(maxSymbolValue, tableLog)` of `unsigned`.
339*5ff13fbcSAllan Jude * See FSE_buildCTable_wksp() for breakdown of workspace usage.
3400c16b537SWarner Losh */
341*5ff13fbcSAllan Jude #define FSE_BUILD_CTABLE_WORKSPACE_SIZE_U32(maxSymbolValue, tableLog) (((maxSymbolValue + 2) + (1ull << (tableLog)))/2 + sizeof(U64)/sizeof(U32) /* additional 8 bytes for potential table overwrite */)
342f7cd7fe5SConrad Meyer #define FSE_BUILD_CTABLE_WORKSPACE_SIZE(maxSymbolValue, tableLog) (sizeof(unsigned) * FSE_BUILD_CTABLE_WORKSPACE_SIZE_U32(maxSymbolValue, tableLog))
3430c16b537SWarner Losh size_t FSE_buildCTable_wksp(FSE_CTable* ct, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog, void* workSpace, size_t wkspSize);
3440c16b537SWarner Losh
345f7cd7fe5SConrad Meyer #define FSE_BUILD_DTABLE_WKSP_SIZE(maxTableLog, maxSymbolValue) (sizeof(short) * (maxSymbolValue + 1) + (1ULL << maxTableLog) + 8)
346f7cd7fe5SConrad Meyer #define FSE_BUILD_DTABLE_WKSP_SIZE_U32(maxTableLog, maxSymbolValue) ((FSE_BUILD_DTABLE_WKSP_SIZE(maxTableLog, maxSymbolValue) + sizeof(unsigned) - 1) / sizeof(unsigned))
347f7cd7fe5SConrad Meyer FSE_PUBLIC_API size_t FSE_buildDTable_wksp(FSE_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog, void* workSpace, size_t wkspSize);
348f7cd7fe5SConrad Meyer /**< Same as FSE_buildDTable(), using an externally allocated `workspace` produced with `FSE_BUILD_DTABLE_WKSP_SIZE_U32(maxSymbolValue)` */
349f7cd7fe5SConrad Meyer
3500c16b537SWarner Losh size_t FSE_buildDTable_raw (FSE_DTable* dt, unsigned nbBits);
3510c16b537SWarner Losh /**< build a fake FSE_DTable, designed to read a flat distribution where each symbol uses nbBits */
3520c16b537SWarner Losh
3530c16b537SWarner Losh size_t FSE_buildDTable_rle (FSE_DTable* dt, unsigned char symbolValue);
3540c16b537SWarner Losh /**< build a fake FSE_DTable, designed to always generate the same symbolValue */
3550c16b537SWarner Losh
356*5ff13fbcSAllan Jude #define FSE_DECOMPRESS_WKSP_SIZE_U32(maxTableLog, maxSymbolValue) (FSE_DTABLE_SIZE_U32(maxTableLog) + FSE_BUILD_DTABLE_WKSP_SIZE_U32(maxTableLog, maxSymbolValue) + (FSE_MAX_SYMBOL_VALUE + 1) / 2 + 1)
357f7cd7fe5SConrad Meyer #define FSE_DECOMPRESS_WKSP_SIZE(maxTableLog, maxSymbolValue) (FSE_DECOMPRESS_WKSP_SIZE_U32(maxTableLog, maxSymbolValue) * sizeof(unsigned))
358f7cd7fe5SConrad Meyer size_t FSE_decompress_wksp(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, unsigned maxLog, void* workSpace, size_t wkspSize);
359f7cd7fe5SConrad Meyer /**< same as FSE_decompress(), using an externally allocated `workSpace` produced with `FSE_DECOMPRESS_WKSP_SIZE_U32(maxLog, maxSymbolValue)` */
360f7cd7fe5SConrad Meyer
361f7cd7fe5SConrad Meyer size_t FSE_decompress_wksp_bmi2(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, unsigned maxLog, void* workSpace, size_t wkspSize, int bmi2);
362f7cd7fe5SConrad Meyer /**< Same as FSE_decompress_wksp() but with dynamic BMI2 support. Pass 1 if your CPU supports BMI2 or 0 if it doesn't. */
3630c16b537SWarner Losh
3640c16b537SWarner Losh typedef enum {
3650c16b537SWarner Losh FSE_repeat_none, /**< Cannot use the previous table */
3660c16b537SWarner Losh FSE_repeat_check, /**< Can use the previous table but it must be checked */
3672b9c00cbSConrad Meyer FSE_repeat_valid /**< Can use the previous table and it is assumed to be valid */
3680c16b537SWarner Losh } FSE_repeat;
3690c16b537SWarner Losh
3700c16b537SWarner Losh /* *****************************************
3710c16b537SWarner Losh * FSE symbol compression API
3720c16b537SWarner Losh *******************************************/
3730c16b537SWarner Losh /*!
3740c16b537SWarner Losh This API consists of small unitary functions, which highly benefit from being inlined.
3750c16b537SWarner Losh Hence their body are included in next section.
3760c16b537SWarner Losh */
3770c16b537SWarner Losh typedef struct {
3780c16b537SWarner Losh ptrdiff_t value;
3790c16b537SWarner Losh const void* stateTable;
3800c16b537SWarner Losh const void* symbolTT;
3810c16b537SWarner Losh unsigned stateLog;
3820c16b537SWarner Losh } FSE_CState_t;
3830c16b537SWarner Losh
3840c16b537SWarner Losh static void FSE_initCState(FSE_CState_t* CStatePtr, const FSE_CTable* ct);
3850c16b537SWarner Losh
3860c16b537SWarner Losh static void FSE_encodeSymbol(BIT_CStream_t* bitC, FSE_CState_t* CStatePtr, unsigned symbol);
3870c16b537SWarner Losh
3880c16b537SWarner Losh static void FSE_flushCState(BIT_CStream_t* bitC, const FSE_CState_t* CStatePtr);
3890c16b537SWarner Losh
3900c16b537SWarner Losh /**<
3910c16b537SWarner Losh These functions are inner components of FSE_compress_usingCTable().
3920c16b537SWarner Losh They allow the creation of custom streams, mixing multiple tables and bit sources.
3930c16b537SWarner Losh
3940c16b537SWarner Losh A key property to keep in mind is that encoding and decoding are done **in reverse direction**.
3950c16b537SWarner Losh So the first symbol you will encode is the last you will decode, like a LIFO stack.
3960c16b537SWarner Losh
3970c16b537SWarner Losh You will need a few variables to track your CStream. They are :
3980c16b537SWarner Losh
3990c16b537SWarner Losh FSE_CTable ct; // Provided by FSE_buildCTable()
4000c16b537SWarner Losh BIT_CStream_t bitStream; // bitStream tracking structure
4010c16b537SWarner Losh FSE_CState_t state; // State tracking structure (can have several)
4020c16b537SWarner Losh
4030c16b537SWarner Losh
4040c16b537SWarner Losh The first thing to do is to init bitStream and state.
4050c16b537SWarner Losh size_t errorCode = BIT_initCStream(&bitStream, dstBuffer, maxDstSize);
4060c16b537SWarner Losh FSE_initCState(&state, ct);
4070c16b537SWarner Losh
4080c16b537SWarner Losh Note that BIT_initCStream() can produce an error code, so its result should be tested, using FSE_isError();
4090c16b537SWarner Losh You can then encode your input data, byte after byte.
4100c16b537SWarner Losh FSE_encodeSymbol() outputs a maximum of 'tableLog' bits at a time.
4110c16b537SWarner Losh Remember decoding will be done in reverse direction.
4120c16b537SWarner Losh FSE_encodeByte(&bitStream, &state, symbol);
4130c16b537SWarner Losh
4140c16b537SWarner Losh At any time, you can also add any bit sequence.
4150c16b537SWarner Losh Note : maximum allowed nbBits is 25, for compatibility with 32-bits decoders
4160c16b537SWarner Losh BIT_addBits(&bitStream, bitField, nbBits);
4170c16b537SWarner Losh
4180c16b537SWarner Losh The above methods don't commit data to memory, they just store it into local register, for speed.
4190c16b537SWarner Losh Local register size is 64-bits on 64-bits systems, 32-bits on 32-bits systems (size_t).
4200c16b537SWarner Losh Writing data to memory is a manual operation, performed by the flushBits function.
4210c16b537SWarner Losh BIT_flushBits(&bitStream);
4220c16b537SWarner Losh
4230c16b537SWarner Losh Your last FSE encoding operation shall be to flush your last state value(s).
4240c16b537SWarner Losh FSE_flushState(&bitStream, &state);
4250c16b537SWarner Losh
4260c16b537SWarner Losh Finally, you must close the bitStream.
4270c16b537SWarner Losh The function returns the size of CStream in bytes.
4280c16b537SWarner Losh If data couldn't fit into dstBuffer, it will return a 0 ( == not compressible)
4290c16b537SWarner Losh If there is an error, it returns an errorCode (which can be tested using FSE_isError()).
4300c16b537SWarner Losh size_t size = BIT_closeCStream(&bitStream);
4310c16b537SWarner Losh */
4320c16b537SWarner Losh
4330c16b537SWarner Losh
4340c16b537SWarner Losh /* *****************************************
4350c16b537SWarner Losh * FSE symbol decompression API
4360c16b537SWarner Losh *******************************************/
4370c16b537SWarner Losh typedef struct {
4380c16b537SWarner Losh size_t state;
4390c16b537SWarner Losh const void* table; /* precise table may vary, depending on U16 */
4400c16b537SWarner Losh } FSE_DState_t;
4410c16b537SWarner Losh
4420c16b537SWarner Losh
4430c16b537SWarner Losh static void FSE_initDState(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD, const FSE_DTable* dt);
4440c16b537SWarner Losh
4450c16b537SWarner Losh static unsigned char FSE_decodeSymbol(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD);
4460c16b537SWarner Losh
4470c16b537SWarner Losh static unsigned FSE_endOfDState(const FSE_DState_t* DStatePtr);
4480c16b537SWarner Losh
4490c16b537SWarner Losh /**<
4500c16b537SWarner Losh Let's now decompose FSE_decompress_usingDTable() into its unitary components.
4510c16b537SWarner Losh You will decode FSE-encoded symbols from the bitStream,
4520c16b537SWarner Losh and also any other bitFields you put in, **in reverse order**.
4530c16b537SWarner Losh
4540c16b537SWarner Losh You will need a few variables to track your bitStream. They are :
4550c16b537SWarner Losh
4560c16b537SWarner Losh BIT_DStream_t DStream; // Stream context
4570c16b537SWarner Losh FSE_DState_t DState; // State context. Multiple ones are possible
4580c16b537SWarner Losh FSE_DTable* DTablePtr; // Decoding table, provided by FSE_buildDTable()
4590c16b537SWarner Losh
4600c16b537SWarner Losh The first thing to do is to init the bitStream.
4610c16b537SWarner Losh errorCode = BIT_initDStream(&DStream, srcBuffer, srcSize);
4620c16b537SWarner Losh
4630c16b537SWarner Losh You should then retrieve your initial state(s)
4640c16b537SWarner Losh (in reverse flushing order if you have several ones) :
4650c16b537SWarner Losh errorCode = FSE_initDState(&DState, &DStream, DTablePtr);
4660c16b537SWarner Losh
4670c16b537SWarner Losh You can then decode your data, symbol after symbol.
4680c16b537SWarner Losh For information the maximum number of bits read by FSE_decodeSymbol() is 'tableLog'.
4690c16b537SWarner Losh Keep in mind that symbols are decoded in reverse order, like a LIFO stack (last in, first out).
4700c16b537SWarner Losh unsigned char symbol = FSE_decodeSymbol(&DState, &DStream);
4710c16b537SWarner Losh
4720c16b537SWarner Losh You can retrieve any bitfield you eventually stored into the bitStream (in reverse order)
4730c16b537SWarner Losh Note : maximum allowed nbBits is 25, for 32-bits compatibility
4740c16b537SWarner Losh size_t bitField = BIT_readBits(&DStream, nbBits);
4750c16b537SWarner Losh
4760c16b537SWarner Losh All above operations only read from local register (which size depends on size_t).
4770c16b537SWarner Losh Refueling the register from memory is manually performed by the reload method.
4780c16b537SWarner Losh endSignal = FSE_reloadDStream(&DStream);
4790c16b537SWarner Losh
4800c16b537SWarner Losh BIT_reloadDStream() result tells if there is still some more data to read from DStream.
4810c16b537SWarner Losh BIT_DStream_unfinished : there is still some data left into the DStream.
4820c16b537SWarner Losh BIT_DStream_endOfBuffer : Dstream reached end of buffer. Its container may no longer be completely filled.
4830c16b537SWarner Losh BIT_DStream_completed : Dstream reached its exact end, corresponding in general to decompression completed.
4840c16b537SWarner Losh BIT_DStream_tooFar : Dstream went too far. Decompression result is corrupted.
4850c16b537SWarner Losh
4860c16b537SWarner Losh When reaching end of buffer (BIT_DStream_endOfBuffer), progress slowly, notably if you decode multiple symbols per loop,
4870c16b537SWarner Losh to properly detect the exact end of stream.
4880c16b537SWarner Losh After each decoded symbol, check if DStream is fully consumed using this simple test :
4890c16b537SWarner Losh BIT_reloadDStream(&DStream) >= BIT_DStream_completed
4900c16b537SWarner Losh
4910c16b537SWarner Losh When it's done, verify decompression is fully completed, by checking both DStream and the relevant states.
4920c16b537SWarner Losh Checking if DStream has reached its end is performed by :
4930c16b537SWarner Losh BIT_endOfDStream(&DStream);
4940c16b537SWarner Losh Check also the states. There might be some symbols left there, if some high probability ones (>50%) are possible.
4950c16b537SWarner Losh FSE_endOfDState(&DState);
4960c16b537SWarner Losh */
4970c16b537SWarner Losh
4980c16b537SWarner Losh
4990c16b537SWarner Losh /* *****************************************
5000c16b537SWarner Losh * FSE unsafe API
5010c16b537SWarner Losh *******************************************/
5020c16b537SWarner Losh static unsigned char FSE_decodeSymbolFast(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD);
5030c16b537SWarner Losh /* faster, but works only if nbBits is always >= 1 (otherwise, result will be corrupted) */
5040c16b537SWarner Losh
5050c16b537SWarner Losh
5060c16b537SWarner Losh /* *****************************************
5070c16b537SWarner Losh * Implementation of inlined functions
5080c16b537SWarner Losh *******************************************/
5090c16b537SWarner Losh typedef struct {
5100c16b537SWarner Losh int deltaFindState;
5110c16b537SWarner Losh U32 deltaNbBits;
5120c16b537SWarner Losh } FSE_symbolCompressionTransform; /* total 8 bytes */
5130c16b537SWarner Losh
FSE_initCState(FSE_CState_t * statePtr,const FSE_CTable * ct)5140c16b537SWarner Losh MEM_STATIC void FSE_initCState(FSE_CState_t* statePtr, const FSE_CTable* ct)
5150c16b537SWarner Losh {
5160c16b537SWarner Losh const void* ptr = ct;
5170c16b537SWarner Losh const U16* u16ptr = (const U16*) ptr;
5180c16b537SWarner Losh const U32 tableLog = MEM_read16(ptr);
5190c16b537SWarner Losh statePtr->value = (ptrdiff_t)1<<tableLog;
5200c16b537SWarner Losh statePtr->stateTable = u16ptr+2;
521a0483764SConrad Meyer statePtr->symbolTT = ct + 1 + (tableLog ? (1<<(tableLog-1)) : 1);
5220c16b537SWarner Losh statePtr->stateLog = tableLog;
5230c16b537SWarner Losh }
5240c16b537SWarner Losh
5250c16b537SWarner Losh
5260c16b537SWarner Losh /*! FSE_initCState2() :
5270c16b537SWarner Losh * Same as FSE_initCState(), but the first symbol to include (which will be the last to be read)
5280c16b537SWarner Losh * uses the smallest state value possible, saving the cost of this symbol */
FSE_initCState2(FSE_CState_t * statePtr,const FSE_CTable * ct,U32 symbol)5290c16b537SWarner Losh MEM_STATIC void FSE_initCState2(FSE_CState_t* statePtr, const FSE_CTable* ct, U32 symbol)
5300c16b537SWarner Losh {
5310c16b537SWarner Losh FSE_initCState(statePtr, ct);
5320c16b537SWarner Losh { const FSE_symbolCompressionTransform symbolTT = ((const FSE_symbolCompressionTransform*)(statePtr->symbolTT))[symbol];
5330c16b537SWarner Losh const U16* stateTable = (const U16*)(statePtr->stateTable);
5340c16b537SWarner Losh U32 nbBitsOut = (U32)((symbolTT.deltaNbBits + (1<<15)) >> 16);
5350c16b537SWarner Losh statePtr->value = (nbBitsOut << 16) - symbolTT.deltaNbBits;
5360c16b537SWarner Losh statePtr->value = stateTable[(statePtr->value >> nbBitsOut) + symbolTT.deltaFindState];
5370c16b537SWarner Losh }
5380c16b537SWarner Losh }
5390c16b537SWarner Losh
FSE_encodeSymbol(BIT_CStream_t * bitC,FSE_CState_t * statePtr,unsigned symbol)540a0483764SConrad Meyer MEM_STATIC void FSE_encodeSymbol(BIT_CStream_t* bitC, FSE_CState_t* statePtr, unsigned symbol)
5410c16b537SWarner Losh {
5420c16b537SWarner Losh FSE_symbolCompressionTransform const symbolTT = ((const FSE_symbolCompressionTransform*)(statePtr->symbolTT))[symbol];
5430c16b537SWarner Losh const U16* const stateTable = (const U16*)(statePtr->stateTable);
5440c16b537SWarner Losh U32 const nbBitsOut = (U32)((statePtr->value + symbolTT.deltaNbBits) >> 16);
5450c16b537SWarner Losh BIT_addBits(bitC, statePtr->value, nbBitsOut);
5460c16b537SWarner Losh statePtr->value = stateTable[ (statePtr->value >> nbBitsOut) + symbolTT.deltaFindState];
5470c16b537SWarner Losh }
5480c16b537SWarner Losh
FSE_flushCState(BIT_CStream_t * bitC,const FSE_CState_t * statePtr)5490c16b537SWarner Losh MEM_STATIC void FSE_flushCState(BIT_CStream_t* bitC, const FSE_CState_t* statePtr)
5500c16b537SWarner Losh {
5510c16b537SWarner Losh BIT_addBits(bitC, statePtr->value, statePtr->stateLog);
5520c16b537SWarner Losh BIT_flushBits(bitC);
5530c16b537SWarner Losh }
5540c16b537SWarner Losh
5550c16b537SWarner Losh
5560f743729SConrad Meyer /* FSE_getMaxNbBits() :
5570f743729SConrad Meyer * Approximate maximum cost of a symbol, in bits.
5580f743729SConrad Meyer * Fractional get rounded up (i.e : a symbol with a normalized frequency of 3 gives the same result as a frequency of 2)
5590f743729SConrad Meyer * note 1 : assume symbolValue is valid (<= maxSymbolValue)
5600f743729SConrad Meyer * note 2 : if freq[symbolValue]==0, @return a fake cost of tableLog+1 bits */
FSE_getMaxNbBits(const void * symbolTTPtr,U32 symbolValue)5610f743729SConrad Meyer MEM_STATIC U32 FSE_getMaxNbBits(const void* symbolTTPtr, U32 symbolValue)
5620f743729SConrad Meyer {
5630f743729SConrad Meyer const FSE_symbolCompressionTransform* symbolTT = (const FSE_symbolCompressionTransform*) symbolTTPtr;
5640f743729SConrad Meyer return (symbolTT[symbolValue].deltaNbBits + ((1<<16)-1)) >> 16;
5650f743729SConrad Meyer }
5660f743729SConrad Meyer
5670f743729SConrad Meyer /* FSE_bitCost() :
5680f743729SConrad Meyer * Approximate symbol cost, as fractional value, using fixed-point format (accuracyLog fractional bits)
5690f743729SConrad Meyer * note 1 : assume symbolValue is valid (<= maxSymbolValue)
5700f743729SConrad Meyer * note 2 : if freq[symbolValue]==0, @return a fake cost of tableLog+1 bits */
FSE_bitCost(const void * symbolTTPtr,U32 tableLog,U32 symbolValue,U32 accuracyLog)5710f743729SConrad Meyer MEM_STATIC U32 FSE_bitCost(const void* symbolTTPtr, U32 tableLog, U32 symbolValue, U32 accuracyLog)
5720f743729SConrad Meyer {
5730f743729SConrad Meyer const FSE_symbolCompressionTransform* symbolTT = (const FSE_symbolCompressionTransform*) symbolTTPtr;
5740f743729SConrad Meyer U32 const minNbBits = symbolTT[symbolValue].deltaNbBits >> 16;
5750f743729SConrad Meyer U32 const threshold = (minNbBits+1) << 16;
5760f743729SConrad Meyer assert(tableLog < 16);
5770f743729SConrad Meyer assert(accuracyLog < 31-tableLog); /* ensure enough room for renormalization double shift */
5780f743729SConrad Meyer { U32 const tableSize = 1 << tableLog;
5790f743729SConrad Meyer U32 const deltaFromThreshold = threshold - (symbolTT[symbolValue].deltaNbBits + tableSize);
5800f743729SConrad Meyer U32 const normalizedDeltaFromThreshold = (deltaFromThreshold << accuracyLog) >> tableLog; /* linear interpolation (very approximate) */
5810f743729SConrad Meyer U32 const bitMultiplier = 1 << accuracyLog;
5820f743729SConrad Meyer assert(symbolTT[symbolValue].deltaNbBits + tableSize <= threshold);
5830f743729SConrad Meyer assert(normalizedDeltaFromThreshold <= bitMultiplier);
5840f743729SConrad Meyer return (minNbBits+1)*bitMultiplier - normalizedDeltaFromThreshold;
5850f743729SConrad Meyer }
5860f743729SConrad Meyer }
5870f743729SConrad Meyer
5880f743729SConrad Meyer
5890c16b537SWarner Losh /* ====== Decompression ====== */
5900c16b537SWarner Losh
5910c16b537SWarner Losh typedef struct {
5920c16b537SWarner Losh U16 tableLog;
5930c16b537SWarner Losh U16 fastMode;
5940c16b537SWarner Losh } FSE_DTableHeader; /* sizeof U32 */
5950c16b537SWarner Losh
5960c16b537SWarner Losh typedef struct
5970c16b537SWarner Losh {
5980c16b537SWarner Losh unsigned short newState;
5990c16b537SWarner Losh unsigned char symbol;
6000c16b537SWarner Losh unsigned char nbBits;
6010c16b537SWarner Losh } FSE_decode_t; /* size == U32 */
6020c16b537SWarner Losh
FSE_initDState(FSE_DState_t * DStatePtr,BIT_DStream_t * bitD,const FSE_DTable * dt)6030c16b537SWarner Losh MEM_STATIC void FSE_initDState(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD, const FSE_DTable* dt)
6040c16b537SWarner Losh {
6050c16b537SWarner Losh const void* ptr = dt;
6060c16b537SWarner Losh const FSE_DTableHeader* const DTableH = (const FSE_DTableHeader*)ptr;
6070c16b537SWarner Losh DStatePtr->state = BIT_readBits(bitD, DTableH->tableLog);
6080c16b537SWarner Losh BIT_reloadDStream(bitD);
6090c16b537SWarner Losh DStatePtr->table = dt + 1;
6100c16b537SWarner Losh }
6110c16b537SWarner Losh
FSE_peekSymbol(const FSE_DState_t * DStatePtr)6120c16b537SWarner Losh MEM_STATIC BYTE FSE_peekSymbol(const FSE_DState_t* DStatePtr)
6130c16b537SWarner Losh {
6140c16b537SWarner Losh FSE_decode_t const DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state];
6150c16b537SWarner Losh return DInfo.symbol;
6160c16b537SWarner Losh }
6170c16b537SWarner Losh
FSE_updateState(FSE_DState_t * DStatePtr,BIT_DStream_t * bitD)6180c16b537SWarner Losh MEM_STATIC void FSE_updateState(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD)
6190c16b537SWarner Losh {
6200c16b537SWarner Losh FSE_decode_t const DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state];
6210c16b537SWarner Losh U32 const nbBits = DInfo.nbBits;
6220c16b537SWarner Losh size_t const lowBits = BIT_readBits(bitD, nbBits);
6230c16b537SWarner Losh DStatePtr->state = DInfo.newState + lowBits;
6240c16b537SWarner Losh }
6250c16b537SWarner Losh
FSE_decodeSymbol(FSE_DState_t * DStatePtr,BIT_DStream_t * bitD)6260c16b537SWarner Losh MEM_STATIC BYTE FSE_decodeSymbol(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD)
6270c16b537SWarner Losh {
6280c16b537SWarner Losh FSE_decode_t const DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state];
6290c16b537SWarner Losh U32 const nbBits = DInfo.nbBits;
6300c16b537SWarner Losh BYTE const symbol = DInfo.symbol;
6310c16b537SWarner Losh size_t const lowBits = BIT_readBits(bitD, nbBits);
6320c16b537SWarner Losh
6330c16b537SWarner Losh DStatePtr->state = DInfo.newState + lowBits;
6340c16b537SWarner Losh return symbol;
6350c16b537SWarner Losh }
6360c16b537SWarner Losh
6370c16b537SWarner Losh /*! FSE_decodeSymbolFast() :
6380c16b537SWarner Losh unsafe, only works if no symbol has a probability > 50% */
FSE_decodeSymbolFast(FSE_DState_t * DStatePtr,BIT_DStream_t * bitD)6390c16b537SWarner Losh MEM_STATIC BYTE FSE_decodeSymbolFast(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD)
6400c16b537SWarner Losh {
6410c16b537SWarner Losh FSE_decode_t const DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state];
6420c16b537SWarner Losh U32 const nbBits = DInfo.nbBits;
6430c16b537SWarner Losh BYTE const symbol = DInfo.symbol;
6440c16b537SWarner Losh size_t const lowBits = BIT_readBitsFast(bitD, nbBits);
6450c16b537SWarner Losh
6460c16b537SWarner Losh DStatePtr->state = DInfo.newState + lowBits;
6470c16b537SWarner Losh return symbol;
6480c16b537SWarner Losh }
6490c16b537SWarner Losh
FSE_endOfDState(const FSE_DState_t * DStatePtr)6500c16b537SWarner Losh MEM_STATIC unsigned FSE_endOfDState(const FSE_DState_t* DStatePtr)
6510c16b537SWarner Losh {
6520c16b537SWarner Losh return DStatePtr->state == 0;
6530c16b537SWarner Losh }
6540c16b537SWarner Losh
6550c16b537SWarner Losh
6560c16b537SWarner Losh
6570c16b537SWarner Losh #ifndef FSE_COMMONDEFS_ONLY
6580c16b537SWarner Losh
6590c16b537SWarner Losh /* **************************************************************
6600c16b537SWarner Losh * Tuning parameters
6610c16b537SWarner Losh ****************************************************************/
6620c16b537SWarner Losh /*!MEMORY_USAGE :
6630c16b537SWarner Losh * Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.)
6640c16b537SWarner Losh * Increasing memory usage improves compression ratio
6650c16b537SWarner Losh * Reduced memory usage can improve speed, due to cache effect
6660c16b537SWarner Losh * Recommended max value is 14, for 16KB, which nicely fits into Intel x86 L1 cache */
6670c16b537SWarner Losh #ifndef FSE_MAX_MEMORY_USAGE
6680c16b537SWarner Losh # define FSE_MAX_MEMORY_USAGE 14
6690c16b537SWarner Losh #endif
6700c16b537SWarner Losh #ifndef FSE_DEFAULT_MEMORY_USAGE
6710c16b537SWarner Losh # define FSE_DEFAULT_MEMORY_USAGE 13
6720c16b537SWarner Losh #endif
673f7cd7fe5SConrad Meyer #if (FSE_DEFAULT_MEMORY_USAGE > FSE_MAX_MEMORY_USAGE)
674f7cd7fe5SConrad Meyer # error "FSE_DEFAULT_MEMORY_USAGE must be <= FSE_MAX_MEMORY_USAGE"
675f7cd7fe5SConrad Meyer #endif
6760c16b537SWarner Losh
6770c16b537SWarner Losh /*!FSE_MAX_SYMBOL_VALUE :
6780c16b537SWarner Losh * Maximum symbol value authorized.
6790c16b537SWarner Losh * Required for proper stack allocation */
6800c16b537SWarner Losh #ifndef FSE_MAX_SYMBOL_VALUE
6810c16b537SWarner Losh # define FSE_MAX_SYMBOL_VALUE 255
6820c16b537SWarner Losh #endif
6830c16b537SWarner Losh
6840c16b537SWarner Losh /* **************************************************************
6850c16b537SWarner Losh * template functions type & suffix
6860c16b537SWarner Losh ****************************************************************/
6870c16b537SWarner Losh #define FSE_FUNCTION_TYPE BYTE
6880c16b537SWarner Losh #define FSE_FUNCTION_EXTENSION
6890c16b537SWarner Losh #define FSE_DECODE_TYPE FSE_decode_t
6900c16b537SWarner Losh
6910c16b537SWarner Losh
6920c16b537SWarner Losh #endif /* !FSE_COMMONDEFS_ONLY */
6930c16b537SWarner Losh
6940c16b537SWarner Losh
6950c16b537SWarner Losh /* ***************************************************************
6960c16b537SWarner Losh * Constants
6970c16b537SWarner Losh *****************************************************************/
6980c16b537SWarner Losh #define FSE_MAX_TABLELOG (FSE_MAX_MEMORY_USAGE-2)
6990c16b537SWarner Losh #define FSE_MAX_TABLESIZE (1U<<FSE_MAX_TABLELOG)
7000c16b537SWarner Losh #define FSE_MAXTABLESIZE_MASK (FSE_MAX_TABLESIZE-1)
7010c16b537SWarner Losh #define FSE_DEFAULT_TABLELOG (FSE_DEFAULT_MEMORY_USAGE-2)
7020c16b537SWarner Losh #define FSE_MIN_TABLELOG 5
7030c16b537SWarner Losh
7040c16b537SWarner Losh #define FSE_TABLELOG_ABSOLUTE_MAX 15
7050c16b537SWarner Losh #if FSE_MAX_TABLELOG > FSE_TABLELOG_ABSOLUTE_MAX
7060c16b537SWarner Losh # error "FSE_MAX_TABLELOG > FSE_TABLELOG_ABSOLUTE_MAX is not supported"
7070c16b537SWarner Losh #endif
7080c16b537SWarner Losh
709f7cd7fe5SConrad Meyer #define FSE_TABLESTEP(tableSize) (((tableSize)>>1) + ((tableSize)>>3) + 3)
7100c16b537SWarner Losh
7110c16b537SWarner Losh
7120c16b537SWarner Losh #endif /* FSE_STATIC_LINKING_ONLY */
7130c16b537SWarner Losh
7140c16b537SWarner Losh
7150c16b537SWarner Losh #if defined (__cplusplus)
7160c16b537SWarner Losh }
7170c16b537SWarner Losh #endif
718