162306a36Sopenharmony_ci/* ****************************************************************** 262306a36Sopenharmony_ci * FSE : Finite State Entropy codec 362306a36Sopenharmony_ci * Public Prototypes declaration 462306a36Sopenharmony_ci * Copyright (c) Yann Collet, Facebook, Inc. 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * You can contact the author at : 762306a36Sopenharmony_ci * - Source repository : https://github.com/Cyan4973/FiniteStateEntropy 862306a36Sopenharmony_ci * 962306a36Sopenharmony_ci * This source code is licensed under both the BSD-style license (found in the 1062306a36Sopenharmony_ci * LICENSE file in the root directory of this source tree) and the GPLv2 (found 1162306a36Sopenharmony_ci * in the COPYING file in the root directory of this source tree). 1262306a36Sopenharmony_ci * You may select, at your option, one of the above-listed licenses. 1362306a36Sopenharmony_ci****************************************************************** */ 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci#ifndef FSE_H 1762306a36Sopenharmony_ci#define FSE_H 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci/*-***************************************** 2162306a36Sopenharmony_ci* Dependencies 2262306a36Sopenharmony_ci******************************************/ 2362306a36Sopenharmony_ci#include "zstd_deps.h" /* size_t, ptrdiff_t */ 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci/*-***************************************** 2762306a36Sopenharmony_ci* FSE_PUBLIC_API : control library symbols visibility 2862306a36Sopenharmony_ci******************************************/ 2962306a36Sopenharmony_ci#if defined(FSE_DLL_EXPORT) && (FSE_DLL_EXPORT==1) && defined(__GNUC__) && (__GNUC__ >= 4) 3062306a36Sopenharmony_ci# define FSE_PUBLIC_API __attribute__ ((visibility ("default"))) 3162306a36Sopenharmony_ci#elif defined(FSE_DLL_EXPORT) && (FSE_DLL_EXPORT==1) /* Visual expected */ 3262306a36Sopenharmony_ci# define FSE_PUBLIC_API __declspec(dllexport) 3362306a36Sopenharmony_ci#elif defined(FSE_DLL_IMPORT) && (FSE_DLL_IMPORT==1) 3462306a36Sopenharmony_ci# 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.*/ 3562306a36Sopenharmony_ci#else 3662306a36Sopenharmony_ci# define FSE_PUBLIC_API 3762306a36Sopenharmony_ci#endif 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci/*------ Version ------*/ 4062306a36Sopenharmony_ci#define FSE_VERSION_MAJOR 0 4162306a36Sopenharmony_ci#define FSE_VERSION_MINOR 9 4262306a36Sopenharmony_ci#define FSE_VERSION_RELEASE 0 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci#define FSE_LIB_VERSION FSE_VERSION_MAJOR.FSE_VERSION_MINOR.FSE_VERSION_RELEASE 4562306a36Sopenharmony_ci#define FSE_QUOTE(str) #str 4662306a36Sopenharmony_ci#define FSE_EXPAND_AND_QUOTE(str) FSE_QUOTE(str) 4762306a36Sopenharmony_ci#define FSE_VERSION_STRING FSE_EXPAND_AND_QUOTE(FSE_LIB_VERSION) 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci#define FSE_VERSION_NUMBER (FSE_VERSION_MAJOR *100*100 + FSE_VERSION_MINOR *100 + FSE_VERSION_RELEASE) 5062306a36Sopenharmony_ciFSE_PUBLIC_API unsigned FSE_versionNumber(void); /*< library version number; to be used when checking dll version */ 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci/*-**************************************** 5462306a36Sopenharmony_ci* FSE simple functions 5562306a36Sopenharmony_ci******************************************/ 5662306a36Sopenharmony_ci/*! FSE_compress() : 5762306a36Sopenharmony_ci Compress content of buffer 'src', of size 'srcSize', into destination buffer 'dst'. 5862306a36Sopenharmony_ci 'dst' buffer must be already allocated. Compression runs faster is dstCapacity >= FSE_compressBound(srcSize). 5962306a36Sopenharmony_ci @return : size of compressed data (<= dstCapacity). 6062306a36Sopenharmony_ci Special values : if return == 0, srcData is not compressible => Nothing is stored within dst !!! 6162306a36Sopenharmony_ci if return == 1, srcData is a single byte symbol * srcSize times. Use RLE compression instead. 6262306a36Sopenharmony_ci if FSE_isError(return), compression failed (more details using FSE_getErrorName()) 6362306a36Sopenharmony_ci*/ 6462306a36Sopenharmony_ciFSE_PUBLIC_API size_t FSE_compress(void* dst, size_t dstCapacity, 6562306a36Sopenharmony_ci const void* src, size_t srcSize); 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci/*! FSE_decompress(): 6862306a36Sopenharmony_ci Decompress FSE data from buffer 'cSrc', of size 'cSrcSize', 6962306a36Sopenharmony_ci into already allocated destination buffer 'dst', of size 'dstCapacity'. 7062306a36Sopenharmony_ci @return : size of regenerated data (<= maxDstSize), 7162306a36Sopenharmony_ci or an error code, which can be tested using FSE_isError() . 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci ** Important ** : FSE_decompress() does not decompress non-compressible nor RLE data !!! 7462306a36Sopenharmony_ci Why ? : making this distinction requires a header. 7562306a36Sopenharmony_ci Header management is intentionally delegated to the user layer, which can better manage special cases. 7662306a36Sopenharmony_ci*/ 7762306a36Sopenharmony_ciFSE_PUBLIC_API size_t FSE_decompress(void* dst, size_t dstCapacity, 7862306a36Sopenharmony_ci const void* cSrc, size_t cSrcSize); 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci/*-***************************************** 8262306a36Sopenharmony_ci* Tool functions 8362306a36Sopenharmony_ci******************************************/ 8462306a36Sopenharmony_ciFSE_PUBLIC_API size_t FSE_compressBound(size_t size); /* maximum compressed size */ 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci/* Error Management */ 8762306a36Sopenharmony_ciFSE_PUBLIC_API unsigned FSE_isError(size_t code); /* tells if a return value is an error code */ 8862306a36Sopenharmony_ciFSE_PUBLIC_API const char* FSE_getErrorName(size_t code); /* provides error code string (useful for debugging) */ 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci/*-***************************************** 9262306a36Sopenharmony_ci* FSE advanced functions 9362306a36Sopenharmony_ci******************************************/ 9462306a36Sopenharmony_ci/*! FSE_compress2() : 9562306a36Sopenharmony_ci Same as FSE_compress(), but allows the selection of 'maxSymbolValue' and 'tableLog' 9662306a36Sopenharmony_ci Both parameters can be defined as '0' to mean : use default value 9762306a36Sopenharmony_ci @return : size of compressed data 9862306a36Sopenharmony_ci Special values : if return == 0, srcData is not compressible => Nothing is stored within cSrc !!! 9962306a36Sopenharmony_ci if return == 1, srcData is a single byte symbol * srcSize times. Use RLE compression. 10062306a36Sopenharmony_ci if FSE_isError(return), it's an error code. 10162306a36Sopenharmony_ci*/ 10262306a36Sopenharmony_ciFSE_PUBLIC_API size_t FSE_compress2 (void* dst, size_t dstSize, const void* src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog); 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ci/*-***************************************** 10662306a36Sopenharmony_ci* FSE detailed API 10762306a36Sopenharmony_ci******************************************/ 10862306a36Sopenharmony_ci/*! 10962306a36Sopenharmony_ciFSE_compress() does the following: 11062306a36Sopenharmony_ci1. count symbol occurrence from source[] into table count[] (see hist.h) 11162306a36Sopenharmony_ci2. normalize counters so that sum(count[]) == Power_of_2 (2^tableLog) 11262306a36Sopenharmony_ci3. save normalized counters to memory buffer using writeNCount() 11362306a36Sopenharmony_ci4. build encoding table 'CTable' from normalized counters 11462306a36Sopenharmony_ci5. encode the data stream using encoding table 'CTable' 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ciFSE_decompress() does the following: 11762306a36Sopenharmony_ci1. read normalized counters with readNCount() 11862306a36Sopenharmony_ci2. build decoding table 'DTable' from normalized counters 11962306a36Sopenharmony_ci3. decode the data stream using decoding table 'DTable' 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ciThe following API allows targeting specific sub-functions for advanced tasks. 12262306a36Sopenharmony_ciFor example, it's possible to compress several blocks using the same 'CTable', 12362306a36Sopenharmony_cior to save and provide normalized distribution using external method. 12462306a36Sopenharmony_ci*/ 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_ci/* *** COMPRESSION *** */ 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci/*! FSE_optimalTableLog(): 12962306a36Sopenharmony_ci dynamically downsize 'tableLog' when conditions are met. 13062306a36Sopenharmony_ci It saves CPU time, by using smaller tables, while preserving or even improving compression ratio. 13162306a36Sopenharmony_ci @return : recommended tableLog (necessarily <= 'maxTableLog') */ 13262306a36Sopenharmony_ciFSE_PUBLIC_API unsigned FSE_optimalTableLog(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue); 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ci/*! FSE_normalizeCount(): 13562306a36Sopenharmony_ci normalize counts so that sum(count[]) == Power_of_2 (2^tableLog) 13662306a36Sopenharmony_ci 'normalizedCounter' is a table of short, of minimum size (maxSymbolValue+1). 13762306a36Sopenharmony_ci useLowProbCount is a boolean parameter which trades off compressed size for 13862306a36Sopenharmony_ci faster header decoding. When it is set to 1, the compressed data will be slightly 13962306a36Sopenharmony_ci smaller. And when it is set to 0, FSE_readNCount() and FSE_buildDTable() will be 14062306a36Sopenharmony_ci faster. If you are compressing a small amount of data (< 2 KB) then useLowProbCount=0 14162306a36Sopenharmony_ci is a good default, since header deserialization makes a big speed difference. 14262306a36Sopenharmony_ci Otherwise, useLowProbCount=1 is a good default, since the speed difference is small. 14362306a36Sopenharmony_ci @return : tableLog, 14462306a36Sopenharmony_ci or an errorCode, which can be tested using FSE_isError() */ 14562306a36Sopenharmony_ciFSE_PUBLIC_API size_t FSE_normalizeCount(short* normalizedCounter, unsigned tableLog, 14662306a36Sopenharmony_ci const unsigned* count, size_t srcSize, unsigned maxSymbolValue, unsigned useLowProbCount); 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci/*! FSE_NCountWriteBound(): 14962306a36Sopenharmony_ci Provides the maximum possible size of an FSE normalized table, given 'maxSymbolValue' and 'tableLog'. 15062306a36Sopenharmony_ci Typically useful for allocation purpose. */ 15162306a36Sopenharmony_ciFSE_PUBLIC_API size_t FSE_NCountWriteBound(unsigned maxSymbolValue, unsigned tableLog); 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci/*! FSE_writeNCount(): 15462306a36Sopenharmony_ci Compactly save 'normalizedCounter' into 'buffer'. 15562306a36Sopenharmony_ci @return : size of the compressed table, 15662306a36Sopenharmony_ci or an errorCode, which can be tested using FSE_isError(). */ 15762306a36Sopenharmony_ciFSE_PUBLIC_API size_t FSE_writeNCount (void* buffer, size_t bufferSize, 15862306a36Sopenharmony_ci const short* normalizedCounter, 15962306a36Sopenharmony_ci unsigned maxSymbolValue, unsigned tableLog); 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci/*! Constructor and Destructor of FSE_CTable. 16262306a36Sopenharmony_ci Note that FSE_CTable size depends on 'tableLog' and 'maxSymbolValue' */ 16362306a36Sopenharmony_citypedef unsigned FSE_CTable; /* don't allocate that. It's only meant to be more restrictive than void* */ 16462306a36Sopenharmony_ciFSE_PUBLIC_API FSE_CTable* FSE_createCTable (unsigned maxSymbolValue, unsigned tableLog); 16562306a36Sopenharmony_ciFSE_PUBLIC_API void FSE_freeCTable (FSE_CTable* ct); 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci/*! FSE_buildCTable(): 16862306a36Sopenharmony_ci Builds `ct`, which must be already allocated, using FSE_createCTable(). 16962306a36Sopenharmony_ci @return : 0, or an errorCode, which can be tested using FSE_isError() */ 17062306a36Sopenharmony_ciFSE_PUBLIC_API size_t FSE_buildCTable(FSE_CTable* ct, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog); 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_ci/*! FSE_compress_usingCTable(): 17362306a36Sopenharmony_ci Compress `src` using `ct` into `dst` which must be already allocated. 17462306a36Sopenharmony_ci @return : size of compressed data (<= `dstCapacity`), 17562306a36Sopenharmony_ci or 0 if compressed data could not fit into `dst`, 17662306a36Sopenharmony_ci or an errorCode, which can be tested using FSE_isError() */ 17762306a36Sopenharmony_ciFSE_PUBLIC_API size_t FSE_compress_usingCTable (void* dst, size_t dstCapacity, const void* src, size_t srcSize, const FSE_CTable* ct); 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_ci/*! 18062306a36Sopenharmony_ciTutorial : 18162306a36Sopenharmony_ci---------- 18262306a36Sopenharmony_ciThe first step is to count all symbols. FSE_count() does this job very fast. 18362306a36Sopenharmony_ciResult will be saved into 'count', a table of unsigned int, which must be already allocated, and have 'maxSymbolValuePtr[0]+1' cells. 18462306a36Sopenharmony_ci'src' is a table of bytes of size 'srcSize'. All values within 'src' MUST be <= maxSymbolValuePtr[0] 18562306a36Sopenharmony_cimaxSymbolValuePtr[0] will be updated, with its real value (necessarily <= original value) 18662306a36Sopenharmony_ciFSE_count() will return the number of occurrence of the most frequent symbol. 18762306a36Sopenharmony_ciThis can be used to know if there is a single symbol within 'src', and to quickly evaluate its compressibility. 18862306a36Sopenharmony_ciIf there is an error, the function will return an ErrorCode (which can be tested using FSE_isError()). 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ciThe next step is to normalize the frequencies. 19162306a36Sopenharmony_ciFSE_normalizeCount() will ensure that sum of frequencies is == 2 ^'tableLog'. 19262306a36Sopenharmony_ciIt also guarantees a minimum of 1 to any Symbol with frequency >= 1. 19362306a36Sopenharmony_ciYou can use 'tableLog'==0 to mean "use default tableLog value". 19462306a36Sopenharmony_ciIf you are unsure of which tableLog value to use, you can ask FSE_optimalTableLog(), 19562306a36Sopenharmony_ciwhich will provide the optimal valid tableLog given sourceSize, maxSymbolValue, and a user-defined maximum (0 means "default"). 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ciThe result of FSE_normalizeCount() will be saved into a table, 19862306a36Sopenharmony_cicalled 'normalizedCounter', which is a table of signed short. 19962306a36Sopenharmony_ci'normalizedCounter' must be already allocated, and have at least 'maxSymbolValue+1' cells. 20062306a36Sopenharmony_ciThe return value is tableLog if everything proceeded as expected. 20162306a36Sopenharmony_ciIt is 0 if there is a single symbol within distribution. 20262306a36Sopenharmony_ciIf there is an error (ex: invalid tableLog value), the function will return an ErrorCode (which can be tested using FSE_isError()). 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_ci'normalizedCounter' can be saved in a compact manner to a memory area using FSE_writeNCount(). 20562306a36Sopenharmony_ci'buffer' must be already allocated. 20662306a36Sopenharmony_ciFor guaranteed success, buffer size must be at least FSE_headerBound(). 20762306a36Sopenharmony_ciThe result of the function is the number of bytes written into 'buffer'. 20862306a36Sopenharmony_ciIf there is an error, the function will return an ErrorCode (which can be tested using FSE_isError(); ex : buffer size too small). 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_ci'normalizedCounter' can then be used to create the compression table 'CTable'. 21162306a36Sopenharmony_ciThe space required by 'CTable' must be already allocated, using FSE_createCTable(). 21262306a36Sopenharmony_ciYou can then use FSE_buildCTable() to fill 'CTable'. 21362306a36Sopenharmony_ciIf there is an error, both functions will return an ErrorCode (which can be tested using FSE_isError()). 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_ci'CTable' can then be used to compress 'src', with FSE_compress_usingCTable(). 21662306a36Sopenharmony_ciSimilar to FSE_count(), the convention is that 'src' is assumed to be a table of char of size 'srcSize' 21762306a36Sopenharmony_ciThe function returns the size of compressed data (without header), necessarily <= `dstCapacity`. 21862306a36Sopenharmony_ciIf it returns '0', compressed data could not fit into 'dst'. 21962306a36Sopenharmony_ciIf there is an error, the function will return an ErrorCode (which can be tested using FSE_isError()). 22062306a36Sopenharmony_ci*/ 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_ci 22362306a36Sopenharmony_ci/* *** DECOMPRESSION *** */ 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_ci/*! FSE_readNCount(): 22662306a36Sopenharmony_ci Read compactly saved 'normalizedCounter' from 'rBuffer'. 22762306a36Sopenharmony_ci @return : size read from 'rBuffer', 22862306a36Sopenharmony_ci or an errorCode, which can be tested using FSE_isError(). 22962306a36Sopenharmony_ci maxSymbolValuePtr[0] and tableLogPtr[0] will also be updated with their respective values */ 23062306a36Sopenharmony_ciFSE_PUBLIC_API size_t FSE_readNCount (short* normalizedCounter, 23162306a36Sopenharmony_ci unsigned* maxSymbolValuePtr, unsigned* tableLogPtr, 23262306a36Sopenharmony_ci const void* rBuffer, size_t rBuffSize); 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_ci/*! FSE_readNCount_bmi2(): 23562306a36Sopenharmony_ci * Same as FSE_readNCount() but pass bmi2=1 when your CPU supports BMI2 and 0 otherwise. 23662306a36Sopenharmony_ci */ 23762306a36Sopenharmony_ciFSE_PUBLIC_API size_t FSE_readNCount_bmi2(short* normalizedCounter, 23862306a36Sopenharmony_ci unsigned* maxSymbolValuePtr, unsigned* tableLogPtr, 23962306a36Sopenharmony_ci const void* rBuffer, size_t rBuffSize, int bmi2); 24062306a36Sopenharmony_ci 24162306a36Sopenharmony_ci/*! Constructor and Destructor of FSE_DTable. 24262306a36Sopenharmony_ci Note that its size depends on 'tableLog' */ 24362306a36Sopenharmony_citypedef unsigned FSE_DTable; /* don't allocate that. It's just a way to be more restrictive than void* */ 24462306a36Sopenharmony_ciFSE_PUBLIC_API FSE_DTable* FSE_createDTable(unsigned tableLog); 24562306a36Sopenharmony_ciFSE_PUBLIC_API void FSE_freeDTable(FSE_DTable* dt); 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_ci/*! FSE_buildDTable(): 24862306a36Sopenharmony_ci Builds 'dt', which must be already allocated, using FSE_createDTable(). 24962306a36Sopenharmony_ci return : 0, or an errorCode, which can be tested using FSE_isError() */ 25062306a36Sopenharmony_ciFSE_PUBLIC_API size_t FSE_buildDTable (FSE_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog); 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_ci/*! FSE_decompress_usingDTable(): 25362306a36Sopenharmony_ci Decompress compressed source `cSrc` of size `cSrcSize` using `dt` 25462306a36Sopenharmony_ci into `dst` which must be already allocated. 25562306a36Sopenharmony_ci @return : size of regenerated data (necessarily <= `dstCapacity`), 25662306a36Sopenharmony_ci or an errorCode, which can be tested using FSE_isError() */ 25762306a36Sopenharmony_ciFSE_PUBLIC_API size_t FSE_decompress_usingDTable(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, const FSE_DTable* dt); 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_ci/*! 26062306a36Sopenharmony_ciTutorial : 26162306a36Sopenharmony_ci---------- 26262306a36Sopenharmony_ci(Note : these functions only decompress FSE-compressed blocks. 26362306a36Sopenharmony_ci If block is uncompressed, use memcpy() instead 26462306a36Sopenharmony_ci If block is a single repeated byte, use memset() instead ) 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_ciThe first step is to obtain the normalized frequencies of symbols. 26762306a36Sopenharmony_ciThis can be performed by FSE_readNCount() if it was saved using FSE_writeNCount(). 26862306a36Sopenharmony_ci'normalizedCounter' must be already allocated, and have at least 'maxSymbolValuePtr[0]+1' cells of signed short. 26962306a36Sopenharmony_ciIn practice, that means it's necessary to know 'maxSymbolValue' beforehand, 27062306a36Sopenharmony_cior size the table to handle worst case situations (typically 256). 27162306a36Sopenharmony_ciFSE_readNCount() will provide 'tableLog' and 'maxSymbolValue'. 27262306a36Sopenharmony_ciThe result of FSE_readNCount() is the number of bytes read from 'rBuffer'. 27362306a36Sopenharmony_ciNote that 'rBufferSize' must be at least 4 bytes, even if useful information is less than that. 27462306a36Sopenharmony_ciIf there is an error, the function will return an error code, which can be tested using FSE_isError(). 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_ciThe next step is to build the decompression tables 'FSE_DTable' from 'normalizedCounter'. 27762306a36Sopenharmony_ciThis is performed by the function FSE_buildDTable(). 27862306a36Sopenharmony_ciThe space required by 'FSE_DTable' must be already allocated using FSE_createDTable(). 27962306a36Sopenharmony_ciIf there is an error, the function will return an error code, which can be tested using FSE_isError(). 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_ci`FSE_DTable` can then be used to decompress `cSrc`, with FSE_decompress_usingDTable(). 28262306a36Sopenharmony_ci`cSrcSize` must be strictly correct, otherwise decompression will fail. 28362306a36Sopenharmony_ciFSE_decompress_usingDTable() result will tell how many bytes were regenerated (<=`dstCapacity`). 28462306a36Sopenharmony_ciIf there is an error, the function will return an error code, which can be tested using FSE_isError(). (ex: dst buffer too small) 28562306a36Sopenharmony_ci*/ 28662306a36Sopenharmony_ci 28762306a36Sopenharmony_ci#endif /* FSE_H */ 28862306a36Sopenharmony_ci 28962306a36Sopenharmony_ci#if !defined(FSE_H_FSE_STATIC_LINKING_ONLY) 29062306a36Sopenharmony_ci#define FSE_H_FSE_STATIC_LINKING_ONLY 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_ci/* *** Dependency *** */ 29362306a36Sopenharmony_ci#include "bitstream.h" 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_ci 29662306a36Sopenharmony_ci/* ***************************************** 29762306a36Sopenharmony_ci* Static allocation 29862306a36Sopenharmony_ci*******************************************/ 29962306a36Sopenharmony_ci/* FSE buffer bounds */ 30062306a36Sopenharmony_ci#define FSE_NCOUNTBOUND 512 30162306a36Sopenharmony_ci#define FSE_BLOCKBOUND(size) ((size) + ((size)>>7) + 4 /* fse states */ + sizeof(size_t) /* bitContainer */) 30262306a36Sopenharmony_ci#define FSE_COMPRESSBOUND(size) (FSE_NCOUNTBOUND + FSE_BLOCKBOUND(size)) /* Macro version, useful for static allocation */ 30362306a36Sopenharmony_ci 30462306a36Sopenharmony_ci/* It is possible to statically allocate FSE CTable/DTable as a table of FSE_CTable/FSE_DTable using below macros */ 30562306a36Sopenharmony_ci#define FSE_CTABLE_SIZE_U32(maxTableLog, maxSymbolValue) (1 + (1<<((maxTableLog)-1)) + (((maxSymbolValue)+1)*2)) 30662306a36Sopenharmony_ci#define FSE_DTABLE_SIZE_U32(maxTableLog) (1 + (1<<(maxTableLog))) 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_ci/* or use the size to malloc() space directly. Pay attention to alignment restrictions though */ 30962306a36Sopenharmony_ci#define FSE_CTABLE_SIZE(maxTableLog, maxSymbolValue) (FSE_CTABLE_SIZE_U32(maxTableLog, maxSymbolValue) * sizeof(FSE_CTable)) 31062306a36Sopenharmony_ci#define FSE_DTABLE_SIZE(maxTableLog) (FSE_DTABLE_SIZE_U32(maxTableLog) * sizeof(FSE_DTable)) 31162306a36Sopenharmony_ci 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ci/* ***************************************** 31462306a36Sopenharmony_ci * FSE advanced API 31562306a36Sopenharmony_ci ***************************************** */ 31662306a36Sopenharmony_ci 31762306a36Sopenharmony_ciunsigned FSE_optimalTableLog_internal(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue, unsigned minus); 31862306a36Sopenharmony_ci/*< same as FSE_optimalTableLog(), which used `minus==2` */ 31962306a36Sopenharmony_ci 32062306a36Sopenharmony_ci/* FSE_compress_wksp() : 32162306a36Sopenharmony_ci * Same as FSE_compress2(), but using an externally allocated scratch buffer (`workSpace`). 32262306a36Sopenharmony_ci * FSE_COMPRESS_WKSP_SIZE_U32() provides the minimum size required for `workSpace` as a table of FSE_CTable. 32362306a36Sopenharmony_ci */ 32462306a36Sopenharmony_ci#define FSE_COMPRESS_WKSP_SIZE_U32(maxTableLog, maxSymbolValue) ( FSE_CTABLE_SIZE_U32(maxTableLog, maxSymbolValue) + ((maxTableLog > 12) ? (1 << (maxTableLog - 2)) : 1024) ) 32562306a36Sopenharmony_cisize_t FSE_compress_wksp (void* dst, size_t dstSize, const void* src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog, void* workSpace, size_t wkspSize); 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_cisize_t FSE_buildCTable_raw (FSE_CTable* ct, unsigned nbBits); 32862306a36Sopenharmony_ci/*< build a fake FSE_CTable, designed for a flat distribution, where each symbol uses nbBits */ 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_cisize_t FSE_buildCTable_rle (FSE_CTable* ct, unsigned char symbolValue); 33162306a36Sopenharmony_ci/*< build a fake FSE_CTable, designed to compress always the same symbolValue */ 33262306a36Sopenharmony_ci 33362306a36Sopenharmony_ci/* FSE_buildCTable_wksp() : 33462306a36Sopenharmony_ci * Same as FSE_buildCTable(), but using an externally allocated scratch buffer (`workSpace`). 33562306a36Sopenharmony_ci * `wkspSize` must be >= `FSE_BUILD_CTABLE_WORKSPACE_SIZE_U32(maxSymbolValue, tableLog)` of `unsigned`. 33662306a36Sopenharmony_ci * See FSE_buildCTable_wksp() for breakdown of workspace usage. 33762306a36Sopenharmony_ci */ 33862306a36Sopenharmony_ci#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 */) 33962306a36Sopenharmony_ci#define FSE_BUILD_CTABLE_WORKSPACE_SIZE(maxSymbolValue, tableLog) (sizeof(unsigned) * FSE_BUILD_CTABLE_WORKSPACE_SIZE_U32(maxSymbolValue, tableLog)) 34062306a36Sopenharmony_cisize_t FSE_buildCTable_wksp(FSE_CTable* ct, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog, void* workSpace, size_t wkspSize); 34162306a36Sopenharmony_ci 34262306a36Sopenharmony_ci#define FSE_BUILD_DTABLE_WKSP_SIZE(maxTableLog, maxSymbolValue) (sizeof(short) * (maxSymbolValue + 1) + (1ULL << maxTableLog) + 8) 34362306a36Sopenharmony_ci#define FSE_BUILD_DTABLE_WKSP_SIZE_U32(maxTableLog, maxSymbolValue) ((FSE_BUILD_DTABLE_WKSP_SIZE(maxTableLog, maxSymbolValue) + sizeof(unsigned) - 1) / sizeof(unsigned)) 34462306a36Sopenharmony_ciFSE_PUBLIC_API size_t FSE_buildDTable_wksp(FSE_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog, void* workSpace, size_t wkspSize); 34562306a36Sopenharmony_ci/*< Same as FSE_buildDTable(), using an externally allocated `workspace` produced with `FSE_BUILD_DTABLE_WKSP_SIZE_U32(maxSymbolValue)` */ 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_cisize_t FSE_buildDTable_raw (FSE_DTable* dt, unsigned nbBits); 34862306a36Sopenharmony_ci/*< build a fake FSE_DTable, designed to read a flat distribution where each symbol uses nbBits */ 34962306a36Sopenharmony_ci 35062306a36Sopenharmony_cisize_t FSE_buildDTable_rle (FSE_DTable* dt, unsigned char symbolValue); 35162306a36Sopenharmony_ci/*< build a fake FSE_DTable, designed to always generate the same symbolValue */ 35262306a36Sopenharmony_ci 35362306a36Sopenharmony_ci#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) 35462306a36Sopenharmony_ci#define FSE_DECOMPRESS_WKSP_SIZE(maxTableLog, maxSymbolValue) (FSE_DECOMPRESS_WKSP_SIZE_U32(maxTableLog, maxSymbolValue) * sizeof(unsigned)) 35562306a36Sopenharmony_cisize_t FSE_decompress_wksp(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, unsigned maxLog, void* workSpace, size_t wkspSize); 35662306a36Sopenharmony_ci/*< same as FSE_decompress(), using an externally allocated `workSpace` produced with `FSE_DECOMPRESS_WKSP_SIZE_U32(maxLog, maxSymbolValue)` */ 35762306a36Sopenharmony_ci 35862306a36Sopenharmony_cisize_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); 35962306a36Sopenharmony_ci/*< Same as FSE_decompress_wksp() but with dynamic BMI2 support. Pass 1 if your CPU supports BMI2 or 0 if it doesn't. */ 36062306a36Sopenharmony_ci 36162306a36Sopenharmony_citypedef enum { 36262306a36Sopenharmony_ci FSE_repeat_none, /*< Cannot use the previous table */ 36362306a36Sopenharmony_ci FSE_repeat_check, /*< Can use the previous table but it must be checked */ 36462306a36Sopenharmony_ci FSE_repeat_valid /*< Can use the previous table and it is assumed to be valid */ 36562306a36Sopenharmony_ci } FSE_repeat; 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_ci/* ***************************************** 36862306a36Sopenharmony_ci* FSE symbol compression API 36962306a36Sopenharmony_ci*******************************************/ 37062306a36Sopenharmony_ci/*! 37162306a36Sopenharmony_ci This API consists of small unitary functions, which highly benefit from being inlined. 37262306a36Sopenharmony_ci Hence their body are included in next section. 37362306a36Sopenharmony_ci*/ 37462306a36Sopenharmony_citypedef struct { 37562306a36Sopenharmony_ci ptrdiff_t value; 37662306a36Sopenharmony_ci const void* stateTable; 37762306a36Sopenharmony_ci const void* symbolTT; 37862306a36Sopenharmony_ci unsigned stateLog; 37962306a36Sopenharmony_ci} FSE_CState_t; 38062306a36Sopenharmony_ci 38162306a36Sopenharmony_cistatic void FSE_initCState(FSE_CState_t* CStatePtr, const FSE_CTable* ct); 38262306a36Sopenharmony_ci 38362306a36Sopenharmony_cistatic void FSE_encodeSymbol(BIT_CStream_t* bitC, FSE_CState_t* CStatePtr, unsigned symbol); 38462306a36Sopenharmony_ci 38562306a36Sopenharmony_cistatic void FSE_flushCState(BIT_CStream_t* bitC, const FSE_CState_t* CStatePtr); 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_ci/*< 38862306a36Sopenharmony_ciThese functions are inner components of FSE_compress_usingCTable(). 38962306a36Sopenharmony_ciThey allow the creation of custom streams, mixing multiple tables and bit sources. 39062306a36Sopenharmony_ci 39162306a36Sopenharmony_ciA key property to keep in mind is that encoding and decoding are done **in reverse direction**. 39262306a36Sopenharmony_ciSo the first symbol you will encode is the last you will decode, like a LIFO stack. 39362306a36Sopenharmony_ci 39462306a36Sopenharmony_ciYou will need a few variables to track your CStream. They are : 39562306a36Sopenharmony_ci 39662306a36Sopenharmony_ciFSE_CTable ct; // Provided by FSE_buildCTable() 39762306a36Sopenharmony_ciBIT_CStream_t bitStream; // bitStream tracking structure 39862306a36Sopenharmony_ciFSE_CState_t state; // State tracking structure (can have several) 39962306a36Sopenharmony_ci 40062306a36Sopenharmony_ci 40162306a36Sopenharmony_ciThe first thing to do is to init bitStream and state. 40262306a36Sopenharmony_ci size_t errorCode = BIT_initCStream(&bitStream, dstBuffer, maxDstSize); 40362306a36Sopenharmony_ci FSE_initCState(&state, ct); 40462306a36Sopenharmony_ci 40562306a36Sopenharmony_ciNote that BIT_initCStream() can produce an error code, so its result should be tested, using FSE_isError(); 40662306a36Sopenharmony_ciYou can then encode your input data, byte after byte. 40762306a36Sopenharmony_ciFSE_encodeSymbol() outputs a maximum of 'tableLog' bits at a time. 40862306a36Sopenharmony_ciRemember decoding will be done in reverse direction. 40962306a36Sopenharmony_ci FSE_encodeByte(&bitStream, &state, symbol); 41062306a36Sopenharmony_ci 41162306a36Sopenharmony_ciAt any time, you can also add any bit sequence. 41262306a36Sopenharmony_ciNote : maximum allowed nbBits is 25, for compatibility with 32-bits decoders 41362306a36Sopenharmony_ci BIT_addBits(&bitStream, bitField, nbBits); 41462306a36Sopenharmony_ci 41562306a36Sopenharmony_ciThe above methods don't commit data to memory, they just store it into local register, for speed. 41662306a36Sopenharmony_ciLocal register size is 64-bits on 64-bits systems, 32-bits on 32-bits systems (size_t). 41762306a36Sopenharmony_ciWriting data to memory is a manual operation, performed by the flushBits function. 41862306a36Sopenharmony_ci BIT_flushBits(&bitStream); 41962306a36Sopenharmony_ci 42062306a36Sopenharmony_ciYour last FSE encoding operation shall be to flush your last state value(s). 42162306a36Sopenharmony_ci FSE_flushState(&bitStream, &state); 42262306a36Sopenharmony_ci 42362306a36Sopenharmony_ciFinally, you must close the bitStream. 42462306a36Sopenharmony_ciThe function returns the size of CStream in bytes. 42562306a36Sopenharmony_ciIf data couldn't fit into dstBuffer, it will return a 0 ( == not compressible) 42662306a36Sopenharmony_ciIf there is an error, it returns an errorCode (which can be tested using FSE_isError()). 42762306a36Sopenharmony_ci size_t size = BIT_closeCStream(&bitStream); 42862306a36Sopenharmony_ci*/ 42962306a36Sopenharmony_ci 43062306a36Sopenharmony_ci 43162306a36Sopenharmony_ci/* ***************************************** 43262306a36Sopenharmony_ci* FSE symbol decompression API 43362306a36Sopenharmony_ci*******************************************/ 43462306a36Sopenharmony_citypedef struct { 43562306a36Sopenharmony_ci size_t state; 43662306a36Sopenharmony_ci const void* table; /* precise table may vary, depending on U16 */ 43762306a36Sopenharmony_ci} FSE_DState_t; 43862306a36Sopenharmony_ci 43962306a36Sopenharmony_ci 44062306a36Sopenharmony_cistatic void FSE_initDState(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD, const FSE_DTable* dt); 44162306a36Sopenharmony_ci 44262306a36Sopenharmony_cistatic unsigned char FSE_decodeSymbol(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD); 44362306a36Sopenharmony_ci 44462306a36Sopenharmony_cistatic unsigned FSE_endOfDState(const FSE_DState_t* DStatePtr); 44562306a36Sopenharmony_ci 44662306a36Sopenharmony_ci/*< 44762306a36Sopenharmony_ciLet's now decompose FSE_decompress_usingDTable() into its unitary components. 44862306a36Sopenharmony_ciYou will decode FSE-encoded symbols from the bitStream, 44962306a36Sopenharmony_ciand also any other bitFields you put in, **in reverse order**. 45062306a36Sopenharmony_ci 45162306a36Sopenharmony_ciYou will need a few variables to track your bitStream. They are : 45262306a36Sopenharmony_ci 45362306a36Sopenharmony_ciBIT_DStream_t DStream; // Stream context 45462306a36Sopenharmony_ciFSE_DState_t DState; // State context. Multiple ones are possible 45562306a36Sopenharmony_ciFSE_DTable* DTablePtr; // Decoding table, provided by FSE_buildDTable() 45662306a36Sopenharmony_ci 45762306a36Sopenharmony_ciThe first thing to do is to init the bitStream. 45862306a36Sopenharmony_ci errorCode = BIT_initDStream(&DStream, srcBuffer, srcSize); 45962306a36Sopenharmony_ci 46062306a36Sopenharmony_ciYou should then retrieve your initial state(s) 46162306a36Sopenharmony_ci(in reverse flushing order if you have several ones) : 46262306a36Sopenharmony_ci errorCode = FSE_initDState(&DState, &DStream, DTablePtr); 46362306a36Sopenharmony_ci 46462306a36Sopenharmony_ciYou can then decode your data, symbol after symbol. 46562306a36Sopenharmony_ciFor information the maximum number of bits read by FSE_decodeSymbol() is 'tableLog'. 46662306a36Sopenharmony_ciKeep in mind that symbols are decoded in reverse order, like a LIFO stack (last in, first out). 46762306a36Sopenharmony_ci unsigned char symbol = FSE_decodeSymbol(&DState, &DStream); 46862306a36Sopenharmony_ci 46962306a36Sopenharmony_ciYou can retrieve any bitfield you eventually stored into the bitStream (in reverse order) 47062306a36Sopenharmony_ciNote : maximum allowed nbBits is 25, for 32-bits compatibility 47162306a36Sopenharmony_ci size_t bitField = BIT_readBits(&DStream, nbBits); 47262306a36Sopenharmony_ci 47362306a36Sopenharmony_ciAll above operations only read from local register (which size depends on size_t). 47462306a36Sopenharmony_ciRefueling the register from memory is manually performed by the reload method. 47562306a36Sopenharmony_ci endSignal = FSE_reloadDStream(&DStream); 47662306a36Sopenharmony_ci 47762306a36Sopenharmony_ciBIT_reloadDStream() result tells if there is still some more data to read from DStream. 47862306a36Sopenharmony_ciBIT_DStream_unfinished : there is still some data left into the DStream. 47962306a36Sopenharmony_ciBIT_DStream_endOfBuffer : Dstream reached end of buffer. Its container may no longer be completely filled. 48062306a36Sopenharmony_ciBIT_DStream_completed : Dstream reached its exact end, corresponding in general to decompression completed. 48162306a36Sopenharmony_ciBIT_DStream_tooFar : Dstream went too far. Decompression result is corrupted. 48262306a36Sopenharmony_ci 48362306a36Sopenharmony_ciWhen reaching end of buffer (BIT_DStream_endOfBuffer), progress slowly, notably if you decode multiple symbols per loop, 48462306a36Sopenharmony_cito properly detect the exact end of stream. 48562306a36Sopenharmony_ciAfter each decoded symbol, check if DStream is fully consumed using this simple test : 48662306a36Sopenharmony_ci BIT_reloadDStream(&DStream) >= BIT_DStream_completed 48762306a36Sopenharmony_ci 48862306a36Sopenharmony_ciWhen it's done, verify decompression is fully completed, by checking both DStream and the relevant states. 48962306a36Sopenharmony_ciChecking if DStream has reached its end is performed by : 49062306a36Sopenharmony_ci BIT_endOfDStream(&DStream); 49162306a36Sopenharmony_ciCheck also the states. There might be some symbols left there, if some high probability ones (>50%) are possible. 49262306a36Sopenharmony_ci FSE_endOfDState(&DState); 49362306a36Sopenharmony_ci*/ 49462306a36Sopenharmony_ci 49562306a36Sopenharmony_ci 49662306a36Sopenharmony_ci/* ***************************************** 49762306a36Sopenharmony_ci* FSE unsafe API 49862306a36Sopenharmony_ci*******************************************/ 49962306a36Sopenharmony_cistatic unsigned char FSE_decodeSymbolFast(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD); 50062306a36Sopenharmony_ci/* faster, but works only if nbBits is always >= 1 (otherwise, result will be corrupted) */ 50162306a36Sopenharmony_ci 50262306a36Sopenharmony_ci 50362306a36Sopenharmony_ci/* ***************************************** 50462306a36Sopenharmony_ci* Implementation of inlined functions 50562306a36Sopenharmony_ci*******************************************/ 50662306a36Sopenharmony_citypedef struct { 50762306a36Sopenharmony_ci int deltaFindState; 50862306a36Sopenharmony_ci U32 deltaNbBits; 50962306a36Sopenharmony_ci} FSE_symbolCompressionTransform; /* total 8 bytes */ 51062306a36Sopenharmony_ci 51162306a36Sopenharmony_ciMEM_STATIC void FSE_initCState(FSE_CState_t* statePtr, const FSE_CTable* ct) 51262306a36Sopenharmony_ci{ 51362306a36Sopenharmony_ci const void* ptr = ct; 51462306a36Sopenharmony_ci const U16* u16ptr = (const U16*) ptr; 51562306a36Sopenharmony_ci const U32 tableLog = MEM_read16(ptr); 51662306a36Sopenharmony_ci statePtr->value = (ptrdiff_t)1<<tableLog; 51762306a36Sopenharmony_ci statePtr->stateTable = u16ptr+2; 51862306a36Sopenharmony_ci statePtr->symbolTT = ct + 1 + (tableLog ? (1<<(tableLog-1)) : 1); 51962306a36Sopenharmony_ci statePtr->stateLog = tableLog; 52062306a36Sopenharmony_ci} 52162306a36Sopenharmony_ci 52262306a36Sopenharmony_ci 52362306a36Sopenharmony_ci/*! FSE_initCState2() : 52462306a36Sopenharmony_ci* Same as FSE_initCState(), but the first symbol to include (which will be the last to be read) 52562306a36Sopenharmony_ci* uses the smallest state value possible, saving the cost of this symbol */ 52662306a36Sopenharmony_ciMEM_STATIC void FSE_initCState2(FSE_CState_t* statePtr, const FSE_CTable* ct, U32 symbol) 52762306a36Sopenharmony_ci{ 52862306a36Sopenharmony_ci FSE_initCState(statePtr, ct); 52962306a36Sopenharmony_ci { const FSE_symbolCompressionTransform symbolTT = ((const FSE_symbolCompressionTransform*)(statePtr->symbolTT))[symbol]; 53062306a36Sopenharmony_ci const U16* stateTable = (const U16*)(statePtr->stateTable); 53162306a36Sopenharmony_ci U32 nbBitsOut = (U32)((symbolTT.deltaNbBits + (1<<15)) >> 16); 53262306a36Sopenharmony_ci statePtr->value = (nbBitsOut << 16) - symbolTT.deltaNbBits; 53362306a36Sopenharmony_ci statePtr->value = stateTable[(statePtr->value >> nbBitsOut) + symbolTT.deltaFindState]; 53462306a36Sopenharmony_ci } 53562306a36Sopenharmony_ci} 53662306a36Sopenharmony_ci 53762306a36Sopenharmony_ciMEM_STATIC void FSE_encodeSymbol(BIT_CStream_t* bitC, FSE_CState_t* statePtr, unsigned symbol) 53862306a36Sopenharmony_ci{ 53962306a36Sopenharmony_ci FSE_symbolCompressionTransform const symbolTT = ((const FSE_symbolCompressionTransform*)(statePtr->symbolTT))[symbol]; 54062306a36Sopenharmony_ci const U16* const stateTable = (const U16*)(statePtr->stateTable); 54162306a36Sopenharmony_ci U32 const nbBitsOut = (U32)((statePtr->value + symbolTT.deltaNbBits) >> 16); 54262306a36Sopenharmony_ci BIT_addBits(bitC, statePtr->value, nbBitsOut); 54362306a36Sopenharmony_ci statePtr->value = stateTable[ (statePtr->value >> nbBitsOut) + symbolTT.deltaFindState]; 54462306a36Sopenharmony_ci} 54562306a36Sopenharmony_ci 54662306a36Sopenharmony_ciMEM_STATIC void FSE_flushCState(BIT_CStream_t* bitC, const FSE_CState_t* statePtr) 54762306a36Sopenharmony_ci{ 54862306a36Sopenharmony_ci BIT_addBits(bitC, statePtr->value, statePtr->stateLog); 54962306a36Sopenharmony_ci BIT_flushBits(bitC); 55062306a36Sopenharmony_ci} 55162306a36Sopenharmony_ci 55262306a36Sopenharmony_ci 55362306a36Sopenharmony_ci/* FSE_getMaxNbBits() : 55462306a36Sopenharmony_ci * Approximate maximum cost of a symbol, in bits. 55562306a36Sopenharmony_ci * Fractional get rounded up (i.e : a symbol with a normalized frequency of 3 gives the same result as a frequency of 2) 55662306a36Sopenharmony_ci * note 1 : assume symbolValue is valid (<= maxSymbolValue) 55762306a36Sopenharmony_ci * note 2 : if freq[symbolValue]==0, @return a fake cost of tableLog+1 bits */ 55862306a36Sopenharmony_ciMEM_STATIC U32 FSE_getMaxNbBits(const void* symbolTTPtr, U32 symbolValue) 55962306a36Sopenharmony_ci{ 56062306a36Sopenharmony_ci const FSE_symbolCompressionTransform* symbolTT = (const FSE_symbolCompressionTransform*) symbolTTPtr; 56162306a36Sopenharmony_ci return (symbolTT[symbolValue].deltaNbBits + ((1<<16)-1)) >> 16; 56262306a36Sopenharmony_ci} 56362306a36Sopenharmony_ci 56462306a36Sopenharmony_ci/* FSE_bitCost() : 56562306a36Sopenharmony_ci * Approximate symbol cost, as fractional value, using fixed-point format (accuracyLog fractional bits) 56662306a36Sopenharmony_ci * note 1 : assume symbolValue is valid (<= maxSymbolValue) 56762306a36Sopenharmony_ci * note 2 : if freq[symbolValue]==0, @return a fake cost of tableLog+1 bits */ 56862306a36Sopenharmony_ciMEM_STATIC U32 FSE_bitCost(const void* symbolTTPtr, U32 tableLog, U32 symbolValue, U32 accuracyLog) 56962306a36Sopenharmony_ci{ 57062306a36Sopenharmony_ci const FSE_symbolCompressionTransform* symbolTT = (const FSE_symbolCompressionTransform*) symbolTTPtr; 57162306a36Sopenharmony_ci U32 const minNbBits = symbolTT[symbolValue].deltaNbBits >> 16; 57262306a36Sopenharmony_ci U32 const threshold = (minNbBits+1) << 16; 57362306a36Sopenharmony_ci assert(tableLog < 16); 57462306a36Sopenharmony_ci assert(accuracyLog < 31-tableLog); /* ensure enough room for renormalization double shift */ 57562306a36Sopenharmony_ci { U32 const tableSize = 1 << tableLog; 57662306a36Sopenharmony_ci U32 const deltaFromThreshold = threshold - (symbolTT[symbolValue].deltaNbBits + tableSize); 57762306a36Sopenharmony_ci U32 const normalizedDeltaFromThreshold = (deltaFromThreshold << accuracyLog) >> tableLog; /* linear interpolation (very approximate) */ 57862306a36Sopenharmony_ci U32 const bitMultiplier = 1 << accuracyLog; 57962306a36Sopenharmony_ci assert(symbolTT[symbolValue].deltaNbBits + tableSize <= threshold); 58062306a36Sopenharmony_ci assert(normalizedDeltaFromThreshold <= bitMultiplier); 58162306a36Sopenharmony_ci return (minNbBits+1)*bitMultiplier - normalizedDeltaFromThreshold; 58262306a36Sopenharmony_ci } 58362306a36Sopenharmony_ci} 58462306a36Sopenharmony_ci 58562306a36Sopenharmony_ci 58662306a36Sopenharmony_ci/* ====== Decompression ====== */ 58762306a36Sopenharmony_ci 58862306a36Sopenharmony_citypedef struct { 58962306a36Sopenharmony_ci U16 tableLog; 59062306a36Sopenharmony_ci U16 fastMode; 59162306a36Sopenharmony_ci} FSE_DTableHeader; /* sizeof U32 */ 59262306a36Sopenharmony_ci 59362306a36Sopenharmony_citypedef struct 59462306a36Sopenharmony_ci{ 59562306a36Sopenharmony_ci unsigned short newState; 59662306a36Sopenharmony_ci unsigned char symbol; 59762306a36Sopenharmony_ci unsigned char nbBits; 59862306a36Sopenharmony_ci} FSE_decode_t; /* size == U32 */ 59962306a36Sopenharmony_ci 60062306a36Sopenharmony_ciMEM_STATIC void FSE_initDState(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD, const FSE_DTable* dt) 60162306a36Sopenharmony_ci{ 60262306a36Sopenharmony_ci const void* ptr = dt; 60362306a36Sopenharmony_ci const FSE_DTableHeader* const DTableH = (const FSE_DTableHeader*)ptr; 60462306a36Sopenharmony_ci DStatePtr->state = BIT_readBits(bitD, DTableH->tableLog); 60562306a36Sopenharmony_ci BIT_reloadDStream(bitD); 60662306a36Sopenharmony_ci DStatePtr->table = dt + 1; 60762306a36Sopenharmony_ci} 60862306a36Sopenharmony_ci 60962306a36Sopenharmony_ciMEM_STATIC BYTE FSE_peekSymbol(const FSE_DState_t* DStatePtr) 61062306a36Sopenharmony_ci{ 61162306a36Sopenharmony_ci FSE_decode_t const DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state]; 61262306a36Sopenharmony_ci return DInfo.symbol; 61362306a36Sopenharmony_ci} 61462306a36Sopenharmony_ci 61562306a36Sopenharmony_ciMEM_STATIC void FSE_updateState(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD) 61662306a36Sopenharmony_ci{ 61762306a36Sopenharmony_ci FSE_decode_t const DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state]; 61862306a36Sopenharmony_ci U32 const nbBits = DInfo.nbBits; 61962306a36Sopenharmony_ci size_t const lowBits = BIT_readBits(bitD, nbBits); 62062306a36Sopenharmony_ci DStatePtr->state = DInfo.newState + lowBits; 62162306a36Sopenharmony_ci} 62262306a36Sopenharmony_ci 62362306a36Sopenharmony_ciMEM_STATIC BYTE FSE_decodeSymbol(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD) 62462306a36Sopenharmony_ci{ 62562306a36Sopenharmony_ci FSE_decode_t const DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state]; 62662306a36Sopenharmony_ci U32 const nbBits = DInfo.nbBits; 62762306a36Sopenharmony_ci BYTE const symbol = DInfo.symbol; 62862306a36Sopenharmony_ci size_t const lowBits = BIT_readBits(bitD, nbBits); 62962306a36Sopenharmony_ci 63062306a36Sopenharmony_ci DStatePtr->state = DInfo.newState + lowBits; 63162306a36Sopenharmony_ci return symbol; 63262306a36Sopenharmony_ci} 63362306a36Sopenharmony_ci 63462306a36Sopenharmony_ci/*! FSE_decodeSymbolFast() : 63562306a36Sopenharmony_ci unsafe, only works if no symbol has a probability > 50% */ 63662306a36Sopenharmony_ciMEM_STATIC BYTE FSE_decodeSymbolFast(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD) 63762306a36Sopenharmony_ci{ 63862306a36Sopenharmony_ci FSE_decode_t const DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state]; 63962306a36Sopenharmony_ci U32 const nbBits = DInfo.nbBits; 64062306a36Sopenharmony_ci BYTE const symbol = DInfo.symbol; 64162306a36Sopenharmony_ci size_t const lowBits = BIT_readBitsFast(bitD, nbBits); 64262306a36Sopenharmony_ci 64362306a36Sopenharmony_ci DStatePtr->state = DInfo.newState + lowBits; 64462306a36Sopenharmony_ci return symbol; 64562306a36Sopenharmony_ci} 64662306a36Sopenharmony_ci 64762306a36Sopenharmony_ciMEM_STATIC unsigned FSE_endOfDState(const FSE_DState_t* DStatePtr) 64862306a36Sopenharmony_ci{ 64962306a36Sopenharmony_ci return DStatePtr->state == 0; 65062306a36Sopenharmony_ci} 65162306a36Sopenharmony_ci 65262306a36Sopenharmony_ci 65362306a36Sopenharmony_ci 65462306a36Sopenharmony_ci#ifndef FSE_COMMONDEFS_ONLY 65562306a36Sopenharmony_ci 65662306a36Sopenharmony_ci/* ************************************************************** 65762306a36Sopenharmony_ci* Tuning parameters 65862306a36Sopenharmony_ci****************************************************************/ 65962306a36Sopenharmony_ci/*!MEMORY_USAGE : 66062306a36Sopenharmony_ci* Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.) 66162306a36Sopenharmony_ci* Increasing memory usage improves compression ratio 66262306a36Sopenharmony_ci* Reduced memory usage can improve speed, due to cache effect 66362306a36Sopenharmony_ci* Recommended max value is 14, for 16KB, which nicely fits into Intel x86 L1 cache */ 66462306a36Sopenharmony_ci#ifndef FSE_MAX_MEMORY_USAGE 66562306a36Sopenharmony_ci# define FSE_MAX_MEMORY_USAGE 14 66662306a36Sopenharmony_ci#endif 66762306a36Sopenharmony_ci#ifndef FSE_DEFAULT_MEMORY_USAGE 66862306a36Sopenharmony_ci# define FSE_DEFAULT_MEMORY_USAGE 13 66962306a36Sopenharmony_ci#endif 67062306a36Sopenharmony_ci#if (FSE_DEFAULT_MEMORY_USAGE > FSE_MAX_MEMORY_USAGE) 67162306a36Sopenharmony_ci# error "FSE_DEFAULT_MEMORY_USAGE must be <= FSE_MAX_MEMORY_USAGE" 67262306a36Sopenharmony_ci#endif 67362306a36Sopenharmony_ci 67462306a36Sopenharmony_ci/*!FSE_MAX_SYMBOL_VALUE : 67562306a36Sopenharmony_ci* Maximum symbol value authorized. 67662306a36Sopenharmony_ci* Required for proper stack allocation */ 67762306a36Sopenharmony_ci#ifndef FSE_MAX_SYMBOL_VALUE 67862306a36Sopenharmony_ci# define FSE_MAX_SYMBOL_VALUE 255 67962306a36Sopenharmony_ci#endif 68062306a36Sopenharmony_ci 68162306a36Sopenharmony_ci/* ************************************************************** 68262306a36Sopenharmony_ci* template functions type & suffix 68362306a36Sopenharmony_ci****************************************************************/ 68462306a36Sopenharmony_ci#define FSE_FUNCTION_TYPE BYTE 68562306a36Sopenharmony_ci#define FSE_FUNCTION_EXTENSION 68662306a36Sopenharmony_ci#define FSE_DECODE_TYPE FSE_decode_t 68762306a36Sopenharmony_ci 68862306a36Sopenharmony_ci 68962306a36Sopenharmony_ci#endif /* !FSE_COMMONDEFS_ONLY */ 69062306a36Sopenharmony_ci 69162306a36Sopenharmony_ci 69262306a36Sopenharmony_ci/* *************************************************************** 69362306a36Sopenharmony_ci* Constants 69462306a36Sopenharmony_ci*****************************************************************/ 69562306a36Sopenharmony_ci#define FSE_MAX_TABLELOG (FSE_MAX_MEMORY_USAGE-2) 69662306a36Sopenharmony_ci#define FSE_MAX_TABLESIZE (1U<<FSE_MAX_TABLELOG) 69762306a36Sopenharmony_ci#define FSE_MAXTABLESIZE_MASK (FSE_MAX_TABLESIZE-1) 69862306a36Sopenharmony_ci#define FSE_DEFAULT_TABLELOG (FSE_DEFAULT_MEMORY_USAGE-2) 69962306a36Sopenharmony_ci#define FSE_MIN_TABLELOG 5 70062306a36Sopenharmony_ci 70162306a36Sopenharmony_ci#define FSE_TABLELOG_ABSOLUTE_MAX 15 70262306a36Sopenharmony_ci#if FSE_MAX_TABLELOG > FSE_TABLELOG_ABSOLUTE_MAX 70362306a36Sopenharmony_ci# error "FSE_MAX_TABLELOG > FSE_TABLELOG_ABSOLUTE_MAX is not supported" 70462306a36Sopenharmony_ci#endif 70562306a36Sopenharmony_ci 70662306a36Sopenharmony_ci#define FSE_TABLESTEP(tableSize) (((tableSize)>>1) + ((tableSize)>>3) + 3) 70762306a36Sopenharmony_ci 70862306a36Sopenharmony_ci 70962306a36Sopenharmony_ci#endif /* FSE_STATIC_LINKING_ONLY */ 71062306a36Sopenharmony_ci 71162306a36Sopenharmony_ci 712