2 * FSE : Finite State Entropy encoder
3 * Copyright (C) 2013-2015, Yann Collet.
5 * BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are
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
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.
30 * This program is free software; you can redistribute it and/or modify it under
31 * the terms of the GNU General Public License version 2 as published by the
32 * Free Software Foundation. This program is dual-licensed; you may select
33 * either version 2 of the GNU General Public License ("GPL") or BSD license
36 * You can contact the author at :
37 * - Source repository : https://github.com/Cyan4973/FiniteStateEntropy
40 /* **************************************************************
42 ****************************************************************/
43 #define FORCE_INLINE static __always_inline
45 /* **************************************************************
47 ****************************************************************/
48 #include "bitstream.h"
50 #include <linux/compiler.h>
51 #include <linux/kernel.h>
52 #include <linux/math64.h>
53 #include <linux/string.h> /* memcpy, memset */
55 /* **************************************************************
57 ****************************************************************/
58 #define FSE_STATIC_ASSERT(c) \
60 enum { FSE_static_assert = 1 / (int)(!!(c)) }; \
61 } /* use only *after* variable declarations */
63 /* **************************************************************
65 ****************************************************************/
67 designed to be included
68 for type-specific functions (template emulation in C)
69 Objective is to write these functions only once, for improved maintenance
73 #ifndef FSE_FUNCTION_EXTENSION
74 #error "FSE_FUNCTION_EXTENSION must be defined"
76 #ifndef FSE_FUNCTION_TYPE
77 #error "FSE_FUNCTION_TYPE must be defined"
81 #define FSE_CAT(X, Y) X##Y
82 #define FSE_FUNCTION_NAME(X, Y) FSE_CAT(X, Y)
83 #define FSE_TYPE_NAME(X, Y) FSE_CAT(X, Y)
85 /* Function templates */
87 /* FSE_buildCTable_wksp() :
88 * Same as FSE_buildCTable(), but using an externally allocated scratch buffer (`workSpace`).
89 * wkspSize should be sized to handle worst case situation, which is `1<<max_tableLog * sizeof(FSE_FUNCTION_TYPE)`
90 * workSpace must also be properly aligned with FSE_FUNCTION_TYPE requirements
92 size_t FSE_buildCTable_wksp(FSE_CTable
*ct
, const short *normalizedCounter
, unsigned maxSymbolValue
, unsigned tableLog
, void *workspace
, size_t workspaceSize
)
94 U32
const tableSize
= 1 << tableLog
;
95 U32
const tableMask
= tableSize
- 1;
97 U16
*const tableU16
= ((U16
*)ptr
) + 2;
98 void *const FSCT
= ((U32
*)ptr
) + 1 /* header */ + (tableLog
? tableSize
>> 1 : 1);
99 FSE_symbolCompressionTransform
*const symbolTT
= (FSE_symbolCompressionTransform
*)(FSCT
);
100 U32
const step
= FSE_TABLESTEP(tableSize
);
101 U32 highThreshold
= tableSize
- 1;
104 FSE_FUNCTION_TYPE
*tableSymbol
;
105 size_t spaceUsed32
= 0;
107 cumul
= (U32
*)workspace
+ spaceUsed32
;
108 spaceUsed32
+= FSE_MAX_SYMBOL_VALUE
+ 2;
109 tableSymbol
= (FSE_FUNCTION_TYPE
*)((U32
*)workspace
+ spaceUsed32
);
110 spaceUsed32
+= ALIGN(sizeof(FSE_FUNCTION_TYPE
) * ((size_t)1 << tableLog
), sizeof(U32
)) >> 2;
112 if ((spaceUsed32
<< 2) > workspaceSize
)
113 return ERROR(tableLog_tooLarge
);
114 workspace
= (U32
*)workspace
+ spaceUsed32
;
115 workspaceSize
-= (spaceUsed32
<< 2);
118 tableU16
[-2] = (U16
)tableLog
;
119 tableU16
[-1] = (U16
)maxSymbolValue
;
121 /* For explanations on how to distribute symbol values over the table :
122 * http://fastcompression.blogspot.fr/2014/02/fse-distributing-symbol-values.html */
124 /* symbol start positions */
128 for (u
= 1; u
<= maxSymbolValue
+ 1; u
++) {
129 if (normalizedCounter
[u
- 1] == -1) { /* Low proba symbol */
130 cumul
[u
] = cumul
[u
- 1] + 1;
131 tableSymbol
[highThreshold
--] = (FSE_FUNCTION_TYPE
)(u
- 1);
133 cumul
[u
] = cumul
[u
- 1] + normalizedCounter
[u
- 1];
136 cumul
[maxSymbolValue
+ 1] = tableSize
+ 1;
143 for (symbol
= 0; symbol
<= maxSymbolValue
; symbol
++) {
145 for (nbOccurences
= 0; nbOccurences
< normalizedCounter
[symbol
]; nbOccurences
++) {
146 tableSymbol
[position
] = (FSE_FUNCTION_TYPE
)symbol
;
147 position
= (position
+ step
) & tableMask
;
148 while (position
> highThreshold
)
149 position
= (position
+ step
) & tableMask
; /* Low proba area */
154 return ERROR(GENERIC
); /* Must have gone through all positions */
160 for (u
= 0; u
< tableSize
; u
++) {
161 FSE_FUNCTION_TYPE s
= tableSymbol
[u
]; /* note : static analyzer may not understand tableSymbol is properly initialized */
162 tableU16
[cumul
[s
]++] = (U16
)(tableSize
+ u
); /* TableU16 : sorted by symbol order; gives next state value */
166 /* Build Symbol Transformation Table */
170 for (s
= 0; s
<= maxSymbolValue
; s
++) {
171 switch (normalizedCounter
[s
]) {
176 symbolTT
[s
].deltaNbBits
= (tableLog
<< 16) - (1 << tableLog
);
177 symbolTT
[s
].deltaFindState
= total
- 1;
181 U32
const maxBitsOut
= tableLog
- BIT_highbit32(normalizedCounter
[s
] - 1);
182 U32
const minStatePlus
= normalizedCounter
[s
] << maxBitsOut
;
183 symbolTT
[s
].deltaNbBits
= (maxBitsOut
<< 16) - minStatePlus
;
184 symbolTT
[s
].deltaFindState
= total
- normalizedCounter
[s
];
185 total
+= normalizedCounter
[s
];
194 /*-**************************************************************
195 * FSE NCount encoding-decoding
196 ****************************************************************/
197 size_t FSE_NCountWriteBound(unsigned maxSymbolValue
, unsigned tableLog
)
199 size_t const maxHeaderSize
= (((maxSymbolValue
+ 1) * tableLog
) >> 3) + 3;
200 return maxSymbolValue
? maxHeaderSize
: FSE_NCOUNTBOUND
; /* maxSymbolValue==0 ? use default */
203 static size_t FSE_writeNCount_generic(void *header
, size_t headerBufferSize
, const short *normalizedCounter
, unsigned maxSymbolValue
, unsigned tableLog
,
204 unsigned writeIsSafe
)
206 BYTE
*const ostart
= (BYTE
*)header
;
208 BYTE
*const oend
= ostart
+ headerBufferSize
;
210 const int tableSize
= 1 << tableLog
;
215 unsigned charnum
= 0;
221 bitStream
+= (tableLog
- FSE_MIN_TABLELOG
) << bitCount
;
225 remaining
= tableSize
+ 1; /* +1 for extra accuracy */
226 threshold
= tableSize
;
227 nbBits
= tableLog
+ 1;
229 while (remaining
> 1) { /* stops at 1 */
231 unsigned start
= charnum
;
232 while (!normalizedCounter
[charnum
])
234 while (charnum
>= start
+ 24) {
236 bitStream
+= 0xFFFFU
<< bitCount
;
237 if ((!writeIsSafe
) && (out
> oend
- 2))
238 return ERROR(dstSize_tooSmall
); /* Buffer overflow */
239 out
[0] = (BYTE
)bitStream
;
240 out
[1] = (BYTE
)(bitStream
>> 8);
244 while (charnum
>= start
+ 3) {
246 bitStream
+= 3 << bitCount
;
249 bitStream
+= (charnum
- start
) << bitCount
;
252 if ((!writeIsSafe
) && (out
> oend
- 2))
253 return ERROR(dstSize_tooSmall
); /* Buffer overflow */
254 out
[0] = (BYTE
)bitStream
;
255 out
[1] = (BYTE
)(bitStream
>> 8);
262 int count
= normalizedCounter
[charnum
++];
263 int const max
= (2 * threshold
- 1) - remaining
;
264 remaining
-= count
< 0 ? -count
: count
;
265 count
++; /* +1 for extra accuracy */
266 if (count
>= threshold
)
267 count
+= max
; /* [0..max[ [max..threshold[ (...) [threshold+max 2*threshold[ */
268 bitStream
+= count
<< bitCount
;
270 bitCount
-= (count
< max
);
271 previous0
= (count
== 1);
273 return ERROR(GENERIC
);
274 while (remaining
< threshold
)
275 nbBits
--, threshold
>>= 1;
278 if ((!writeIsSafe
) && (out
> oend
- 2))
279 return ERROR(dstSize_tooSmall
); /* Buffer overflow */
280 out
[0] = (BYTE
)bitStream
;
281 out
[1] = (BYTE
)(bitStream
>> 8);
288 /* flush remaining bitStream */
289 if ((!writeIsSafe
) && (out
> oend
- 2))
290 return ERROR(dstSize_tooSmall
); /* Buffer overflow */
291 out
[0] = (BYTE
)bitStream
;
292 out
[1] = (BYTE
)(bitStream
>> 8);
293 out
+= (bitCount
+ 7) / 8;
295 if (charnum
> maxSymbolValue
+ 1)
296 return ERROR(GENERIC
);
298 return (out
- ostart
);
301 size_t FSE_writeNCount(void *buffer
, size_t bufferSize
, const short *normalizedCounter
, unsigned maxSymbolValue
, unsigned tableLog
)
303 if (tableLog
> FSE_MAX_TABLELOG
)
304 return ERROR(tableLog_tooLarge
); /* Unsupported */
305 if (tableLog
< FSE_MIN_TABLELOG
)
306 return ERROR(GENERIC
); /* Unsupported */
308 if (bufferSize
< FSE_NCountWriteBound(maxSymbolValue
, tableLog
))
309 return FSE_writeNCount_generic(buffer
, bufferSize
, normalizedCounter
, maxSymbolValue
, tableLog
, 0);
311 return FSE_writeNCount_generic(buffer
, bufferSize
, normalizedCounter
, maxSymbolValue
, tableLog
, 1);
314 /*-**************************************************************
316 ****************************************************************/
318 This function counts byte values within `src`, and store the histogram into table `count`.
319 It doesn't use any additional memory.
320 But this function is unsafe : it doesn't check that all values within `src` can fit into `count`.
321 For this reason, prefer using a table `count` with 256 elements.
322 @return : count of most numerous element
324 size_t FSE_count_simple(unsigned *count
, unsigned *maxSymbolValuePtr
, const void *src
, size_t srcSize
)
326 const BYTE
*ip
= (const BYTE
*)src
;
327 const BYTE
*const end
= ip
+ srcSize
;
328 unsigned maxSymbolValue
= *maxSymbolValuePtr
;
331 memset(count
, 0, (maxSymbolValue
+ 1) * sizeof(*count
));
333 *maxSymbolValuePtr
= 0;
340 while (!count
[maxSymbolValue
])
342 *maxSymbolValuePtr
= maxSymbolValue
;
346 for (s
= 0; s
<= maxSymbolValue
; s
++)
354 /* FSE_count_parallel_wksp() :
355 * Same as FSE_count_parallel(), but using an externally provided scratch buffer.
356 * `workSpace` size must be a minimum of `1024 * sizeof(unsigned)`` */
357 static size_t FSE_count_parallel_wksp(unsigned *count
, unsigned *maxSymbolValuePtr
, const void *source
, size_t sourceSize
, unsigned checkMax
,
358 unsigned *const workSpace
)
360 const BYTE
*ip
= (const BYTE
*)source
;
361 const BYTE
*const iend
= ip
+ sourceSize
;
362 unsigned maxSymbolValue
= *maxSymbolValuePtr
;
364 U32
*const Counting1
= workSpace
;
365 U32
*const Counting2
= Counting1
+ 256;
366 U32
*const Counting3
= Counting2
+ 256;
367 U32
*const Counting4
= Counting3
+ 256;
369 memset(Counting1
, 0, 4 * 256 * sizeof(unsigned));
373 memset(count
, 0, maxSymbolValue
+ 1);
374 *maxSymbolValuePtr
= 0;
378 maxSymbolValue
= 255; /* 0 == default */
380 /* by stripes of 16 bytes */
382 U32 cached
= ZSTD_read32(ip
);
384 while (ip
< iend
- 15) {
386 cached
= ZSTD_read32(ip
);
388 Counting1
[(BYTE
)c
]++;
389 Counting2
[(BYTE
)(c
>> 8)]++;
390 Counting3
[(BYTE
)(c
>> 16)]++;
391 Counting4
[c
>> 24]++;
393 cached
= ZSTD_read32(ip
);
395 Counting1
[(BYTE
)c
]++;
396 Counting2
[(BYTE
)(c
>> 8)]++;
397 Counting3
[(BYTE
)(c
>> 16)]++;
398 Counting4
[c
>> 24]++;
400 cached
= ZSTD_read32(ip
);
402 Counting1
[(BYTE
)c
]++;
403 Counting2
[(BYTE
)(c
>> 8)]++;
404 Counting3
[(BYTE
)(c
>> 16)]++;
405 Counting4
[c
>> 24]++;
407 cached
= ZSTD_read32(ip
);
409 Counting1
[(BYTE
)c
]++;
410 Counting2
[(BYTE
)(c
>> 8)]++;
411 Counting3
[(BYTE
)(c
>> 16)]++;
412 Counting4
[c
>> 24]++;
417 /* finish last symbols */
421 if (checkMax
) { /* verify stats will fit into destination table */
423 for (s
= 255; s
> maxSymbolValue
; s
--) {
424 Counting1
[s
] += Counting2
[s
] + Counting3
[s
] + Counting4
[s
];
426 return ERROR(maxSymbolValue_tooSmall
);
432 for (s
= 0; s
<= maxSymbolValue
; s
++) {
433 count
[s
] = Counting1
[s
] + Counting2
[s
] + Counting3
[s
] + Counting4
[s
];
439 while (!count
[maxSymbolValue
])
441 *maxSymbolValuePtr
= maxSymbolValue
;
445 /* FSE_countFast_wksp() :
446 * Same as FSE_countFast(), but using an externally provided scratch buffer.
447 * `workSpace` size must be table of >= `1024` unsigned */
448 size_t FSE_countFast_wksp(unsigned *count
, unsigned *maxSymbolValuePtr
, const void *source
, size_t sourceSize
, unsigned *workSpace
)
450 if (sourceSize
< 1500)
451 return FSE_count_simple(count
, maxSymbolValuePtr
, source
, sourceSize
);
452 return FSE_count_parallel_wksp(count
, maxSymbolValuePtr
, source
, sourceSize
, 0, workSpace
);
455 /* FSE_count_wksp() :
456 * Same as FSE_count(), but using an externally provided scratch buffer.
457 * `workSpace` size must be table of >= `1024` unsigned */
458 size_t FSE_count_wksp(unsigned *count
, unsigned *maxSymbolValuePtr
, const void *source
, size_t sourceSize
, unsigned *workSpace
)
460 if (*maxSymbolValuePtr
< 255)
461 return FSE_count_parallel_wksp(count
, maxSymbolValuePtr
, source
, sourceSize
, 1, workSpace
);
462 *maxSymbolValuePtr
= 255;
463 return FSE_countFast_wksp(count
, maxSymbolValuePtr
, source
, sourceSize
, workSpace
);
466 /*-**************************************************************
467 * FSE Compression Code
468 ****************************************************************/
469 /*! FSE_sizeof_CTable() :
470 FSE_CTable is a variable size structure which contains :
472 `U16 maxSymbolValue;`
473 `U16 nextStateNumber[1 << tableLog];` // This size is variable
474 `FSE_symbolCompressionTransform symbolTT[maxSymbolValue+1];` // This size is variable
475 Allocation is manual (C standard does not support variable-size structures).
477 size_t FSE_sizeof_CTable(unsigned maxSymbolValue
, unsigned tableLog
)
479 if (tableLog
> FSE_MAX_TABLELOG
)
480 return ERROR(tableLog_tooLarge
);
481 return FSE_CTABLE_SIZE_U32(tableLog
, maxSymbolValue
) * sizeof(U32
);
484 /* provides the minimum logSize to safely represent a distribution */
485 static unsigned FSE_minTableLog(size_t srcSize
, unsigned maxSymbolValue
)
487 U32 minBitsSrc
= BIT_highbit32((U32
)(srcSize
- 1)) + 1;
488 U32 minBitsSymbols
= BIT_highbit32(maxSymbolValue
) + 2;
489 U32 minBits
= minBitsSrc
< minBitsSymbols
? minBitsSrc
: minBitsSymbols
;
493 unsigned FSE_optimalTableLog_internal(unsigned maxTableLog
, size_t srcSize
, unsigned maxSymbolValue
, unsigned minus
)
495 U32 maxBitsSrc
= BIT_highbit32((U32
)(srcSize
- 1)) - minus
;
496 U32 tableLog
= maxTableLog
;
497 U32 minBits
= FSE_minTableLog(srcSize
, maxSymbolValue
);
499 tableLog
= FSE_DEFAULT_TABLELOG
;
500 if (maxBitsSrc
< tableLog
)
501 tableLog
= maxBitsSrc
; /* Accuracy can be reduced */
502 if (minBits
> tableLog
)
503 tableLog
= minBits
; /* Need a minimum to safely represent all symbol values */
504 if (tableLog
< FSE_MIN_TABLELOG
)
505 tableLog
= FSE_MIN_TABLELOG
;
506 if (tableLog
> FSE_MAX_TABLELOG
)
507 tableLog
= FSE_MAX_TABLELOG
;
511 unsigned FSE_optimalTableLog(unsigned maxTableLog
, size_t srcSize
, unsigned maxSymbolValue
)
513 return FSE_optimalTableLog_internal(maxTableLog
, srcSize
, maxSymbolValue
, 2);
516 /* Secondary normalization method.
517 To be used when primary method fails. */
519 static size_t FSE_normalizeM2(short *norm
, U32 tableLog
, const unsigned *count
, size_t total
, U32 maxSymbolValue
)
521 short const NOT_YET_ASSIGNED
= -2;
527 U32
const lowThreshold
= (U32
)(total
>> tableLog
);
528 U32 lowOne
= (U32
)((total
* 3) >> (tableLog
+ 1));
530 for (s
= 0; s
<= maxSymbolValue
; s
++) {
535 if (count
[s
] <= lowThreshold
) {
541 if (count
[s
] <= lowOne
) {
548 norm
[s
] = NOT_YET_ASSIGNED
;
550 ToDistribute
= (1 << tableLog
) - distributed
;
552 if ((total
/ ToDistribute
) > lowOne
) {
553 /* risk of rounding to zero */
554 lowOne
= (U32
)((total
* 3) / (ToDistribute
* 2));
555 for (s
= 0; s
<= maxSymbolValue
; s
++) {
556 if ((norm
[s
] == NOT_YET_ASSIGNED
) && (count
[s
] <= lowOne
)) {
563 ToDistribute
= (1 << tableLog
) - distributed
;
566 if (distributed
== maxSymbolValue
+ 1) {
567 /* all values are pretty poor;
568 probably incompressible data (should have already been detected);
569 find max, then give all remaining points to max */
570 U32 maxV
= 0, maxC
= 0;
571 for (s
= 0; s
<= maxSymbolValue
; s
++)
573 maxV
= s
, maxC
= count
[s
];
574 norm
[maxV
] += (short)ToDistribute
;
579 /* all of the symbols were low enough for the lowOne or lowThreshold */
580 for (s
= 0; ToDistribute
> 0; s
= (s
+ 1) % (maxSymbolValue
+ 1))
582 ToDistribute
--, norm
[s
]++;
587 U64
const vStepLog
= 62 - tableLog
;
588 U64
const mid
= (1ULL << (vStepLog
- 1)) - 1;
589 U64
const rStep
= div_u64((((U64
)1 << vStepLog
) * ToDistribute
) + mid
, (U32
)total
); /* scale on remaining */
591 for (s
= 0; s
<= maxSymbolValue
; s
++) {
592 if (norm
[s
] == NOT_YET_ASSIGNED
) {
593 U64
const end
= tmpTotal
+ (count
[s
] * rStep
);
594 U32
const sStart
= (U32
)(tmpTotal
>> vStepLog
);
595 U32
const sEnd
= (U32
)(end
>> vStepLog
);
596 U32
const weight
= sEnd
- sStart
;
598 return ERROR(GENERIC
);
599 norm
[s
] = (short)weight
;
608 size_t FSE_normalizeCount(short *normalizedCounter
, unsigned tableLog
, const unsigned *count
, size_t total
, unsigned maxSymbolValue
)
612 tableLog
= FSE_DEFAULT_TABLELOG
;
613 if (tableLog
< FSE_MIN_TABLELOG
)
614 return ERROR(GENERIC
); /* Unsupported size */
615 if (tableLog
> FSE_MAX_TABLELOG
)
616 return ERROR(tableLog_tooLarge
); /* Unsupported size */
617 if (tableLog
< FSE_minTableLog(total
, maxSymbolValue
))
618 return ERROR(GENERIC
); /* Too small tableLog, compression potentially impossible */
621 U32
const rtbTable
[] = {0, 473195, 504333, 520860, 550000, 700000, 750000, 830000};
622 U64
const scale
= 62 - tableLog
;
623 U64
const step
= div_u64((U64
)1 << 62, (U32
)total
); /* <== here, one division ! */
624 U64
const vStep
= 1ULL << (scale
- 20);
625 int stillToDistribute
= 1 << tableLog
;
627 unsigned largest
= 0;
629 U32 lowThreshold
= (U32
)(total
>> tableLog
);
631 for (s
= 0; s
<= maxSymbolValue
; s
++) {
632 if (count
[s
] == total
)
633 return 0; /* rle special case */
635 normalizedCounter
[s
] = 0;
638 if (count
[s
] <= lowThreshold
) {
639 normalizedCounter
[s
] = -1;
642 short proba
= (short)((count
[s
] * step
) >> scale
);
644 U64 restToBeat
= vStep
* rtbTable
[proba
];
645 proba
+= (count
[s
] * step
) - ((U64
)proba
<< scale
) > restToBeat
;
647 if (proba
> largestP
)
648 largestP
= proba
, largest
= s
;
649 normalizedCounter
[s
] = proba
;
650 stillToDistribute
-= proba
;
653 if (-stillToDistribute
>= (normalizedCounter
[largest
] >> 1)) {
654 /* corner case, need another normalization method */
655 size_t const errorCode
= FSE_normalizeM2(normalizedCounter
, tableLog
, count
, total
, maxSymbolValue
);
656 if (FSE_isError(errorCode
))
659 normalizedCounter
[largest
] += (short)stillToDistribute
;
665 /* fake FSE_CTable, for raw (uncompressed) input */
666 size_t FSE_buildCTable_raw(FSE_CTable
*ct
, unsigned nbBits
)
668 const unsigned tableSize
= 1 << nbBits
;
669 const unsigned tableMask
= tableSize
- 1;
670 const unsigned maxSymbolValue
= tableMask
;
671 void *const ptr
= ct
;
672 U16
*const tableU16
= ((U16
*)ptr
) + 2;
673 void *const FSCT
= ((U32
*)ptr
) + 1 /* header */ + (tableSize
>> 1); /* assumption : tableLog >= 1 */
674 FSE_symbolCompressionTransform
*const symbolTT
= (FSE_symbolCompressionTransform
*)(FSCT
);
679 return ERROR(GENERIC
); /* min size */
682 tableU16
[-2] = (U16
)nbBits
;
683 tableU16
[-1] = (U16
)maxSymbolValue
;
686 for (s
= 0; s
< tableSize
; s
++)
687 tableU16
[s
] = (U16
)(tableSize
+ s
);
689 /* Build Symbol Transformation Table */
691 const U32 deltaNbBits
= (nbBits
<< 16) - (1 << nbBits
);
692 for (s
= 0; s
<= maxSymbolValue
; s
++) {
693 symbolTT
[s
].deltaNbBits
= deltaNbBits
;
694 symbolTT
[s
].deltaFindState
= s
- 1;
701 /* fake FSE_CTable, for rle input (always same symbol) */
702 size_t FSE_buildCTable_rle(FSE_CTable
*ct
, BYTE symbolValue
)
705 U16
*tableU16
= ((U16
*)ptr
) + 2;
706 void *FSCTptr
= (U32
*)ptr
+ 2;
707 FSE_symbolCompressionTransform
*symbolTT
= (FSE_symbolCompressionTransform
*)FSCTptr
;
710 tableU16
[-2] = (U16
)0;
711 tableU16
[-1] = (U16
)symbolValue
;
715 tableU16
[1] = 0; /* just in case */
717 /* Build Symbol Transformation Table */
718 symbolTT
[symbolValue
].deltaNbBits
= 0;
719 symbolTT
[symbolValue
].deltaFindState
= 0;
724 static size_t FSE_compress_usingCTable_generic(void *dst
, size_t dstSize
, const void *src
, size_t srcSize
, const FSE_CTable
*ct
, const unsigned fast
)
726 const BYTE
*const istart
= (const BYTE
*)src
;
727 const BYTE
*const iend
= istart
+ srcSize
;
728 const BYTE
*ip
= iend
;
731 FSE_CState_t CState1
, CState2
;
737 size_t const initError
= BIT_initCStream(&bitC
, dst
, dstSize
);
738 if (FSE_isError(initError
))
739 return 0; /* not enough space available to write a bitstream */
742 #define FSE_FLUSHBITS(s) (fast ? BIT_flushBitsFast(s) : BIT_flushBits(s))
745 FSE_initCState2(&CState1
, ct
, *--ip
);
746 FSE_initCState2(&CState2
, ct
, *--ip
);
747 FSE_encodeSymbol(&bitC
, &CState1
, *--ip
);
748 FSE_FLUSHBITS(&bitC
);
750 FSE_initCState2(&CState2
, ct
, *--ip
);
751 FSE_initCState2(&CState1
, ct
, *--ip
);
756 if ((sizeof(bitC
.bitContainer
) * 8 > FSE_MAX_TABLELOG
* 4 + 7) && (srcSize
& 2)) { /* test bit 2 */
757 FSE_encodeSymbol(&bitC
, &CState2
, *--ip
);
758 FSE_encodeSymbol(&bitC
, &CState1
, *--ip
);
759 FSE_FLUSHBITS(&bitC
);
762 /* 2 or 4 encoding per loop */
763 while (ip
> istart
) {
765 FSE_encodeSymbol(&bitC
, &CState2
, *--ip
);
767 if (sizeof(bitC
.bitContainer
) * 8 < FSE_MAX_TABLELOG
* 2 + 7) /* this test must be static */
768 FSE_FLUSHBITS(&bitC
);
770 FSE_encodeSymbol(&bitC
, &CState1
, *--ip
);
772 if (sizeof(bitC
.bitContainer
) * 8 > FSE_MAX_TABLELOG
* 4 + 7) { /* this test must be static */
773 FSE_encodeSymbol(&bitC
, &CState2
, *--ip
);
774 FSE_encodeSymbol(&bitC
, &CState1
, *--ip
);
777 FSE_FLUSHBITS(&bitC
);
780 FSE_flushCState(&bitC
, &CState2
);
781 FSE_flushCState(&bitC
, &CState1
);
782 return BIT_closeCStream(&bitC
);
785 size_t FSE_compress_usingCTable(void *dst
, size_t dstSize
, const void *src
, size_t srcSize
, const FSE_CTable
*ct
)
787 unsigned const fast
= (dstSize
>= FSE_BLOCKBOUND(srcSize
));
790 return FSE_compress_usingCTable_generic(dst
, dstSize
, src
, srcSize
, ct
, 1);
792 return FSE_compress_usingCTable_generic(dst
, dstSize
, src
, srcSize
, ct
, 0);
795 size_t FSE_compressBound(size_t size
) { return FSE_COMPRESSBOUND(size
); }