blob: 1f382ed10e547f31832e26460dac17cdb7b9e541 [file] [log] [blame]
Yann Collet4856a002015-01-24 01:58:16 +01001/* ******************************************************************
2 FSE : Finite State Entropy coder
3 Copyright (C) 2013-2015, Yann Collet.
4
5 BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
6
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions are
9 met:
10
11 * Redistributions of source code must retain the above copyright
12 notice, this list of conditions and the following disclaimer.
13 * Redistributions in binary form must reproduce the above
14 copyright notice, this list of conditions and the following disclaimer
15 in the documentation and/or other materials provided with the
16 distribution.
17
18 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
30 You can contact the author at :
31 - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy
32 - Public forum : https://groups.google.com/forum/#!forum/lz4c
33****************************************************************** */
34
35#ifndef FSE_COMMONDEFS_ONLY
36
Yann Collet3b994cb2016-01-06 01:58:37 +010037/* **************************************************************
Yann Collet4856a002015-01-24 01:58:16 +010038* Tuning parameters
39****************************************************************/
Yann Collet3b994cb2016-01-06 01:58:37 +010040/*!MEMORY_USAGE :
Yann Collet4856a002015-01-24 01:58:16 +010041* Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.)
42* Increasing memory usage improves compression ratio
43* Reduced memory usage can improve speed, due to cache effect
44* Recommended max value is 14, for 16KB, which nicely fits into Intel x86 L1 cache */
45#define FSE_MAX_MEMORY_USAGE 14
46#define FSE_DEFAULT_MEMORY_USAGE 13
47
Yann Collet3b994cb2016-01-06 01:58:37 +010048/*!FSE_MAX_SYMBOL_VALUE :
Yann Collet4856a002015-01-24 01:58:16 +010049* Maximum symbol value authorized.
50* Required for proper stack allocation */
51#define FSE_MAX_SYMBOL_VALUE 255
52
53
Yann Collet3b994cb2016-01-06 01:58:37 +010054/* **************************************************************
Yann Collete8c6bb12015-07-26 00:23:57 +010055* template functions type & suffix
Yann Collet4856a002015-01-24 01:58:16 +010056****************************************************************/
57#define FSE_FUNCTION_TYPE BYTE
58#define FSE_FUNCTION_EXTENSION
Yann Collet3b994cb2016-01-06 01:58:37 +010059#define FSE_DECODE_TYPE FSE_decode_t
Yann Collet4856a002015-01-24 01:58:16 +010060
Yann Collete8c6bb12015-07-26 00:23:57 +010061
Yann Collet4856a002015-01-24 01:58:16 +010062#endif /* !FSE_COMMONDEFS_ONLY */
63
Yann Collet3b994cb2016-01-06 01:58:37 +010064/* **************************************************************
Yann Collet4856a002015-01-24 01:58:16 +010065* Compiler specifics
66****************************************************************/
67#ifdef _MSC_VER /* Visual Studio */
68# define FORCE_INLINE static __forceinline
69# include <intrin.h> /* For Visual 2005 */
70# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
71# pragma warning(disable : 4214) /* disable: C4214: non-int bitfields */
72#else
Yann Collet4856a002015-01-24 01:58:16 +010073# ifdef __GNUC__
Yann Colletb1f3f4b2015-10-18 22:18:32 +010074# define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
Yann Collet4856a002015-01-24 01:58:16 +010075# define FORCE_INLINE static inline __attribute__((always_inline))
76# else
77# define FORCE_INLINE static inline
78# endif
79#endif
80
81
Yann Collet3b994cb2016-01-06 01:58:37 +010082/* **************************************************************
Yann Collet4856a002015-01-24 01:58:16 +010083* Includes
84****************************************************************/
85#include <stdlib.h> /* malloc, free, qsort */
86#include <string.h> /* memcpy, memset */
87#include <stdio.h> /* printf (debug) */
Yann Colletb1f3f4b2015-10-18 22:18:32 +010088#include "bitstream.h"
Yann Collet4856a002015-01-24 01:58:16 +010089#include "fse_static.h"
90
91
Yann Collet3b994cb2016-01-06 01:58:37 +010092/* ***************************************************************
Yann Collet4856a002015-01-24 01:58:16 +010093* Constants
94*****************************************************************/
95#define FSE_MAX_TABLELOG (FSE_MAX_MEMORY_USAGE-2)
96#define FSE_MAX_TABLESIZE (1U<<FSE_MAX_TABLELOG)
97#define FSE_MAXTABLESIZE_MASK (FSE_MAX_TABLESIZE-1)
98#define FSE_DEFAULT_TABLELOG (FSE_DEFAULT_MEMORY_USAGE-2)
99#define FSE_MIN_TABLELOG 5
100
101#define FSE_TABLELOG_ABSOLUTE_MAX 15
102#if FSE_MAX_TABLELOG > FSE_TABLELOG_ABSOLUTE_MAX
103#error "FSE_MAX_TABLELOG > FSE_TABLELOG_ABSOLUTE_MAX is not supported"
104#endif
105
106
Yann Collet3b994cb2016-01-06 01:58:37 +0100107/* **************************************************************
Yann Collet4856a002015-01-24 01:58:16 +0100108* Error Management
109****************************************************************/
110#define FSE_STATIC_ASSERT(c) { enum { FSE_static_assert = 1/(int)(!!(c)) }; } /* use only *after* variable declarations */
111
112
Yann Collet3b994cb2016-01-06 01:58:37 +0100113/* **************************************************************
Yann Collet4856a002015-01-24 01:58:16 +0100114* Complex types
115****************************************************************/
Yann Collet1efa31f2015-07-04 15:56:41 -0800116typedef U32 CTable_max_t[FSE_CTABLE_SIZE_U32(FSE_MAX_TABLELOG, FSE_MAX_SYMBOL_VALUE)];
117typedef U32 DTable_max_t[FSE_DTABLE_SIZE_U32(FSE_MAX_TABLELOG)];
Yann Collet4856a002015-01-24 01:58:16 +0100118
Yann Collet4856a002015-01-24 01:58:16 +0100119
Yann Collet3b994cb2016-01-06 01:58:37 +0100120/* **************************************************************
Yann Collete8c6bb12015-07-26 00:23:57 +0100121* Templates
122****************************************************************/
123/*
124 designed to be included
125 for type-specific functions (template emulation in C)
126 Objective is to write these functions only once, for improved maintenance
127*/
128
129/* safety checks */
130#ifndef FSE_FUNCTION_EXTENSION
131# error "FSE_FUNCTION_EXTENSION must be defined"
132#endif
133#ifndef FSE_FUNCTION_TYPE
134# error "FSE_FUNCTION_TYPE must be defined"
135#endif
136
137/* Function names */
138#define FSE_CAT(X,Y) X##Y
139#define FSE_FUNCTION_NAME(X,Y) FSE_CAT(X,Y)
140#define FSE_TYPE_NAME(X,Y) FSE_CAT(X,Y)
141
142
143/* Function templates */
Yann Collete8c6bb12015-07-26 00:23:57 +0100144static U32 FSE_tableStep(U32 tableSize) { return (tableSize>>1) + (tableSize>>3) + 3; }
145
Yann Collet3b994cb2016-01-06 01:58:37 +0100146size_t FSE_buildCTable(FSE_CTable* ct, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog)
Yann Collete8c6bb12015-07-26 00:23:57 +0100147{
148 const unsigned tableSize = 1 << tableLog;
149 const unsigned tableMask = tableSize - 1;
Yann Collet3b994cb2016-01-06 01:58:37 +0100150 void* const ptr = ct;
151 U16* const tableU16 = ( (U16*) ptr) + 2;
152 void* const FSCT = ((U32*)ptr) + 1 /* header */ + (tableLog ? tableSize>>1 : 1) ;
153 FSE_symbolCompressionTransform* const symbolTT = (FSE_symbolCompressionTransform*) (FSCT);
Yann Collete8c6bb12015-07-26 00:23:57 +0100154 const unsigned step = FSE_tableStep(tableSize);
155 unsigned cumul[FSE_MAX_SYMBOL_VALUE+2];
156 U32 position = 0;
Yann Collet3b994cb2016-01-06 01:58:37 +0100157 FSE_FUNCTION_TYPE tableSymbol[FSE_MAX_TABLESIZE]; /* memset() is not necessary, even if static analyzer complain about it */
Yann Collete8c6bb12015-07-26 00:23:57 +0100158 U32 highThreshold = tableSize-1;
159 unsigned symbol;
160 unsigned i;
161
162 /* header */
163 tableU16[-2] = (U16) tableLog;
164 tableU16[-1] = (U16) maxSymbolValue;
165
166 /* For explanations on how to distribute symbol values over the table :
167 * http://fastcompression.blogspot.fr/2014/02/fse-distributing-symbol-values.html */
168
169 /* symbol start positions */
170 cumul[0] = 0;
Yann Collet4ddb1f52016-01-28 03:24:53 +0100171 for (i=1; i<=maxSymbolValue+1; i++) {
172 if (normalizedCounter[i-1]==-1) { /* Low proba symbol */
Yann Collete8c6bb12015-07-26 00:23:57 +0100173 cumul[i] = cumul[i-1] + 1;
174 tableSymbol[highThreshold--] = (FSE_FUNCTION_TYPE)(i-1);
Yann Collet4ddb1f52016-01-28 03:24:53 +0100175 } else {
Yann Collete8c6bb12015-07-26 00:23:57 +0100176 cumul[i] = cumul[i-1] + normalizedCounter[i-1];
Yann Collet4ddb1f52016-01-28 03:24:53 +0100177 } }
Yann Collete8c6bb12015-07-26 00:23:57 +0100178 cumul[maxSymbolValue+1] = tableSize+1;
179
180 /* Spread symbols */
Yann Collet4ddb1f52016-01-28 03:24:53 +0100181 for (symbol=0; symbol<=maxSymbolValue; symbol++) {
Yann Collete8c6bb12015-07-26 00:23:57 +0100182 int nbOccurences;
Yann Collet4ddb1f52016-01-28 03:24:53 +0100183 for (nbOccurences=0; nbOccurences<normalizedCounter[symbol]; nbOccurences++) {
Yann Collete8c6bb12015-07-26 00:23:57 +0100184 tableSymbol[position] = (FSE_FUNCTION_TYPE)symbol;
185 position = (position + step) & tableMask;
Yann Collet3b994cb2016-01-06 01:58:37 +0100186 while (position > highThreshold) position = (position + step) & tableMask; /* Low proba area */
Yann Collet4ddb1f52016-01-28 03:24:53 +0100187 } }
Yann Collete8c6bb12015-07-26 00:23:57 +0100188
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100189 if (position!=0) return ERROR(GENERIC); /* Must have gone through all positions */
Yann Collete8c6bb12015-07-26 00:23:57 +0100190
191 /* Build table */
Yann Collet4ddb1f52016-01-28 03:24:53 +0100192 for (i=0; i<tableSize; i++) {
Yann Collet3b994cb2016-01-06 01:58:37 +0100193 FSE_FUNCTION_TYPE s = tableSymbol[i]; /* note : static analyzer may not understand tableSymbol is properly initialized */
Yann Colleta7875502015-08-07 15:21:00 +0100194 tableU16[cumul[s]++] = (U16) (tableSize+i); /* TableU16 : sorted by symbol order; gives next state value */
Yann Collete8c6bb12015-07-26 00:23:57 +0100195 }
196
197 /* Build Symbol Transformation Table */
198 {
199 unsigned s;
200 unsigned total = 0;
Yann Collet4ddb1f52016-01-28 03:24:53 +0100201 for (s=0; s<=maxSymbolValue; s++) {
Yann Collete8c6bb12015-07-26 00:23:57 +0100202 switch (normalizedCounter[s])
203 {
Yann Collet77c82b62015-08-02 01:19:09 +0100204 case 0:
Yann Collete8c6bb12015-07-26 00:23:57 +0100205 break;
206 case -1:
Yann Collet77c82b62015-08-02 01:19:09 +0100207 case 1:
Yann Colleta7875502015-08-07 15:21:00 +0100208 symbolTT[s].deltaNbBits = tableLog << 16;
Yann Collete8c6bb12015-07-26 00:23:57 +0100209 symbolTT[s].deltaFindState = total - 1;
210 total ++;
Yann Collete8c6bb12015-07-26 00:23:57 +0100211 break;
212 default :
Yann Collet77c82b62015-08-02 01:19:09 +0100213 {
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100214 U32 maxBitsOut = tableLog - BIT_highbit32 (normalizedCounter[s]-1);
Yann Collet77c82b62015-08-02 01:19:09 +0100215 U32 minStatePlus = normalizedCounter[s] << maxBitsOut;
216 symbolTT[s].deltaNbBits = (maxBitsOut << 16) - minStatePlus;
217 symbolTT[s].deltaFindState = total - normalizedCounter[s];
218 total += normalizedCounter[s];
219 }
Yann Collete8c6bb12015-07-26 00:23:57 +0100220 }
221 }
Yann Collet4ddb1f52016-01-28 03:24:53 +0100222 } /* Build Symbol Transformation Table */
Yann Collete8c6bb12015-07-26 00:23:57 +0100223
224 return 0;
225}
226
227
Yann Collet3b994cb2016-01-06 01:58:37 +0100228FSE_DTable* FSE_createDTable (unsigned tableLog)
Yann Collete8c6bb12015-07-26 00:23:57 +0100229{
230 if (tableLog > FSE_TABLELOG_ABSOLUTE_MAX) tableLog = FSE_TABLELOG_ABSOLUTE_MAX;
231 return (FSE_DTable*)malloc( FSE_DTABLE_SIZE_U32(tableLog) * sizeof (U32) );
232}
233
Yann Collet3b994cb2016-01-06 01:58:37 +0100234void FSE_freeDTable (FSE_DTable* dt)
Yann Collete8c6bb12015-07-26 00:23:57 +0100235{
236 free(dt);
237}
238
Yann Collet3b994cb2016-01-06 01:58:37 +0100239size_t FSE_buildDTable(FSE_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog)
Yann Collete8c6bb12015-07-26 00:23:57 +0100240{
Yann Collet3b994cb2016-01-06 01:58:37 +0100241 FSE_DTableHeader DTableH;
242 void* const tdPtr = dt+1; /* because dt is unsigned, 32-bits aligned on 32-bits */
243 FSE_DECODE_TYPE* const tableDecode = (FSE_DECODE_TYPE*) (tdPtr);
Yann Collete8c6bb12015-07-26 00:23:57 +0100244 const U32 tableSize = 1 << tableLog;
245 const U32 tableMask = tableSize-1;
246 const U32 step = FSE_tableStep(tableSize);
247 U16 symbolNext[FSE_MAX_SYMBOL_VALUE+1];
248 U32 position = 0;
249 U32 highThreshold = tableSize-1;
250 const S16 largeLimit= (S16)(1 << (tableLog-1));
251 U32 noLarge = 1;
252 U32 s;
253
254 /* Sanity Checks */
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100255 if (maxSymbolValue > FSE_MAX_SYMBOL_VALUE) return ERROR(maxSymbolValue_tooLarge);
256 if (tableLog > FSE_MAX_TABLELOG) return ERROR(tableLog_tooLarge);
Yann Collete8c6bb12015-07-26 00:23:57 +0100257
258 /* Init, lay down lowprob symbols */
Yann Collet3b994cb2016-01-06 01:58:37 +0100259 DTableH.tableLog = (U16)tableLog;
Yann Collet4ddb1f52016-01-28 03:24:53 +0100260 for (s=0; s<=maxSymbolValue; s++) {
261 if (normalizedCounter[s]==-1) {
Yann Collete8c6bb12015-07-26 00:23:57 +0100262 tableDecode[highThreshold--].symbol = (FSE_FUNCTION_TYPE)s;
263 symbolNext[s] = 1;
Yann Collet4ddb1f52016-01-28 03:24:53 +0100264 } else {
Yann Collete8c6bb12015-07-26 00:23:57 +0100265 if (normalizedCounter[s] >= largeLimit) noLarge=0;
266 symbolNext[s] = normalizedCounter[s];
Yann Collet4ddb1f52016-01-28 03:24:53 +0100267 } }
Yann Collete8c6bb12015-07-26 00:23:57 +0100268
269 /* Spread symbols */
Yann Collet4ddb1f52016-01-28 03:24:53 +0100270 for (s=0; s<=maxSymbolValue; s++) {
Yann Collete8c6bb12015-07-26 00:23:57 +0100271 int i;
Yann Collet4ddb1f52016-01-28 03:24:53 +0100272 for (i=0; i<normalizedCounter[s]; i++) {
Yann Collete8c6bb12015-07-26 00:23:57 +0100273 tableDecode[position].symbol = (FSE_FUNCTION_TYPE)s;
274 position = (position + step) & tableMask;
275 while (position > highThreshold) position = (position + step) & tableMask; /* lowprob area */
Yann Collet4ddb1f52016-01-28 03:24:53 +0100276 } }
Yann Collete8c6bb12015-07-26 00:23:57 +0100277
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100278 if (position!=0) return ERROR(GENERIC); /* position must reach all cells once, otherwise normalizedCounter is incorrect */
Yann Collete8c6bb12015-07-26 00:23:57 +0100279
280 /* Build Decoding table */
281 {
282 U32 i;
Yann Collet4ddb1f52016-01-28 03:24:53 +0100283 for (i=0; i<tableSize; i++) {
Yann Collete8c6bb12015-07-26 00:23:57 +0100284 FSE_FUNCTION_TYPE symbol = (FSE_FUNCTION_TYPE)(tableDecode[i].symbol);
285 U16 nextState = symbolNext[symbol]++;
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100286 tableDecode[i].nbBits = (BYTE) (tableLog - BIT_highbit32 ((U32)nextState) );
Yann Collete8c6bb12015-07-26 00:23:57 +0100287 tableDecode[i].newState = (U16) ( (nextState << tableDecode[i].nbBits) - tableSize);
Yann Collet4ddb1f52016-01-28 03:24:53 +0100288 } }
Yann Collete8c6bb12015-07-26 00:23:57 +0100289
Yann Collet3b994cb2016-01-06 01:58:37 +0100290 DTableH.fastMode = (U16)noLarge;
291 memcpy(dt, &DTableH, sizeof(DTableH));
Yann Colleta7875502015-08-07 15:21:00 +0100292 return 0;
Yann Collete8c6bb12015-07-26 00:23:57 +0100293}
294
295
Yann Collet4856a002015-01-24 01:58:16 +0100296#ifndef FSE_COMMONDEFS_ONLY
Yann Collet4ddb1f52016-01-28 03:24:53 +0100297/*-****************************************
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100298* FSE helper functions
299******************************************/
300unsigned FSE_isError(size_t code) { return ERR_isError(code); }
Yann Collet4856a002015-01-24 01:58:16 +0100301
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100302const char* FSE_getErrorName(size_t code) { return ERR_getErrorName(code); }
Yann Collet4856a002015-01-24 01:58:16 +0100303
304
Yann Collet4ddb1f52016-01-28 03:24:53 +0100305/*-**************************************************************
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100306* FSE NCount encoding-decoding
Yann Collet4856a002015-01-24 01:58:16 +0100307****************************************************************/
Yann Collet1efa31f2015-07-04 15:56:41 -0800308size_t FSE_NCountWriteBound(unsigned maxSymbolValue, unsigned tableLog)
Yann Collet4856a002015-01-24 01:58:16 +0100309{
Yann Colletd02114e2015-08-21 03:59:31 +0100310 size_t maxHeaderSize = (((maxSymbolValue+1) * tableLog) >> 3) + 3;
Yann Collet23743532015-08-19 23:53:56 +0100311 return maxSymbolValue ? maxHeaderSize : FSE_NCOUNTBOUND; /* maxSymbolValue==0 ? use default */
Yann Collet4856a002015-01-24 01:58:16 +0100312}
313
Yann Colletfb810d62016-01-28 00:18:06 +0100314static short FSE_abs(short a) { return a<0 ? -a : a; }
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100315
Yann Collet1efa31f2015-07-04 15:56:41 -0800316static size_t FSE_writeNCount_generic (void* header, size_t headerBufferSize,
Yann Collet4856a002015-01-24 01:58:16 +0100317 const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog,
Yann Collet23743532015-08-19 23:53:56 +0100318 unsigned writeIsSafe)
Yann Collet4856a002015-01-24 01:58:16 +0100319{
320 BYTE* const ostart = (BYTE*) header;
321 BYTE* out = ostart;
322 BYTE* const oend = ostart + headerBufferSize;
323 int nbBits;
324 const int tableSize = 1 << tableLog;
325 int remaining;
326 int threshold;
327 U32 bitStream;
328 int bitCount;
329 unsigned charnum = 0;
330 int previous0 = 0;
331
332 bitStream = 0;
333 bitCount = 0;
334 /* Table Size */
335 bitStream += (tableLog-FSE_MIN_TABLELOG) << bitCount;
336 bitCount += 4;
337
338 /* Init */
339 remaining = tableSize+1; /* +1 for extra accuracy */
340 threshold = tableSize;
341 nbBits = tableLog+1;
342
Yann Colletfb810d62016-01-28 00:18:06 +0100343 while (remaining>1) { /* stops at 1 */
344 if (previous0) {
Yann Collet4856a002015-01-24 01:58:16 +0100345 unsigned start = charnum;
346 while (!normalizedCounter[charnum]) charnum++;
Yann Colletfb810d62016-01-28 00:18:06 +0100347 while (charnum >= start+24) {
Yann Collet4856a002015-01-24 01:58:16 +0100348 start+=24;
Yann Collet213089c2015-06-18 07:43:16 -0800349 bitStream += 0xFFFFU << bitCount;
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100350 if ((!writeIsSafe) && (out > oend-2)) return ERROR(dstSize_tooSmall); /* Buffer overflow */
Yann Collet213089c2015-06-18 07:43:16 -0800351 out[0] = (BYTE) bitStream;
Yann Collet4856a002015-01-24 01:58:16 +0100352 out[1] = (BYTE)(bitStream>>8);
353 out+=2;
354 bitStream>>=16;
355 }
Yann Colletfb810d62016-01-28 00:18:06 +0100356 while (charnum >= start+3) {
Yann Collet4856a002015-01-24 01:58:16 +0100357 start+=3;
358 bitStream += 3 << bitCount;
359 bitCount += 2;
360 }
361 bitStream += (charnum-start) << bitCount;
362 bitCount += 2;
Yann Colletfb810d62016-01-28 00:18:06 +0100363 if (bitCount>16) {
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100364 if ((!writeIsSafe) && (out > oend - 2)) return ERROR(dstSize_tooSmall); /* Buffer overflow */
Yann Collet4856a002015-01-24 01:58:16 +0100365 out[0] = (BYTE)bitStream;
366 out[1] = (BYTE)(bitStream>>8);
367 out += 2;
368 bitStream >>= 16;
369 bitCount -= 16;
Yann Colletfb810d62016-01-28 00:18:06 +0100370 } }
Yann Collet4856a002015-01-24 01:58:16 +0100371 {
372 short count = normalizedCounter[charnum++];
373 const short max = (short)((2*threshold-1)-remaining);
374 remaining -= FSE_abs(count);
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100375 if (remaining<1) return ERROR(GENERIC);
Yann Collet4856a002015-01-24 01:58:16 +0100376 count++; /* +1 for extra accuracy */
377 if (count>=threshold) count += max; /* [0..max[ [max..threshold[ (...) [threshold+max 2*threshold[ */
378 bitStream += count << bitCount;
379 bitCount += nbBits;
380 bitCount -= (count<max);
381 previous0 = (count==1);
382 while (remaining<threshold) nbBits--, threshold>>=1;
383 }
Yann Colletfb810d62016-01-28 00:18:06 +0100384 if (bitCount>16) {
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100385 if ((!writeIsSafe) && (out > oend - 2)) return ERROR(dstSize_tooSmall); /* Buffer overflow */
Yann Collet4856a002015-01-24 01:58:16 +0100386 out[0] = (BYTE)bitStream;
387 out[1] = (BYTE)(bitStream>>8);
388 out += 2;
389 bitStream >>= 16;
390 bitCount -= 16;
391 }
392 }
393
394 /* flush remaining bitStream */
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100395 if ((!writeIsSafe) && (out > oend - 2)) return ERROR(dstSize_tooSmall); /* Buffer overflow */
Yann Collet4856a002015-01-24 01:58:16 +0100396 out[0] = (BYTE)bitStream;
397 out[1] = (BYTE)(bitStream>>8);
398 out+= (bitCount+7) /8;
399
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100400 if (charnum > maxSymbolValue + 1) return ERROR(GENERIC);
Yann Collet4856a002015-01-24 01:58:16 +0100401
402 return (out-ostart);
403}
404
405
Yann Collet997f9ee2015-08-21 02:44:20 +0100406size_t FSE_writeNCount (void* buffer, size_t bufferSize, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog)
Yann Collet4856a002015-01-24 01:58:16 +0100407{
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100408 if (tableLog > FSE_MAX_TABLELOG) return ERROR(GENERIC); /* Unsupported */
409 if (tableLog < FSE_MIN_TABLELOG) return ERROR(GENERIC); /* Unsupported */
Yann Collet4856a002015-01-24 01:58:16 +0100410
Yann Collet997f9ee2015-08-21 02:44:20 +0100411 if (bufferSize < FSE_NCountWriteBound(maxSymbolValue, tableLog))
412 return FSE_writeNCount_generic(buffer, bufferSize, normalizedCounter, maxSymbolValue, tableLog, 0);
Yann Collet4856a002015-01-24 01:58:16 +0100413
Yann Collet997f9ee2015-08-21 02:44:20 +0100414 return FSE_writeNCount_generic(buffer, bufferSize, normalizedCounter, maxSymbolValue, tableLog, 1);
Yann Collet4856a002015-01-24 01:58:16 +0100415}
416
417
Yann Collet1efa31f2015-07-04 15:56:41 -0800418size_t FSE_readNCount (short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr,
Yann Collet4856a002015-01-24 01:58:16 +0100419 const void* headerBuffer, size_t hbSize)
420{
421 const BYTE* const istart = (const BYTE*) headerBuffer;
Yann Collet1efa31f2015-07-04 15:56:41 -0800422 const BYTE* const iend = istart + hbSize;
Yann Collet4856a002015-01-24 01:58:16 +0100423 const BYTE* ip = istart;
424 int nbBits;
425 int remaining;
426 int threshold;
427 U32 bitStream;
428 int bitCount;
429 unsigned charnum = 0;
430 int previous0 = 0;
431
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100432 if (hbSize < 4) return ERROR(srcSize_wrong);
433 bitStream = MEM_readLE32(ip);
Yann Collet4856a002015-01-24 01:58:16 +0100434 nbBits = (bitStream & 0xF) + FSE_MIN_TABLELOG; /* extract tableLog */
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100435 if (nbBits > FSE_TABLELOG_ABSOLUTE_MAX) return ERROR(tableLog_tooLarge);
Yann Collet4856a002015-01-24 01:58:16 +0100436 bitStream >>= 4;
437 bitCount = 4;
438 *tableLogPtr = nbBits;
439 remaining = (1<<nbBits)+1;
440 threshold = 1<<nbBits;
441 nbBits++;
442
Yann Colletfb810d62016-01-28 00:18:06 +0100443 while ((remaining>1) && (charnum<=*maxSVPtr)) {
444 if (previous0) {
Yann Collet4856a002015-01-24 01:58:16 +0100445 unsigned n0 = charnum;
Yann Colletfb810d62016-01-28 00:18:06 +0100446 while ((bitStream & 0xFFFF) == 0xFFFF) {
Yann Collet4856a002015-01-24 01:58:16 +0100447 n0+=24;
Yann Colletfb810d62016-01-28 00:18:06 +0100448 if (ip < iend-5) {
Yann Collet23743532015-08-19 23:53:56 +0100449 ip+=2;
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100450 bitStream = MEM_readLE32(ip) >> bitCount;
Yann Colletfb810d62016-01-28 00:18:06 +0100451 } else {
Yann Collet23743532015-08-19 23:53:56 +0100452 bitStream >>= 16;
453 bitCount+=16;
Yann Colletfb810d62016-01-28 00:18:06 +0100454 } }
455 while ((bitStream & 3) == 3) {
Yann Collet4856a002015-01-24 01:58:16 +0100456 n0+=3;
457 bitStream>>=2;
458 bitCount+=2;
459 }
460 n0 += bitStream & 3;
461 bitCount += 2;
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100462 if (n0 > *maxSVPtr) return ERROR(maxSymbolValue_tooSmall);
Yann Collet4856a002015-01-24 01:58:16 +0100463 while (charnum < n0) normalizedCounter[charnum++] = 0;
Yann Colletfb810d62016-01-28 00:18:06 +0100464 if ((ip <= iend-7) || (ip + (bitCount>>3) <= iend-4)) {
Yann Collet23743532015-08-19 23:53:56 +0100465 ip += bitCount>>3;
466 bitCount &= 7;
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100467 bitStream = MEM_readLE32(ip) >> bitCount;
Yann Collet23743532015-08-19 23:53:56 +0100468 }
469 else
470 bitStream >>= 2;
Yann Collet4856a002015-01-24 01:58:16 +0100471 }
472 {
473 const short max = (short)((2*threshold-1)-remaining);
474 short count;
475
Yann Colletfb810d62016-01-28 00:18:06 +0100476 if ((bitStream & (threshold-1)) < (U32)max) {
Yann Collet4856a002015-01-24 01:58:16 +0100477 count = (short)(bitStream & (threshold-1));
478 bitCount += nbBits-1;
Yann Colletfb810d62016-01-28 00:18:06 +0100479 } else {
Yann Collet4856a002015-01-24 01:58:16 +0100480 count = (short)(bitStream & (2*threshold-1));
481 if (count >= threshold) count -= max;
482 bitCount += nbBits;
483 }
484
485 count--; /* extra accuracy */
486 remaining -= FSE_abs(count);
487 normalizedCounter[charnum++] = count;
488 previous0 = !count;
Yann Colletfb810d62016-01-28 00:18:06 +0100489 while (remaining < threshold) {
Yann Collet4856a002015-01-24 01:58:16 +0100490 nbBits--;
491 threshold >>= 1;
492 }
493
Yann Colletfb810d62016-01-28 00:18:06 +0100494 if ((ip <= iend-7) || (ip + (bitCount>>3) <= iend-4)) {
495 ip += bitCount>>3;
496 bitCount &= 7;
497 } else {
498 bitCount -= (int)(8 * (iend - 4 - ip));
499 ip = iend - 4;
Yann Collet1efa31f2015-07-04 15:56:41 -0800500 }
Yann Colletfb810d62016-01-28 00:18:06 +0100501 bitStream = MEM_readLE32(ip) >> (bitCount & 31);
502 } }
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100503 if (remaining != 1) return ERROR(GENERIC);
Yann Collet4856a002015-01-24 01:58:16 +0100504 *maxSVPtr = charnum-1;
505
Yann Collet1efa31f2015-07-04 15:56:41 -0800506 ip += (bitCount+7)>>3;
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100507 if ((size_t)(ip-istart) > hbSize) return ERROR(srcSize_wrong);
Yann Collet4856a002015-01-24 01:58:16 +0100508 return ip-istart;
509}
510
511
Yann Collet4ddb1f52016-01-28 03:24:53 +0100512/*-**************************************************************
513* Counting histogram
514****************************************************************/
515/*! FSE_count_simple
516 This function just counts byte values within @src,
517 and store the histogram into @count.
518 This function is unsafe : it doesn't check that all values within @src can fit into @count.
519 For this reason, prefer using a table @count with 256 elements.
520 @return : highest count for a single element
521*/
522static size_t FSE_count_simple(unsigned* count, unsigned* maxSymbolValuePtr,
523 const void* src, size_t srcSize)
524{
525 const BYTE* ip = (const BYTE*)src;
526 const BYTE* const end = ip + srcSize;
527 unsigned maxSymbolValue = *maxSymbolValuePtr;
528 unsigned max=0;
529 U32 s;
530
531 memset(count, 0, (maxSymbolValue+1)*sizeof(*count));
532 if (srcSize==0) { *maxSymbolValuePtr = 0; return 0; }
533
534 while (ip<end) count[*ip++]++;
535
536 while (!count[maxSymbolValue]) maxSymbolValue--;
537 *maxSymbolValuePtr = maxSymbolValue;
538
539 for (s=0; s<=maxSymbolValue; s++) if (count[s] > max) max = count[s];
540
541 return (size_t)max;
542}
543
544
545static size_t FSE_count_parallel(unsigned* count, unsigned* maxSymbolValuePtr,
546 const void* source, size_t sourceSize,
547 unsigned checkMax)
548{
549 const BYTE* ip = (const BYTE*)source;
550 const BYTE* const iend = ip+sourceSize;
551 unsigned maxSymbolValue = *maxSymbolValuePtr;
552 unsigned max=0;
553 U32 s;
554
555 U32 Counting1[256] = { 0 };
556 U32 Counting2[256] = { 0 };
557 U32 Counting3[256] = { 0 };
558 U32 Counting4[256] = { 0 };
559
560 /* safety checks */
561 if (!sourceSize) {
562 memset(count, 0, maxSymbolValue + 1);
563 *maxSymbolValuePtr = 0;
564 return 0;
565 }
566 if (!maxSymbolValue) maxSymbolValue = 255; /* 0 == default */
567
568 { /* by stripes of 16 bytes */
569 U32 cached = MEM_read32(ip); ip += 4;
570 while (ip < iend-15) {
571 U32 c = cached; cached = MEM_read32(ip); ip += 4;
572 Counting1[(BYTE) c ]++;
573 Counting2[(BYTE)(c>>8) ]++;
574 Counting3[(BYTE)(c>>16)]++;
575 Counting4[ c>>24 ]++;
576 c = cached; cached = MEM_read32(ip); ip += 4;
577 Counting1[(BYTE) c ]++;
578 Counting2[(BYTE)(c>>8) ]++;
579 Counting3[(BYTE)(c>>16)]++;
580 Counting4[ c>>24 ]++;
581 c = cached; cached = MEM_read32(ip); ip += 4;
582 Counting1[(BYTE) c ]++;
583 Counting2[(BYTE)(c>>8) ]++;
584 Counting3[(BYTE)(c>>16)]++;
585 Counting4[ c>>24 ]++;
586 c = cached; cached = MEM_read32(ip); ip += 4;
587 Counting1[(BYTE) c ]++;
588 Counting2[(BYTE)(c>>8) ]++;
589 Counting3[(BYTE)(c>>16)]++;
590 Counting4[ c>>24 ]++;
591 }
592 ip-=4;
593 }
594
595 /* finish last symbols */
596 while (ip<iend) Counting1[*ip++]++;
597
598 if (checkMax) { /* verify stats will fit into destination table */
599 for (s=255; s>maxSymbolValue; s--)
600 {
601 Counting1[s] += Counting2[s] + Counting3[s] + Counting4[s];
602 if (Counting1[s]) return ERROR(maxSymbolValue_tooSmall);
603 } }
604
605 for (s=0; s<=maxSymbolValue; s++) {
606 count[s] = Counting1[s] + Counting2[s] + Counting3[s] + Counting4[s];
607 if (count[s] > max) max = count[s];
608 }
609
610 while (!count[maxSymbolValue]) maxSymbolValue--;
611 *maxSymbolValuePtr = maxSymbolValue;
612 return (size_t)max;
613}
614
615/* fast variant (unsafe : won't check if src contains values beyond count[] limit) */
616size_t FSE_countFast(unsigned* count, unsigned* maxSymbolValuePtr,
617 const void* source, size_t sourceSize)
618{
619 if (sourceSize < 1500) return FSE_count_simple(count, maxSymbolValuePtr, source, sourceSize);
620 return FSE_count_parallel(count, maxSymbolValuePtr, source, sourceSize, 0);
621}
622
623size_t FSE_count(unsigned* count, unsigned* maxSymbolValuePtr,
624 const void* source, size_t sourceSize)
625{
626 if (*maxSymbolValuePtr <255)
627 return FSE_count_parallel(count, maxSymbolValuePtr, source, sourceSize, 1);
628 *maxSymbolValuePtr = 255;
629 return FSE_countFast(count, maxSymbolValuePtr, source, sourceSize);
630}
631
632
633/*-**************************************************************
Yann Collet4856a002015-01-24 01:58:16 +0100634* FSE Compression Code
635****************************************************************/
Yann Collet4ddb1f52016-01-28 03:24:53 +0100636/*!
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100637FSE_CTable is a variable size structure which contains :
Yann Collet4856a002015-01-24 01:58:16 +0100638 U16 tableLog;
639 U16 maxSymbolValue;
640 U16 nextStateNumber[1 << tableLog]; // This size is variable
641 FSE_symbolCompressionTransform symbolTT[maxSymbolValue+1]; // This size is variable
642Allocation is manual, since C standard does not support variable-size structures.
643*/
644
645size_t FSE_sizeof_CTable (unsigned maxSymbolValue, unsigned tableLog)
646{
647 size_t size;
648 FSE_STATIC_ASSERT((size_t)FSE_CTABLE_SIZE_U32(FSE_MAX_TABLELOG, FSE_MAX_SYMBOL_VALUE)*4 >= sizeof(CTable_max_t)); /* A compilation error here means FSE_CTABLE_SIZE_U32 is not large enough */
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100649 if (tableLog > FSE_MAX_TABLELOG) return ERROR(GENERIC);
Yann Collet4856a002015-01-24 01:58:16 +0100650 size = FSE_CTABLE_SIZE_U32 (tableLog, maxSymbolValue) * sizeof(U32);
651 return size;
652}
653
Yann Collet1efa31f2015-07-04 15:56:41 -0800654FSE_CTable* FSE_createCTable (unsigned maxSymbolValue, unsigned tableLog)
Yann Collet4856a002015-01-24 01:58:16 +0100655{
656 size_t size;
657 if (tableLog > FSE_TABLELOG_ABSOLUTE_MAX) tableLog = FSE_TABLELOG_ABSOLUTE_MAX;
658 size = FSE_CTABLE_SIZE_U32 (tableLog, maxSymbolValue) * sizeof(U32);
Yann Collet1efa31f2015-07-04 15:56:41 -0800659 return (FSE_CTable*)malloc(size);
Yann Collet4856a002015-01-24 01:58:16 +0100660}
661
Yann Collet1efa31f2015-07-04 15:56:41 -0800662void FSE_freeCTable (FSE_CTable* ct)
Yann Collet4856a002015-01-24 01:58:16 +0100663{
Yann Collet1efa31f2015-07-04 15:56:41 -0800664 free(ct);
Yann Collet4856a002015-01-24 01:58:16 +0100665}
666
Yann Colletd02114e2015-08-21 03:59:31 +0100667/* provides the minimum logSize to safely represent a distribution */
668static unsigned FSE_minTableLog(size_t srcSize, unsigned maxSymbolValue)
Yann Collet4856a002015-01-24 01:58:16 +0100669{
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100670 U32 minBitsSrc = BIT_highbit32((U32)(srcSize - 1)) + 1;
671 U32 minBitsSymbols = BIT_highbit32(maxSymbolValue) + 2;
672 U32 minBits = minBitsSrc < minBitsSymbols ? minBitsSrc : minBitsSymbols;
673 return minBits;
Yann Colletd02114e2015-08-21 03:59:31 +0100674}
675
676unsigned FSE_optimalTableLog(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue)
677{
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100678 U32 maxBitsSrc = BIT_highbit32((U32)(srcSize - 1)) - 2;
Yann Colletd02114e2015-08-21 03:59:31 +0100679 U32 tableLog = maxTableLog;
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100680 U32 minBits = FSE_minTableLog(srcSize, maxSymbolValue);
Yann Collet4856a002015-01-24 01:58:16 +0100681 if (tableLog==0) tableLog = FSE_DEFAULT_TABLELOG;
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100682 if (maxBitsSrc < tableLog) tableLog = maxBitsSrc; /* Accuracy can be reduced */
683 if (minBits > tableLog) tableLog = minBits; /* Need a minimum to safely represent all symbol values */
Yann Collet4856a002015-01-24 01:58:16 +0100684 if (tableLog < FSE_MIN_TABLELOG) tableLog = FSE_MIN_TABLELOG;
685 if (tableLog > FSE_MAX_TABLELOG) tableLog = FSE_MAX_TABLELOG;
686 return tableLog;
687}
688
689
Yann Collet26aa1ec2015-02-24 09:05:58 +0100690/* Secondary normalization method.
691 To be used when primary method fails. */
692
693static size_t FSE_normalizeM2(short* norm, U32 tableLog, const unsigned* count, size_t total, U32 maxSymbolValue)
Yann Colleta3c75ba2015-02-21 03:31:59 +0100694{
695 U32 s;
Yann Colleta3c75ba2015-02-21 03:31:59 +0100696 U32 distributed = 0;
697 U32 ToDistribute;
698
699 /* Init */
Yann Colleta3c75ba2015-02-21 03:31:59 +0100700 U32 lowThreshold = (U32)(total >> tableLog);
701 U32 lowOne = (U32)((total * 3) >> (tableLog + 1));
702
Yann Colletfb810d62016-01-28 00:18:06 +0100703 for (s=0; s<=maxSymbolValue; s++) {
704 if (count[s] == 0) {
Yann Colleta3c75ba2015-02-21 03:31:59 +0100705 norm[s]=0;
706 continue;
707 }
Yann Colletfb810d62016-01-28 00:18:06 +0100708 if (count[s] <= lowThreshold) {
Yann Colleta3c75ba2015-02-21 03:31:59 +0100709 norm[s] = -1;
710 distributed++;
711 total -= count[s];
712 continue;
713 }
Yann Colletfb810d62016-01-28 00:18:06 +0100714 if (count[s] <= lowOne) {
Yann Colleta3c75ba2015-02-21 03:31:59 +0100715 norm[s] = 1;
716 distributed++;
717 total -= count[s];
718 continue;
719 }
720 norm[s]=-2;
721 }
722 ToDistribute = (1 << tableLog) - distributed;
723
Yann Colletfb810d62016-01-28 00:18:06 +0100724 if ((total / ToDistribute) > lowOne) {
Yann Colleta3c75ba2015-02-21 03:31:59 +0100725 /* risk of rounding to zero */
726 lowOne = (U32)((total * 3) / (ToDistribute * 2));
Yann Colletfb810d62016-01-28 00:18:06 +0100727 for (s=0; s<=maxSymbolValue; s++) {
728 if ((norm[s] == -2) && (count[s] <= lowOne)) {
Yann Colleta3c75ba2015-02-21 03:31:59 +0100729 norm[s] = 1;
730 distributed++;
731 total -= count[s];
732 continue;
Yann Colletfb810d62016-01-28 00:18:06 +0100733 } }
Yann Colleta3c75ba2015-02-21 03:31:59 +0100734 ToDistribute = (1 << tableLog) - distributed;
735 }
736
Yann Colletfb810d62016-01-28 00:18:06 +0100737 if (distributed == maxSymbolValue+1) {
Yann Collet26aa1ec2015-02-24 09:05:58 +0100738 /* all values are pretty poor;
739 probably incompressible data (should have already been detected);
740 find max, then give all remaining points to max */
Yann Colleta3c75ba2015-02-21 03:31:59 +0100741 U32 maxV = 0, maxC =0;
742 for (s=0; s<=maxSymbolValue; s++)
743 if (count[s] > maxC) maxV=s, maxC=count[s];
Yann Collet1efa31f2015-07-04 15:56:41 -0800744 norm[maxV] += (short)ToDistribute;
Yann Colleta3c75ba2015-02-21 03:31:59 +0100745 return 0;
746 }
747
748 {
749 U64 const vStepLog = 62 - tableLog;
750 U64 const mid = (1ULL << (vStepLog-1)) - 1;
751 U64 const rStep = ((((U64)1<<vStepLog) * ToDistribute) + mid) / total; /* scale on remaining */
752 U64 tmpTotal = mid;
Yann Colletfb810d62016-01-28 00:18:06 +0100753 for (s=0; s<=maxSymbolValue; s++) {
754 if (norm[s]==-2) {
Yann Colleta3c75ba2015-02-21 03:31:59 +0100755 U64 end = tmpTotal + (count[s] * rStep);
756 U32 sStart = (U32)(tmpTotal >> vStepLog);
757 U32 sEnd = (U32)(end >> vStepLog);
758 U32 weight = sEnd - sStart;
759 if (weight < 1)
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100760 return ERROR(GENERIC);
Yann Collet213089c2015-06-18 07:43:16 -0800761 norm[s] = (short)weight;
Yann Colleta3c75ba2015-02-21 03:31:59 +0100762 tmpTotal = end;
Yann Colletfb810d62016-01-28 00:18:06 +0100763 } } }
Yann Colleta3c75ba2015-02-21 03:31:59 +0100764
765 return 0;
766}
Yann Colleta3c75ba2015-02-21 03:31:59 +0100767
Yann Collet4856a002015-01-24 01:58:16 +0100768
769size_t FSE_normalizeCount (short* normalizedCounter, unsigned tableLog,
770 const unsigned* count, size_t total,
771 unsigned maxSymbolValue)
772{
773 /* Sanity checks */
774 if (tableLog==0) tableLog = FSE_DEFAULT_TABLELOG;
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100775 if (tableLog < FSE_MIN_TABLELOG) return ERROR(GENERIC); /* Unsupported size */
Yann Colletfb810d62016-01-28 00:18:06 +0100776 if (tableLog > FSE_MAX_TABLELOG) return ERROR(tableLog_tooLarge); /* Unsupported size */
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100777 if (tableLog < FSE_minTableLog(total, maxSymbolValue)) return ERROR(GENERIC); /* Too small tableLog, compression potentially impossible */
Yann Collet4856a002015-01-24 01:58:16 +0100778
779 {
780 U32 const rtbTable[] = { 0, 473195, 504333, 520860, 550000, 700000, 750000, 830000 };
781 U64 const scale = 62 - tableLog;
782 U64 const step = ((U64)1<<62) / total; /* <== here, one division ! */
783 U64 const vStep = 1ULL<<(scale-20);
784 int stillToDistribute = 1<<tableLog;
785 unsigned s;
786 unsigned largest=0;
787 short largestP=0;
788 U32 lowThreshold = (U32)(total >> tableLog);
789
Yann Colletfb810d62016-01-28 00:18:06 +0100790 for (s=0; s<=maxSymbolValue; s++) {
791 if (count[s] == total) return 0; /* rle special case */
792 if (count[s] == 0) { normalizedCounter[s]=0; continue; }
793 if (count[s] <= lowThreshold) {
Yann Collet4856a002015-01-24 01:58:16 +0100794 normalizedCounter[s] = -1;
795 stillToDistribute--;
Yann Colletfb810d62016-01-28 00:18:06 +0100796 } else {
Yann Collet4856a002015-01-24 01:58:16 +0100797 short proba = (short)((count[s]*step) >> scale);
Yann Colletfb810d62016-01-28 00:18:06 +0100798 if (proba<8) {
Yann Collet2ddf7e92015-02-08 20:26:47 +0100799 U64 restToBeat = vStep * rtbTable[proba];
Yann Collet4856a002015-01-24 01:58:16 +0100800 proba += (count[s]*step) - ((U64)proba<<scale) > restToBeat;
801 }
Yann Colletfb810d62016-01-28 00:18:06 +0100802 if (proba > largestP) largestP=proba, largest=s;
Yann Collet4856a002015-01-24 01:58:16 +0100803 normalizedCounter[s] = proba;
804 stillToDistribute -= proba;
Yann Colletfb810d62016-01-28 00:18:06 +0100805 } }
806 if (-stillToDistribute >= (normalizedCounter[largest] >> 1)) {
Yann Collet26aa1ec2015-02-24 09:05:58 +0100807 /* corner case, need another normalization method */
808 size_t errorCode = FSE_normalizeM2(normalizedCounter, tableLog, count, total, maxSymbolValue);
Yann Collet565b81d2015-01-29 06:51:30 +0100809 if (FSE_isError(errorCode)) return errorCode;
Yann Collet4856a002015-01-24 01:58:16 +0100810 }
811 else normalizedCounter[largest] += (short)stillToDistribute;
812 }
813
814#if 0
815 { /* Print Table (debug) */
Yann Collet565b81d2015-01-29 06:51:30 +0100816 U32 s;
817 U32 nTotal = 0;
Yann Collet4856a002015-01-24 01:58:16 +0100818 for (s=0; s<=maxSymbolValue; s++)
819 printf("%3i: %4i \n", s, normalizedCounter[s]);
Yann Collet565b81d2015-01-29 06:51:30 +0100820 for (s=0; s<=maxSymbolValue; s++)
821 nTotal += abs(normalizedCounter[s]);
822 if (nTotal != (1U<<tableLog))
823 printf("Warning !!! Total == %u != %u !!!", nTotal, 1U<<tableLog);
Yann Collet4856a002015-01-24 01:58:16 +0100824 getchar();
825 }
826#endif
827
828 return tableLog;
829}
830
831
Yann Collet1efa31f2015-07-04 15:56:41 -0800832/* fake FSE_CTable, for raw (uncompressed) input */
833size_t FSE_buildCTable_raw (FSE_CTable* ct, unsigned nbBits)
Yann Collet4856a002015-01-24 01:58:16 +0100834{
835 const unsigned tableSize = 1 << nbBits;
836 const unsigned tableMask = tableSize - 1;
837 const unsigned maxSymbolValue = tableMask;
Yann Collet3b994cb2016-01-06 01:58:37 +0100838 void* const ptr = ct;
839 U16* const tableU16 = ( (U16*) ptr) + 2;
840 void* const FSCT = ((U32*)ptr) + 1 /* header */ + (tableSize>>1); /* assumption : tableLog >= 1 */
841 FSE_symbolCompressionTransform* const symbolTT = (FSE_symbolCompressionTransform*) (FSCT);
Yann Collet4856a002015-01-24 01:58:16 +0100842 unsigned s;
843
844 /* Sanity checks */
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100845 if (nbBits < 1) return ERROR(GENERIC); /* min size */
Yann Collet4856a002015-01-24 01:58:16 +0100846
847 /* header */
848 tableU16[-2] = (U16) nbBits;
849 tableU16[-1] = (U16) maxSymbolValue;
850
851 /* Build table */
852 for (s=0; s<tableSize; s++)
853 tableU16[s] = (U16)(tableSize + s);
854
855 /* Build Symbol Transformation Table */
Yann Colletfb810d62016-01-28 00:18:06 +0100856 for (s=0; s<=maxSymbolValue; s++) {
Yann Collet77c82b62015-08-02 01:19:09 +0100857 symbolTT[s].deltaNbBits = nbBits << 16;
Yann Collet4856a002015-01-24 01:58:16 +0100858 symbolTT[s].deltaFindState = s-1;
Yann Collet4856a002015-01-24 01:58:16 +0100859 }
860
861 return 0;
862}
863
Yann Collet1efa31f2015-07-04 15:56:41 -0800864/* fake FSE_CTable, for rle (100% always same symbol) input */
865size_t FSE_buildCTable_rle (FSE_CTable* ct, BYTE symbolValue)
Yann Collet4856a002015-01-24 01:58:16 +0100866{
Yann Collet3b994cb2016-01-06 01:58:37 +0100867 void* ptr = ct;
868 U16* tableU16 = ( (U16*) ptr) + 2;
869 void* FSCTptr = (U32*)ptr + 2;
870 FSE_symbolCompressionTransform* symbolTT = (FSE_symbolCompressionTransform*) FSCTptr;
Yann Collet4856a002015-01-24 01:58:16 +0100871
872 /* header */
873 tableU16[-2] = (U16) 0;
874 tableU16[-1] = (U16) symbolValue;
875
876 /* Build table */
877 tableU16[0] = 0;
878 tableU16[1] = 0; /* just in case */
879
880 /* Build Symbol Transformation Table */
Yann Collet4ddb1f52016-01-28 03:24:53 +0100881 symbolTT[symbolValue].deltaNbBits = 0;
882 symbolTT[symbolValue].deltaFindState = 0;
Yann Collet4856a002015-01-24 01:58:16 +0100883
884 return 0;
885}
886
887
Yann Colleta7875502015-08-07 15:21:00 +0100888static size_t FSE_compress_usingCTable_generic (void* dst, size_t dstSize,
Yann Collet4856a002015-01-24 01:58:16 +0100889 const void* src, size_t srcSize,
Yann Colleta7875502015-08-07 15:21:00 +0100890 const FSE_CTable* ct, const unsigned fast)
Yann Collet4856a002015-01-24 01:58:16 +0100891{
892 const BYTE* const istart = (const BYTE*) src;
893 const BYTE* ip;
894 const BYTE* const iend = istart + srcSize;
895
Yann Colleta7875502015-08-07 15:21:00 +0100896 size_t errorCode;
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100897 BIT_CStream_t bitC;
Yann Collet4856a002015-01-24 01:58:16 +0100898 FSE_CState_t CState1, CState2;
899
900
901 /* init */
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100902 errorCode = BIT_initCStream(&bitC, dst, dstSize);
Yann Colleta7875502015-08-07 15:21:00 +0100903 if (FSE_isError(errorCode)) return 0;
Yann Collet1efa31f2015-07-04 15:56:41 -0800904 FSE_initCState(&CState1, ct);
Yann Collet4856a002015-01-24 01:58:16 +0100905 CState2 = CState1;
906
907 ip=iend;
908
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100909#define FSE_FLUSHBITS(s) (fast ? BIT_flushBitsFast(s) : BIT_flushBits(s))
Yann Colleta7875502015-08-07 15:21:00 +0100910
Yann Collet4856a002015-01-24 01:58:16 +0100911 /* join to even */
Yann Collet4ddb1f52016-01-28 03:24:53 +0100912 if (srcSize & 1) {
Yann Collet1efa31f2015-07-04 15:56:41 -0800913 FSE_encodeSymbol(&bitC, &CState1, *--ip);
Yann Colleta7875502015-08-07 15:21:00 +0100914 FSE_FLUSHBITS(&bitC);
Yann Collet4856a002015-01-24 01:58:16 +0100915 }
916
917 /* join to mod 4 */
Yann Collet4ddb1f52016-01-28 03:24:53 +0100918 if ((sizeof(bitC.bitContainer)*8 > FSE_MAX_TABLELOG*4+7 ) && (srcSize & 2)) { /* test bit 2 */
Yann Collet1efa31f2015-07-04 15:56:41 -0800919 FSE_encodeSymbol(&bitC, &CState2, *--ip);
920 FSE_encodeSymbol(&bitC, &CState1, *--ip);
Yann Colleta7875502015-08-07 15:21:00 +0100921 FSE_FLUSHBITS(&bitC);
Yann Collet4856a002015-01-24 01:58:16 +0100922 }
923
924 /* 2 or 4 encoding per loop */
Yann Colleta7875502015-08-07 15:21:00 +0100925 for ( ; ip>istart ; )
Yann Collet4856a002015-01-24 01:58:16 +0100926 {
Yann Collet1efa31f2015-07-04 15:56:41 -0800927 FSE_encodeSymbol(&bitC, &CState2, *--ip);
Yann Collet4856a002015-01-24 01:58:16 +0100928
Yann Collet77c82b62015-08-02 01:19:09 +0100929 if (sizeof(bitC.bitContainer)*8 < FSE_MAX_TABLELOG*2+7 ) /* this test must be static */
Yann Colleta7875502015-08-07 15:21:00 +0100930 FSE_FLUSHBITS(&bitC);
Yann Collet4856a002015-01-24 01:58:16 +0100931
Yann Collet1efa31f2015-07-04 15:56:41 -0800932 FSE_encodeSymbol(&bitC, &CState1, *--ip);
Yann Collet4856a002015-01-24 01:58:16 +0100933
Yann Collet4ddb1f52016-01-28 03:24:53 +0100934 if (sizeof(bitC.bitContainer)*8 > FSE_MAX_TABLELOG*4+7 ) { /* this test must be static */
Yann Collet1efa31f2015-07-04 15:56:41 -0800935 FSE_encodeSymbol(&bitC, &CState2, *--ip);
936 FSE_encodeSymbol(&bitC, &CState1, *--ip);
Yann Collet4856a002015-01-24 01:58:16 +0100937 }
938
Yann Colleta7875502015-08-07 15:21:00 +0100939 FSE_FLUSHBITS(&bitC);
Yann Collet4856a002015-01-24 01:58:16 +0100940 }
941
942 FSE_flushCState(&bitC, &CState2);
943 FSE_flushCState(&bitC, &CState1);
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100944 return BIT_closeCStream(&bitC);
Yann Collet4856a002015-01-24 01:58:16 +0100945}
946
Yann Colleta7875502015-08-07 15:21:00 +0100947size_t FSE_compress_usingCTable (void* dst, size_t dstSize,
948 const void* src, size_t srcSize,
949 const FSE_CTable* ct)
950{
951 const unsigned fast = (dstSize >= FSE_BLOCKBOUND(srcSize));
952
953 if (fast)
954 return FSE_compress_usingCTable_generic(dst, dstSize, src, srcSize, ct, 1);
955 else
956 return FSE_compress_usingCTable_generic(dst, dstSize, src, srcSize, ct, 0);
957}
958
Yann Collet4856a002015-01-24 01:58:16 +0100959
Yann Collet4856a002015-01-24 01:58:16 +0100960size_t FSE_compressBound(size_t size) { return FSE_COMPRESSBOUND(size); }
961
Yann Collet4856a002015-01-24 01:58:16 +0100962size_t FSE_compress2 (void* dst, size_t dstSize, const void* src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog)
963{
964 const BYTE* const istart = (const BYTE*) src;
965 const BYTE* ip = istart;
966
967 BYTE* const ostart = (BYTE*) dst;
968 BYTE* op = ostart;
969 BYTE* const oend = ostart + dstSize;
970
971 U32 count[FSE_MAX_SYMBOL_VALUE+1];
972 S16 norm[FSE_MAX_SYMBOL_VALUE+1];
Yann Collet1efa31f2015-07-04 15:56:41 -0800973 CTable_max_t ct;
Yann Collet4856a002015-01-24 01:58:16 +0100974 size_t errorCode;
975
Yann Colleta7875502015-08-07 15:21:00 +0100976 /* init conditions */
977 if (srcSize <= 1) return 0; /* Uncompressible */
Yann Collet4856a002015-01-24 01:58:16 +0100978 if (!maxSymbolValue) maxSymbolValue = FSE_MAX_SYMBOL_VALUE;
979 if (!tableLog) tableLog = FSE_DEFAULT_TABLELOG;
980
981 /* Scan input and build symbol stats */
Yann Collet1efa31f2015-07-04 15:56:41 -0800982 errorCode = FSE_count (count, &maxSymbolValue, ip, srcSize);
Yann Collet4856a002015-01-24 01:58:16 +0100983 if (FSE_isError(errorCode)) return errorCode;
Yann Colleta3c75ba2015-02-21 03:31:59 +0100984 if (errorCode == srcSize) return 1;
Yann Collet6b5198f2015-08-26 19:22:01 +0100985 if (errorCode == 1) return 0; /* each symbol only present once */
Yann Colleta3c75ba2015-02-21 03:31:59 +0100986 if (errorCode < (srcSize >> 7)) return 0; /* Heuristic : not compressible enough */
Yann Collet4856a002015-01-24 01:58:16 +0100987
988 tableLog = FSE_optimalTableLog(tableLog, srcSize, maxSymbolValue);
989 errorCode = FSE_normalizeCount (norm, tableLog, count, srcSize, maxSymbolValue);
990 if (FSE_isError(errorCode)) return errorCode;
991
992 /* Write table description header */
Yann Colleta7875502015-08-07 15:21:00 +0100993 errorCode = FSE_writeNCount (op, oend-op, norm, maxSymbolValue, tableLog);
Yann Collet4856a002015-01-24 01:58:16 +0100994 if (FSE_isError(errorCode)) return errorCode;
995 op += errorCode;
996
997 /* Compress */
Yann Collet1efa31f2015-07-04 15:56:41 -0800998 errorCode = FSE_buildCTable (ct, norm, maxSymbolValue, tableLog);
Yann Collet4856a002015-01-24 01:58:16 +0100999 if (FSE_isError(errorCode)) return errorCode;
Yann Colleta7875502015-08-07 15:21:00 +01001000 errorCode = FSE_compress_usingCTable(op, oend - op, ip, srcSize, ct);
1001 if (errorCode == 0) return 0; /* not enough space for compressed data */
1002 op += errorCode;
Yann Collet4856a002015-01-24 01:58:16 +01001003
1004 /* check compressibility */
1005 if ( (size_t)(op-ostart) >= srcSize-1 )
1006 return 0;
1007
1008 return op-ostart;
1009}
1010
Yann Collet4856a002015-01-24 01:58:16 +01001011size_t FSE_compress (void* dst, size_t dstSize, const void* src, size_t srcSize)
1012{
1013 return FSE_compress2(dst, dstSize, src, (U32)srcSize, FSE_MAX_SYMBOL_VALUE, FSE_DEFAULT_TABLELOG);
1014}
1015
1016
Yann Collet4ddb1f52016-01-28 03:24:53 +01001017/*-*******************************************************
Yann Collet4856a002015-01-24 01:58:16 +01001018* Decompression (Byte symbols)
1019*********************************************************/
Yann Collet1efa31f2015-07-04 15:56:41 -08001020size_t FSE_buildDTable_rle (FSE_DTable* dt, BYTE symbolValue)
Yann Collet4856a002015-01-24 01:58:16 +01001021{
Yann Collet3b994cb2016-01-06 01:58:37 +01001022 void* ptr = dt;
1023 FSE_DTableHeader* const DTableH = (FSE_DTableHeader*)ptr;
1024 void* dPtr = dt + 1;
1025 FSE_decode_t* const cell = (FSE_decode_t*)dPtr;
Yann Collet4856a002015-01-24 01:58:16 +01001026
Yann Colleta7875502015-08-07 15:21:00 +01001027 DTableH->tableLog = 0;
1028 DTableH->fastMode = 0;
Yann Collet4856a002015-01-24 01:58:16 +01001029
1030 cell->newState = 0;
1031 cell->symbol = symbolValue;
1032 cell->nbBits = 0;
1033
1034 return 0;
1035}
1036
1037
Yann Collet1efa31f2015-07-04 15:56:41 -08001038size_t FSE_buildDTable_raw (FSE_DTable* dt, unsigned nbBits)
Yann Collet4856a002015-01-24 01:58:16 +01001039{
Yann Collet3b994cb2016-01-06 01:58:37 +01001040 void* ptr = dt;
1041 FSE_DTableHeader* const DTableH = (FSE_DTableHeader*)ptr;
1042 void* dPtr = dt + 1;
1043 FSE_decode_t* const dinfo = (FSE_decode_t*)dPtr;
Yann Collet4856a002015-01-24 01:58:16 +01001044 const unsigned tableSize = 1 << nbBits;
1045 const unsigned tableMask = tableSize - 1;
1046 const unsigned maxSymbolValue = tableMask;
1047 unsigned s;
1048
1049 /* Sanity checks */
Yann Colletb1f3f4b2015-10-18 22:18:32 +01001050 if (nbBits < 1) return ERROR(GENERIC); /* min size */
Yann Collet4856a002015-01-24 01:58:16 +01001051
1052 /* Build Decoding Table */
Yann Colleta7875502015-08-07 15:21:00 +01001053 DTableH->tableLog = (U16)nbBits;
1054 DTableH->fastMode = 1;
Yann Collet863ec402016-01-28 17:56:33 +01001055 for (s=0; s<=maxSymbolValue; s++) {
Yann Collet4856a002015-01-24 01:58:16 +01001056 dinfo[s].newState = 0;
1057 dinfo[s].symbol = (BYTE)s;
1058 dinfo[s].nbBits = (BYTE)nbBits;
1059 }
1060
1061 return 0;
1062}
1063
Yann Collet4856a002015-01-24 01:58:16 +01001064FORCE_INLINE size_t FSE_decompress_usingDTable_generic(
1065 void* dst, size_t maxDstSize,
1066 const void* cSrc, size_t cSrcSize,
Yann Colleta7875502015-08-07 15:21:00 +01001067 const FSE_DTable* dt, const unsigned fast)
Yann Collet4856a002015-01-24 01:58:16 +01001068{
1069 BYTE* const ostart = (BYTE*) dst;
1070 BYTE* op = ostart;
1071 BYTE* const omax = op + maxDstSize;
1072 BYTE* const olimit = omax-3;
1073
Yann Colletb1f3f4b2015-10-18 22:18:32 +01001074 BIT_DStream_t bitD;
Yann Collet1efa31f2015-07-04 15:56:41 -08001075 FSE_DState_t state1;
1076 FSE_DState_t state2;
Yann Collet4856a002015-01-24 01:58:16 +01001077 size_t errorCode;
1078
1079 /* Init */
Yann Colletb1f3f4b2015-10-18 22:18:32 +01001080 errorCode = BIT_initDStream(&bitD, cSrc, cSrcSize); /* replaced last arg by maxCompressed Size */
Yann Collet4856a002015-01-24 01:58:16 +01001081 if (FSE_isError(errorCode)) return errorCode;
1082
Yann Collet1efa31f2015-07-04 15:56:41 -08001083 FSE_initDState(&state1, &bitD, dt);
1084 FSE_initDState(&state2, &bitD, dt);
Yann Collet4856a002015-01-24 01:58:16 +01001085
Yann Collet77c82b62015-08-02 01:19:09 +01001086#define FSE_GETSYMBOL(statePtr) fast ? FSE_decodeSymbolFast(statePtr, &bitD) : FSE_decodeSymbol(statePtr, &bitD)
Yann Collet4856a002015-01-24 01:58:16 +01001087
Yann Collet77c82b62015-08-02 01:19:09 +01001088 /* 4 symbols per loop */
Yann Collet863ec402016-01-28 17:56:33 +01001089 for ( ; (BIT_reloadDStream(&bitD)==BIT_DStream_unfinished) && (op<olimit) ; op+=4) {
Yann Collet77c82b62015-08-02 01:19:09 +01001090 op[0] = FSE_GETSYMBOL(&state1);
Yann Collet4856a002015-01-24 01:58:16 +01001091
Yann Collet77c82b62015-08-02 01:19:09 +01001092 if (FSE_MAX_TABLELOG*2+7 > sizeof(bitD.bitContainer)*8) /* This test must be static */
Yann Colletb1f3f4b2015-10-18 22:18:32 +01001093 BIT_reloadDStream(&bitD);
Yann Collet4856a002015-01-24 01:58:16 +01001094
Yann Collet77c82b62015-08-02 01:19:09 +01001095 op[1] = FSE_GETSYMBOL(&state2);
Yann Collet4856a002015-01-24 01:58:16 +01001096
Yann Collet77c82b62015-08-02 01:19:09 +01001097 if (FSE_MAX_TABLELOG*4+7 > sizeof(bitD.bitContainer)*8) /* This test must be static */
Yann Colletb1f3f4b2015-10-18 22:18:32 +01001098 { if (BIT_reloadDStream(&bitD) > BIT_DStream_unfinished) { op+=2; break; } }
Yann Collet77c82b62015-08-02 01:19:09 +01001099
1100 op[2] = FSE_GETSYMBOL(&state1);
1101
1102 if (FSE_MAX_TABLELOG*2+7 > sizeof(bitD.bitContainer)*8) /* This test must be static */
Yann Colletb1f3f4b2015-10-18 22:18:32 +01001103 BIT_reloadDStream(&bitD);
Yann Collet77c82b62015-08-02 01:19:09 +01001104
1105 op[3] = FSE_GETSYMBOL(&state2);
Yann Collet4856a002015-01-24 01:58:16 +01001106 }
1107
1108 /* tail */
Yann Colletb1f3f4b2015-10-18 22:18:32 +01001109 /* note : BIT_reloadDStream(&bitD) >= FSE_DStream_partiallyFilled; Ends at exactly BIT_DStream_completed */
Yann Collet863ec402016-01-28 17:56:33 +01001110 while (1) {
Yann Colletb1f3f4b2015-10-18 22:18:32 +01001111 if ( (BIT_reloadDStream(&bitD)>BIT_DStream_completed) || (op==omax) || (BIT_endOfDStream(&bitD) && (fast || FSE_endOfDState(&state1))) )
Yann Collet4856a002015-01-24 01:58:16 +01001112 break;
1113
Yann Collet77c82b62015-08-02 01:19:09 +01001114 *op++ = FSE_GETSYMBOL(&state1);
Yann Collet4856a002015-01-24 01:58:16 +01001115
Yann Colletb1f3f4b2015-10-18 22:18:32 +01001116 if ( (BIT_reloadDStream(&bitD)>BIT_DStream_completed) || (op==omax) || (BIT_endOfDStream(&bitD) && (fast || FSE_endOfDState(&state2))) )
Yann Collet4856a002015-01-24 01:58:16 +01001117 break;
1118
Yann Collet77c82b62015-08-02 01:19:09 +01001119 *op++ = FSE_GETSYMBOL(&state2);
Yann Collet4856a002015-01-24 01:58:16 +01001120 }
1121
1122 /* end ? */
Yann Colletb1f3f4b2015-10-18 22:18:32 +01001123 if (BIT_endOfDStream(&bitD) && FSE_endOfDState(&state1) && FSE_endOfDState(&state2))
Yann Collet4856a002015-01-24 01:58:16 +01001124 return op-ostart;
1125
Yann Colletb1f3f4b2015-10-18 22:18:32 +01001126 if (op==omax) return ERROR(dstSize_tooSmall); /* dst buffer is full, but cSrc unfinished */
Yann Collet4856a002015-01-24 01:58:16 +01001127
Yann Colletb1f3f4b2015-10-18 22:18:32 +01001128 return ERROR(corruption_detected);
Yann Collet4856a002015-01-24 01:58:16 +01001129}
1130
1131
1132size_t FSE_decompress_usingDTable(void* dst, size_t originalSize,
1133 const void* cSrc, size_t cSrcSize,
Yann Colleta7875502015-08-07 15:21:00 +01001134 const FSE_DTable* dt)
Yann Collet4856a002015-01-24 01:58:16 +01001135{
Yann Collet3b994cb2016-01-06 01:58:37 +01001136 const void* ptr = dt;
1137 const FSE_DTableHeader* DTableH = (const FSE_DTableHeader*)ptr;
Yann Colleta7875502015-08-07 15:21:00 +01001138 const U32 fastMode = DTableH->fastMode;
1139
Yann Collet4856a002015-01-24 01:58:16 +01001140 /* select fast mode (static) */
Yann Collet1efa31f2015-07-04 15:56:41 -08001141 if (fastMode) return FSE_decompress_usingDTable_generic(dst, originalSize, cSrc, cSrcSize, dt, 1);
1142 return FSE_decompress_usingDTable_generic(dst, originalSize, cSrc, cSrcSize, dt, 0);
Yann Collet4856a002015-01-24 01:58:16 +01001143}
1144
1145
1146size_t FSE_decompress(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize)
1147{
1148 const BYTE* const istart = (const BYTE*)cSrc;
1149 const BYTE* ip = istart;
1150 short counting[FSE_MAX_SYMBOL_VALUE+1];
Yann Collet1efa31f2015-07-04 15:56:41 -08001151 DTable_max_t dt; /* Static analyzer seems unable to understand this table will be properly initialized later */
Yann Collet4856a002015-01-24 01:58:16 +01001152 unsigned tableLog;
Yann Collet1efa31f2015-07-04 15:56:41 -08001153 unsigned maxSymbolValue = FSE_MAX_SYMBOL_VALUE;
Yann Colleta7875502015-08-07 15:21:00 +01001154 size_t errorCode;
Yann Collet4856a002015-01-24 01:58:16 +01001155
Yann Colletb1f3f4b2015-10-18 22:18:32 +01001156 if (cSrcSize<2) return ERROR(srcSize_wrong); /* too small input size */
Yann Collet4856a002015-01-24 01:58:16 +01001157
1158 /* normal FSE decoding mode */
Yann Collet1efa31f2015-07-04 15:56:41 -08001159 errorCode = FSE_readNCount (counting, &maxSymbolValue, &tableLog, istart, cSrcSize);
Yann Collet4856a002015-01-24 01:58:16 +01001160 if (FSE_isError(errorCode)) return errorCode;
Yann Colletb1f3f4b2015-10-18 22:18:32 +01001161 if (errorCode >= cSrcSize) return ERROR(srcSize_wrong); /* too small input size */
Yann Collet4856a002015-01-24 01:58:16 +01001162 ip += errorCode;
1163 cSrcSize -= errorCode;
1164
Yann Colleta7875502015-08-07 15:21:00 +01001165 errorCode = FSE_buildDTable (dt, counting, maxSymbolValue, tableLog);
1166 if (FSE_isError(errorCode)) return errorCode;
Yann Collet4856a002015-01-24 01:58:16 +01001167
1168 /* always return, even if it is an error code */
Yann Colleta7875502015-08-07 15:21:00 +01001169 return FSE_decompress_usingDTable (dst, maxDstSize, ip, cSrcSize, dt);
Yann Collet4856a002015-01-24 01:58:16 +01001170}
1171
1172
Yann Collet4856a002015-01-24 01:58:16 +01001173
Yann Collete8c6bb12015-07-26 00:23:57 +01001174#endif /* FSE_COMMONDEFS_ONLY */