Yann Collet | 4856a00 | 2015-01-24 01:58:16 +0100 | [diff] [blame] | 1 | /* ****************************************************************** |
| 2 | FSE : Finite State Entropy coder |
| 3 | header file for static linking (only) |
| 4 | Copyright (C) 2013-2015, Yann Collet |
| 5 | |
| 6 | BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) |
| 7 | |
| 8 | Redistribution and use in source and binary forms, with or without |
| 9 | modification, are permitted provided that the following conditions are |
| 10 | met: |
| 11 | |
| 12 | * Redistributions of source code must retain the above copyright |
| 13 | notice, this list of conditions and the following disclaimer. |
| 14 | * Redistributions in binary form must reproduce the above |
| 15 | copyright notice, this list of conditions and the following disclaimer |
| 16 | in the documentation and/or other materials provided with the |
| 17 | distribution. |
| 18 | |
| 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 20 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| 21 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| 22 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| 23 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 24 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 25 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 26 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 27 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 28 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 30 | |
| 31 | You can contact the author at : |
| 32 | - Source repository : https://github.com/Cyan4973/FiniteStateEntropy |
| 33 | - Public forum : https://groups.google.com/forum/#!forum/lz4c |
| 34 | ****************************************************************** */ |
Yann Collet | aa07405 | 2015-10-30 11:21:50 +0100 | [diff] [blame] | 35 | #ifndef FSE_STATIC_H |
| 36 | #define FSE_STATIC_H |
Yann Collet | 4856a00 | 2015-01-24 01:58:16 +0100 | [diff] [blame] | 37 | |
| 38 | #if defined (__cplusplus) |
| 39 | extern "C" { |
| 40 | #endif |
| 41 | |
| 42 | |
Yann Collet | 3b994cb | 2016-01-06 01:58:37 +0100 | [diff] [blame] | 43 | /* ***************************************** |
| 44 | * Dependencies |
| 45 | *******************************************/ |
Yann Collet | 1efa31f | 2015-07-04 15:56:41 -0800 | [diff] [blame] | 46 | #include "fse.h" |
Yann Collet | b1f3f4b | 2015-10-18 22:18:32 +0100 | [diff] [blame] | 47 | #include "bitstream.h" |
Yann Collet | 4856a00 | 2015-01-24 01:58:16 +0100 | [diff] [blame] | 48 | |
| 49 | |
Yann Collet | 3b994cb | 2016-01-06 01:58:37 +0100 | [diff] [blame] | 50 | /* ***************************************** |
Yann Collet | 4856a00 | 2015-01-24 01:58:16 +0100 | [diff] [blame] | 51 | * Static allocation |
Yann Collet | 3b994cb | 2016-01-06 01:58:37 +0100 | [diff] [blame] | 52 | *******************************************/ |
Yann Collet | a787550 | 2015-08-07 15:21:00 +0100 | [diff] [blame] | 53 | /* FSE buffer bounds */ |
| 54 | #define FSE_NCOUNTBOUND 512 |
| 55 | #define FSE_BLOCKBOUND(size) (size + (size>>7)) |
| 56 | #define FSE_COMPRESSBOUND(size) (FSE_NCOUNTBOUND + FSE_BLOCKBOUND(size)) /* Macro version, useful for static allocation */ |
Yann Collet | e8c6bb1 | 2015-07-26 00:23:57 +0100 | [diff] [blame] | 57 | |
Yann Collet | 3b994cb | 2016-01-06 01:58:37 +0100 | [diff] [blame] | 58 | /* It is possible to statically allocate FSE CTable/DTable as a table of unsigned using below macros */ |
Yann Collet | 4856a00 | 2015-01-24 01:58:16 +0100 | [diff] [blame] | 59 | #define FSE_CTABLE_SIZE_U32(maxTableLog, maxSymbolValue) (1 + (1<<(maxTableLog-1)) + ((maxSymbolValue+1)*2)) |
Yann Collet | 1efa31f | 2015-07-04 15:56:41 -0800 | [diff] [blame] | 60 | #define FSE_DTABLE_SIZE_U32(maxTableLog) (1 + (1<<maxTableLog)) |
Yann Collet | 4856a00 | 2015-01-24 01:58:16 +0100 | [diff] [blame] | 61 | |
Yann Collet | 4856a00 | 2015-01-24 01:58:16 +0100 | [diff] [blame] | 62 | |
Yann Collet | 3b994cb | 2016-01-06 01:58:37 +0100 | [diff] [blame] | 63 | /* ***************************************** |
Yann Collet | 4856a00 | 2015-01-24 01:58:16 +0100 | [diff] [blame] | 64 | * FSE advanced API |
Yann Collet | 3b994cb | 2016-01-06 01:58:37 +0100 | [diff] [blame] | 65 | *******************************************/ |
Yann Collet | 4ddb1f5 | 2016-01-28 03:24:53 +0100 | [diff] [blame] | 66 | size_t FSE_countFast(unsigned* count, unsigned* maxSymbolValuePtr, const void* src, size_t srcSize); |
| 67 | /* same as FSE_count(), but blindly trusts that all byte values within src are <= *maxSymbolValuePtr */ |
Yann Collet | 4856a00 | 2015-01-24 01:58:16 +0100 | [diff] [blame] | 68 | |
Yann Collet | 1efa31f | 2015-07-04 15:56:41 -0800 | [diff] [blame] | 69 | size_t FSE_buildCTable_raw (FSE_CTable* ct, unsigned nbBits); |
| 70 | /* build a fake FSE_CTable, designed to not compress an input, where each symbol uses nbBits */ |
Yann Collet | 4856a00 | 2015-01-24 01:58:16 +0100 | [diff] [blame] | 71 | |
Yann Collet | 1efa31f | 2015-07-04 15:56:41 -0800 | [diff] [blame] | 72 | size_t FSE_buildCTable_rle (FSE_CTable* ct, unsigned char symbolValue); |
| 73 | /* build a fake FSE_CTable, designed to compress always the same symbolValue */ |
Yann Collet | 4856a00 | 2015-01-24 01:58:16 +0100 | [diff] [blame] | 74 | |
Yann Collet | 1efa31f | 2015-07-04 15:56:41 -0800 | [diff] [blame] | 75 | size_t FSE_buildDTable_raw (FSE_DTable* dt, unsigned nbBits); |
| 76 | /* build a fake FSE_DTable, designed to read an uncompressed bitstream where each symbol uses nbBits */ |
Yann Collet | 4856a00 | 2015-01-24 01:58:16 +0100 | [diff] [blame] | 77 | |
Yann Collet | 1efa31f | 2015-07-04 15:56:41 -0800 | [diff] [blame] | 78 | size_t FSE_buildDTable_rle (FSE_DTable* dt, unsigned char symbolValue); |
| 79 | /* build a fake FSE_DTable, designed to always generate the same symbolValue */ |
Yann Collet | 4856a00 | 2015-01-24 01:58:16 +0100 | [diff] [blame] | 80 | |
| 81 | |
Yann Collet | 3b994cb | 2016-01-06 01:58:37 +0100 | [diff] [blame] | 82 | /* ***************************************** |
Yann Collet | 1efa31f | 2015-07-04 15:56:41 -0800 | [diff] [blame] | 83 | * FSE symbol compression API |
Yann Collet | 3b994cb | 2016-01-06 01:58:37 +0100 | [diff] [blame] | 84 | *******************************************/ |
| 85 | /*! |
Yann Collet | 1efa31f | 2015-07-04 15:56:41 -0800 | [diff] [blame] | 86 | This API consists of small unitary functions, which highly benefit from being inlined. |
| 87 | You will want to enable link-time-optimization to ensure these functions are properly inlined in your binary. |
| 88 | Visual seems to do it automatically. |
| 89 | For gcc or clang, you'll need to add -flto flag at compilation and linking stages. |
Yann Collet | a787550 | 2015-08-07 15:21:00 +0100 | [diff] [blame] | 90 | If none of these solutions is applicable, include "fse.c" directly. |
Yann Collet | 1efa31f | 2015-07-04 15:56:41 -0800 | [diff] [blame] | 91 | */ |
Yann Collet | 1efa31f | 2015-07-04 15:56:41 -0800 | [diff] [blame] | 92 | typedef struct |
| 93 | { |
| 94 | ptrdiff_t value; |
| 95 | const void* stateTable; |
| 96 | const void* symbolTT; |
| 97 | unsigned stateLog; |
| 98 | } FSE_CState_t; |
| 99 | |
Yann Collet | b1f3f4b | 2015-10-18 22:18:32 +0100 | [diff] [blame] | 100 | static void FSE_initCState(FSE_CState_t* CStatePtr, const FSE_CTable* ct); |
Yann Collet | 1efa31f | 2015-07-04 15:56:41 -0800 | [diff] [blame] | 101 | |
Yann Collet | b1f3f4b | 2015-10-18 22:18:32 +0100 | [diff] [blame] | 102 | static void FSE_encodeSymbol(BIT_CStream_t* bitC, FSE_CState_t* CStatePtr, unsigned symbol); |
Yann Collet | 1efa31f | 2015-07-04 15:56:41 -0800 | [diff] [blame] | 103 | |
Yann Collet | b1f3f4b | 2015-10-18 22:18:32 +0100 | [diff] [blame] | 104 | static void FSE_flushCState(BIT_CStream_t* bitC, const FSE_CState_t* CStatePtr); |
Yann Collet | 1efa31f | 2015-07-04 15:56:41 -0800 | [diff] [blame] | 105 | |
Yann Collet | 3b994cb | 2016-01-06 01:58:37 +0100 | [diff] [blame] | 106 | /*! |
Yann Collet | 1efa31f | 2015-07-04 15:56:41 -0800 | [diff] [blame] | 107 | These functions are inner components of FSE_compress_usingCTable(). |
| 108 | They allow the creation of custom streams, mixing multiple tables and bit sources. |
| 109 | |
| 110 | A key property to keep in mind is that encoding and decoding are done **in reverse direction**. |
| 111 | So the first symbol you will encode is the last you will decode, like a LIFO stack. |
| 112 | |
| 113 | You will need a few variables to track your CStream. They are : |
| 114 | |
Yann Collet | a787550 | 2015-08-07 15:21:00 +0100 | [diff] [blame] | 115 | FSE_CTable ct; // Provided by FSE_buildCTable() |
Yann Collet | b1f3f4b | 2015-10-18 22:18:32 +0100 | [diff] [blame] | 116 | BIT_CStream_t bitStream; // bitStream tracking structure |
Yann Collet | a787550 | 2015-08-07 15:21:00 +0100 | [diff] [blame] | 117 | FSE_CState_t state; // State tracking structure (can have several) |
Yann Collet | 1efa31f | 2015-07-04 15:56:41 -0800 | [diff] [blame] | 118 | |
| 119 | |
| 120 | The first thing to do is to init bitStream and state. |
Yann Collet | b1f3f4b | 2015-10-18 22:18:32 +0100 | [diff] [blame] | 121 | size_t errorCode = BIT_initCStream(&bitStream, dstBuffer, maxDstSize); |
Yann Collet | 1efa31f | 2015-07-04 15:56:41 -0800 | [diff] [blame] | 122 | FSE_initCState(&state, ct); |
| 123 | |
Yann Collet | b1f3f4b | 2015-10-18 22:18:32 +0100 | [diff] [blame] | 124 | Note that BIT_initCStream() can produce an error code, so its result should be tested, using FSE_isError(); |
Yann Collet | 1efa31f | 2015-07-04 15:56:41 -0800 | [diff] [blame] | 125 | You can then encode your input data, byte after byte. |
Yann Collet | a787550 | 2015-08-07 15:21:00 +0100 | [diff] [blame] | 126 | FSE_encodeSymbol() outputs a maximum of 'tableLog' bits at a time. |
Yann Collet | 1efa31f | 2015-07-04 15:56:41 -0800 | [diff] [blame] | 127 | Remember decoding will be done in reverse direction. |
| 128 | FSE_encodeByte(&bitStream, &state, symbol); |
| 129 | |
| 130 | At any time, you can also add any bit sequence. |
| 131 | Note : maximum allowed nbBits is 25, for compatibility with 32-bits decoders |
Yann Collet | b1f3f4b | 2015-10-18 22:18:32 +0100 | [diff] [blame] | 132 | BIT_addBits(&bitStream, bitField, nbBits); |
Yann Collet | 1efa31f | 2015-07-04 15:56:41 -0800 | [diff] [blame] | 133 | |
| 134 | The above methods don't commit data to memory, they just store it into local register, for speed. |
| 135 | Local register size is 64-bits on 64-bits systems, 32-bits on 32-bits systems (size_t). |
| 136 | Writing data to memory is a manual operation, performed by the flushBits function. |
Yann Collet | b1f3f4b | 2015-10-18 22:18:32 +0100 | [diff] [blame] | 137 | BIT_flushBits(&bitStream); |
Yann Collet | 1efa31f | 2015-07-04 15:56:41 -0800 | [diff] [blame] | 138 | |
| 139 | Your last FSE encoding operation shall be to flush your last state value(s). |
| 140 | FSE_flushState(&bitStream, &state); |
| 141 | |
Yann Collet | a787550 | 2015-08-07 15:21:00 +0100 | [diff] [blame] | 142 | Finally, you must close the bitStream. |
| 143 | The function returns the size of CStream in bytes. |
| 144 | If data couldn't fit into dstBuffer, it will return a 0 ( == not compressible) |
Yann Collet | 1efa31f | 2015-07-04 15:56:41 -0800 | [diff] [blame] | 145 | If there is an error, it returns an errorCode (which can be tested using FSE_isError()). |
Yann Collet | b1f3f4b | 2015-10-18 22:18:32 +0100 | [diff] [blame] | 146 | size_t size = BIT_closeCStream(&bitStream); |
Yann Collet | 1efa31f | 2015-07-04 15:56:41 -0800 | [diff] [blame] | 147 | */ |
| 148 | |
| 149 | |
Yann Collet | 3b994cb | 2016-01-06 01:58:37 +0100 | [diff] [blame] | 150 | /* ***************************************** |
Yann Collet | 1efa31f | 2015-07-04 15:56:41 -0800 | [diff] [blame] | 151 | * FSE symbol decompression API |
Yann Collet | 3b994cb | 2016-01-06 01:58:37 +0100 | [diff] [blame] | 152 | *******************************************/ |
Yann Collet | 1efa31f | 2015-07-04 15:56:41 -0800 | [diff] [blame] | 153 | typedef struct |
| 154 | { |
Yann Collet | 1efa31f | 2015-07-04 15:56:41 -0800 | [diff] [blame] | 155 | size_t state; |
| 156 | const void* table; /* precise table may vary, depending on U16 */ |
| 157 | } FSE_DState_t; |
| 158 | |
| 159 | |
Yann Collet | b1f3f4b | 2015-10-18 22:18:32 +0100 | [diff] [blame] | 160 | static void FSE_initDState(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD, const FSE_DTable* dt); |
Yann Collet | 1efa31f | 2015-07-04 15:56:41 -0800 | [diff] [blame] | 161 | |
Yann Collet | b1f3f4b | 2015-10-18 22:18:32 +0100 | [diff] [blame] | 162 | static unsigned char FSE_decodeSymbol(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD); |
Yann Collet | 1efa31f | 2015-07-04 15:56:41 -0800 | [diff] [blame] | 163 | |
Yann Collet | b1f3f4b | 2015-10-18 22:18:32 +0100 | [diff] [blame] | 164 | static unsigned FSE_endOfDState(const FSE_DState_t* DStatePtr); |
Yann Collet | e8c6bb1 | 2015-07-26 00:23:57 +0100 | [diff] [blame] | 165 | |
Yann Collet | 3b994cb | 2016-01-06 01:58:37 +0100 | [diff] [blame] | 166 | /*! |
Yann Collet | 1efa31f | 2015-07-04 15:56:41 -0800 | [diff] [blame] | 167 | Let's now decompose FSE_decompress_usingDTable() into its unitary components. |
| 168 | You will decode FSE-encoded symbols from the bitStream, |
| 169 | and also any other bitFields you put in, **in reverse order**. |
| 170 | |
| 171 | You will need a few variables to track your bitStream. They are : |
| 172 | |
Yann Collet | b1f3f4b | 2015-10-18 22:18:32 +0100 | [diff] [blame] | 173 | BIT_DStream_t DStream; // Stream context |
Yann Collet | a787550 | 2015-08-07 15:21:00 +0100 | [diff] [blame] | 174 | FSE_DState_t DState; // State context. Multiple ones are possible |
| 175 | FSE_DTable* DTablePtr; // Decoding table, provided by FSE_buildDTable() |
Yann Collet | 1efa31f | 2015-07-04 15:56:41 -0800 | [diff] [blame] | 176 | |
| 177 | The first thing to do is to init the bitStream. |
Yann Collet | b1f3f4b | 2015-10-18 22:18:32 +0100 | [diff] [blame] | 178 | errorCode = BIT_initDStream(&DStream, srcBuffer, srcSize); |
Yann Collet | 1efa31f | 2015-07-04 15:56:41 -0800 | [diff] [blame] | 179 | |
Yann Collet | a787550 | 2015-08-07 15:21:00 +0100 | [diff] [blame] | 180 | You should then retrieve your initial state(s) |
| 181 | (in reverse flushing order if you have several ones) : |
| 182 | errorCode = FSE_initDState(&DState, &DStream, DTablePtr); |
Yann Collet | 1efa31f | 2015-07-04 15:56:41 -0800 | [diff] [blame] | 183 | |
| 184 | You can then decode your data, symbol after symbol. |
| 185 | For information the maximum number of bits read by FSE_decodeSymbol() is 'tableLog'. |
| 186 | Keep in mind that symbols are decoded in reverse order, like a LIFO stack (last in, first out). |
| 187 | unsigned char symbol = FSE_decodeSymbol(&DState, &DStream); |
| 188 | |
| 189 | You can retrieve any bitfield you eventually stored into the bitStream (in reverse order) |
Yann Collet | e8c6bb1 | 2015-07-26 00:23:57 +0100 | [diff] [blame] | 190 | Note : maximum allowed nbBits is 25, for 32-bits compatibility |
Yann Collet | b1f3f4b | 2015-10-18 22:18:32 +0100 | [diff] [blame] | 191 | size_t bitField = BIT_readBits(&DStream, nbBits); |
Yann Collet | 1efa31f | 2015-07-04 15:56:41 -0800 | [diff] [blame] | 192 | |
Yann Collet | e8c6bb1 | 2015-07-26 00:23:57 +0100 | [diff] [blame] | 193 | All above operations only read from local register (which size depends on size_t). |
Yann Collet | 1efa31f | 2015-07-04 15:56:41 -0800 | [diff] [blame] | 194 | Refueling the register from memory is manually performed by the reload method. |
| 195 | endSignal = FSE_reloadDStream(&DStream); |
| 196 | |
Yann Collet | b1f3f4b | 2015-10-18 22:18:32 +0100 | [diff] [blame] | 197 | BIT_reloadDStream() result tells if there is still some more data to read from DStream. |
| 198 | BIT_DStream_unfinished : there is still some data left into the DStream. |
| 199 | BIT_DStream_endOfBuffer : Dstream reached end of buffer. Its container may no longer be completely filled. |
| 200 | BIT_DStream_completed : Dstream reached its exact end, corresponding in general to decompression completed. |
| 201 | BIT_DStream_tooFar : Dstream went too far. Decompression result is corrupted. |
Yann Collet | 1efa31f | 2015-07-04 15:56:41 -0800 | [diff] [blame] | 202 | |
Yann Collet | b1f3f4b | 2015-10-18 22:18:32 +0100 | [diff] [blame] | 203 | When reaching end of buffer (BIT_DStream_endOfBuffer), progress slowly, notably if you decode multiple symbols per loop, |
Yann Collet | 1efa31f | 2015-07-04 15:56:41 -0800 | [diff] [blame] | 204 | to properly detect the exact end of stream. |
| 205 | After each decoded symbol, check if DStream is fully consumed using this simple test : |
Yann Collet | b1f3f4b | 2015-10-18 22:18:32 +0100 | [diff] [blame] | 206 | BIT_reloadDStream(&DStream) >= BIT_DStream_completed |
Yann Collet | 1efa31f | 2015-07-04 15:56:41 -0800 | [diff] [blame] | 207 | |
| 208 | When it's done, verify decompression is fully completed, by checking both DStream and the relevant states. |
| 209 | Checking if DStream has reached its end is performed by : |
Yann Collet | b1f3f4b | 2015-10-18 22:18:32 +0100 | [diff] [blame] | 210 | BIT_endOfDStream(&DStream); |
Yann Collet | a787550 | 2015-08-07 15:21:00 +0100 | [diff] [blame] | 211 | Check also the states. There might be some symbols left there, if some high probability ones (>50%) are possible. |
Yann Collet | 1efa31f | 2015-07-04 15:56:41 -0800 | [diff] [blame] | 212 | FSE_endOfDState(&DState); |
| 213 | */ |
| 214 | |
| 215 | |
Yann Collet | 3b994cb | 2016-01-06 01:58:37 +0100 | [diff] [blame] | 216 | /* ***************************************** |
Yann Collet | b1f3f4b | 2015-10-18 22:18:32 +0100 | [diff] [blame] | 217 | * FSE unsafe API |
Yann Collet | 3b994cb | 2016-01-06 01:58:37 +0100 | [diff] [blame] | 218 | *******************************************/ |
Yann Collet | b1f3f4b | 2015-10-18 22:18:32 +0100 | [diff] [blame] | 219 | static unsigned char FSE_decodeSymbolFast(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD); |
| 220 | /* faster, but works only if nbBits is always >= 1 (otherwise, result will be corrupted) */ |
Yann Collet | 4856a00 | 2015-01-24 01:58:16 +0100 | [diff] [blame] | 221 | |
Yann Collet | b1f3f4b | 2015-10-18 22:18:32 +0100 | [diff] [blame] | 222 | |
Yann Collet | 3b994cb | 2016-01-06 01:58:37 +0100 | [diff] [blame] | 223 | /* ***************************************** |
| 224 | * Implementation of inlined functions |
| 225 | *******************************************/ |
Yann Collet | fb810d6 | 2016-01-28 00:18:06 +0100 | [diff] [blame] | 226 | typedef struct { |
Yann Collet | b1f3f4b | 2015-10-18 22:18:32 +0100 | [diff] [blame] | 227 | int deltaFindState; |
| 228 | U32 deltaNbBits; |
| 229 | } FSE_symbolCompressionTransform; /* total 8 bytes */ |
| 230 | |
| 231 | MEM_STATIC void FSE_initCState(FSE_CState_t* statePtr, const FSE_CTable* ct) |
| 232 | { |
Yann Collet | 3b994cb | 2016-01-06 01:58:37 +0100 | [diff] [blame] | 233 | const void* ptr = ct; |
| 234 | const U16* u16ptr = (const U16*) ptr; |
Yann Collet | 218bd31 | 2016-01-06 02:19:55 +0100 | [diff] [blame] | 235 | const U32 tableLog = MEM_read16(ptr); |
Yann Collet | b1f3f4b | 2015-10-18 22:18:32 +0100 | [diff] [blame] | 236 | statePtr->value = (ptrdiff_t)1<<tableLog; |
Yann Collet | 3b994cb | 2016-01-06 01:58:37 +0100 | [diff] [blame] | 237 | statePtr->stateTable = u16ptr+2; |
| 238 | statePtr->symbolTT = ((const U32*)ct + 1 + (tableLog ? (1<<(tableLog-1)) : 1)); |
Yann Collet | b1f3f4b | 2015-10-18 22:18:32 +0100 | [diff] [blame] | 239 | statePtr->stateLog = tableLog; |
| 240 | } |
| 241 | |
Yann Collet | e93d6ce | 2016-01-31 00:58:06 +0100 | [diff] [blame] | 242 | MEM_STATIC void FSE_initCState2(FSE_CState_t* statePtr, const FSE_CTable* ct, U32 symbol) |
| 243 | { |
| 244 | FSE_initCState(statePtr, ct); |
| 245 | { |
| 246 | const FSE_symbolCompressionTransform symbolTT = ((const FSE_symbolCompressionTransform*)(statePtr->symbolTT))[symbol]; |
| 247 | const U16* stateTable = (const U16*)(statePtr->stateTable); |
| 248 | U32 nbBitsOut = (U32)((symbolTT.deltaNbBits + (1<<15)) >> 16); |
| 249 | statePtr->value = (nbBitsOut << 16) - symbolTT.deltaNbBits; |
| 250 | statePtr->value = stateTable[(statePtr->value >> nbBitsOut) + symbolTT.deltaFindState]; |
| 251 | |
| 252 | } |
| 253 | } |
| 254 | |
Yann Collet | b1f3f4b | 2015-10-18 22:18:32 +0100 | [diff] [blame] | 255 | MEM_STATIC void FSE_encodeSymbol(BIT_CStream_t* bitC, FSE_CState_t* statePtr, U32 symbol) |
| 256 | { |
| 257 | const FSE_symbolCompressionTransform symbolTT = ((const FSE_symbolCompressionTransform*)(statePtr->symbolTT))[symbol]; |
| 258 | const U16* const stateTable = (const U16*)(statePtr->stateTable); |
| 259 | U32 nbBitsOut = (U32)((statePtr->value + symbolTT.deltaNbBits) >> 16); |
| 260 | BIT_addBits(bitC, statePtr->value, nbBitsOut); |
| 261 | statePtr->value = stateTable[ (statePtr->value >> nbBitsOut) + symbolTT.deltaFindState]; |
| 262 | } |
| 263 | |
| 264 | MEM_STATIC void FSE_flushCState(BIT_CStream_t* bitC, const FSE_CState_t* statePtr) |
| 265 | { |
| 266 | BIT_addBits(bitC, statePtr->value, statePtr->stateLog); |
| 267 | BIT_flushBits(bitC); |
| 268 | } |
| 269 | |
| 270 | /* decompression */ |
| 271 | |
| 272 | typedef struct { |
| 273 | U16 tableLog; |
| 274 | U16 fastMode; |
| 275 | } FSE_DTableHeader; /* sizeof U32 */ |
| 276 | |
| 277 | typedef struct |
| 278 | { |
| 279 | unsigned short newState; |
| 280 | unsigned char symbol; |
| 281 | unsigned char nbBits; |
| 282 | } FSE_decode_t; /* size == U32 */ |
| 283 | |
| 284 | MEM_STATIC void FSE_initDState(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD, const FSE_DTable* dt) |
| 285 | { |
Yann Collet | 3b994cb | 2016-01-06 01:58:37 +0100 | [diff] [blame] | 286 | const void* ptr = dt; |
| 287 | const FSE_DTableHeader* const DTableH = (const FSE_DTableHeader*)ptr; |
Yann Collet | b1f3f4b | 2015-10-18 22:18:32 +0100 | [diff] [blame] | 288 | DStatePtr->state = BIT_readBits(bitD, DTableH->tableLog); |
| 289 | BIT_reloadDStream(bitD); |
| 290 | DStatePtr->table = dt + 1; |
| 291 | } |
| 292 | |
Yann Collet | e93d6ce | 2016-01-31 00:58:06 +0100 | [diff] [blame] | 293 | MEM_STATIC size_t FSE_getStateValue(FSE_DState_t* DStatePtr) |
| 294 | { |
| 295 | return DStatePtr->state; |
| 296 | } |
| 297 | |
| 298 | MEM_STATIC BYTE FSE_peakSymbol(FSE_DState_t* DStatePtr) |
| 299 | { |
| 300 | const FSE_decode_t DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state]; |
| 301 | return DInfo.symbol; |
| 302 | } |
| 303 | |
Yann Collet | b1f3f4b | 2015-10-18 22:18:32 +0100 | [diff] [blame] | 304 | MEM_STATIC BYTE FSE_decodeSymbol(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD) |
| 305 | { |
| 306 | const FSE_decode_t DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state]; |
| 307 | const U32 nbBits = DInfo.nbBits; |
| 308 | BYTE symbol = DInfo.symbol; |
| 309 | size_t lowBits = BIT_readBits(bitD, nbBits); |
| 310 | |
| 311 | DStatePtr->state = DInfo.newState + lowBits; |
| 312 | return symbol; |
| 313 | } |
| 314 | |
| 315 | MEM_STATIC BYTE FSE_decodeSymbolFast(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD) |
| 316 | { |
| 317 | const FSE_decode_t DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state]; |
| 318 | const U32 nbBits = DInfo.nbBits; |
| 319 | BYTE symbol = DInfo.symbol; |
| 320 | size_t lowBits = BIT_readBitsFast(bitD, nbBits); |
| 321 | |
| 322 | DStatePtr->state = DInfo.newState + lowBits; |
| 323 | return symbol; |
| 324 | } |
| 325 | |
| 326 | MEM_STATIC unsigned FSE_endOfDState(const FSE_DState_t* DStatePtr) |
| 327 | { |
| 328 | return DStatePtr->state == 0; |
| 329 | } |
Yann Collet | 4856a00 | 2015-01-24 01:58:16 +0100 | [diff] [blame] | 330 | |
| 331 | |
| 332 | #if defined (__cplusplus) |
| 333 | } |
| 334 | #endif |
Yann Collet | aa07405 | 2015-10-30 11:21:50 +0100 | [diff] [blame] | 335 | |
| 336 | #endif /* FSE_STATIC_H */ |