extzstd 0.2 → 0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/HISTORY.ja.md +13 -0
- data/README.md +17 -14
- data/contrib/zstd/{NEWS → CHANGELOG} +115 -2
- data/contrib/zstd/CODE_OF_CONDUCT.md +5 -0
- data/contrib/zstd/Makefile +99 -53
- data/contrib/zstd/README.md +59 -39
- data/contrib/zstd/TESTING.md +1 -1
- data/contrib/zstd/appveyor.yml +17 -6
- data/contrib/zstd/lib/BUCK +29 -2
- data/contrib/zstd/lib/Makefile +118 -21
- data/contrib/zstd/lib/README.md +84 -44
- data/contrib/zstd/lib/common/bitstream.h +17 -33
- data/contrib/zstd/lib/common/compiler.h +62 -8
- data/contrib/zstd/lib/common/cpu.h +215 -0
- data/contrib/zstd/lib/common/debug.c +44 -0
- data/contrib/zstd/lib/common/debug.h +134 -0
- data/contrib/zstd/lib/common/entropy_common.c +16 -1
- data/contrib/zstd/lib/common/error_private.c +7 -0
- data/contrib/zstd/lib/common/fse.h +48 -44
- data/contrib/zstd/lib/common/fse_decompress.c +3 -3
- data/contrib/zstd/lib/common/huf.h +169 -113
- data/contrib/zstd/lib/common/mem.h +20 -2
- data/contrib/zstd/lib/common/pool.c +135 -49
- data/contrib/zstd/lib/common/pool.h +40 -21
- data/contrib/zstd/lib/common/threading.c +2 -2
- data/contrib/zstd/lib/common/threading.h +12 -12
- data/contrib/zstd/lib/common/xxhash.c +3 -2
- data/contrib/zstd/lib/common/zstd_common.c +3 -6
- data/contrib/zstd/lib/common/zstd_errors.h +17 -7
- data/contrib/zstd/lib/common/zstd_internal.h +76 -48
- data/contrib/zstd/lib/compress/fse_compress.c +89 -209
- data/contrib/zstd/lib/compress/hist.c +203 -0
- data/contrib/zstd/lib/compress/hist.h +95 -0
- data/contrib/zstd/lib/compress/huf_compress.c +188 -80
- data/contrib/zstd/lib/compress/zstd_compress.c +2500 -1203
- data/contrib/zstd/lib/compress/zstd_compress_internal.h +463 -62
- data/contrib/zstd/lib/compress/zstd_double_fast.c +321 -131
- data/contrib/zstd/lib/compress/zstd_double_fast.h +13 -4
- data/contrib/zstd/lib/compress/zstd_fast.c +335 -108
- data/contrib/zstd/lib/compress/zstd_fast.h +12 -6
- data/contrib/zstd/lib/compress/zstd_lazy.c +654 -313
- data/contrib/zstd/lib/compress/zstd_lazy.h +44 -16
- data/contrib/zstd/lib/compress/zstd_ldm.c +310 -420
- data/contrib/zstd/lib/compress/zstd_ldm.h +63 -26
- data/contrib/zstd/lib/compress/zstd_opt.c +773 -325
- data/contrib/zstd/lib/compress/zstd_opt.h +31 -5
- data/contrib/zstd/lib/compress/zstdmt_compress.c +1468 -518
- data/contrib/zstd/lib/compress/zstdmt_compress.h +96 -45
- data/contrib/zstd/lib/decompress/huf_decompress.c +518 -282
- data/contrib/zstd/lib/decompress/zstd_ddict.c +240 -0
- data/contrib/zstd/lib/decompress/zstd_ddict.h +44 -0
- data/contrib/zstd/lib/decompress/zstd_decompress.c +613 -1513
- data/contrib/zstd/lib/decompress/zstd_decompress_block.c +1311 -0
- data/contrib/zstd/lib/decompress/zstd_decompress_block.h +59 -0
- data/contrib/zstd/lib/decompress/zstd_decompress_internal.h +175 -0
- data/contrib/zstd/lib/dictBuilder/cover.c +194 -113
- data/contrib/zstd/lib/dictBuilder/cover.h +112 -0
- data/contrib/zstd/lib/dictBuilder/divsufsort.c +3 -3
- data/contrib/zstd/lib/dictBuilder/fastcover.c +740 -0
- data/contrib/zstd/lib/dictBuilder/zdict.c +142 -106
- data/contrib/zstd/lib/dictBuilder/zdict.h +115 -49
- data/contrib/zstd/lib/legacy/zstd_legacy.h +44 -12
- data/contrib/zstd/lib/legacy/zstd_v01.c +41 -10
- data/contrib/zstd/lib/legacy/zstd_v01.h +12 -7
- data/contrib/zstd/lib/legacy/zstd_v02.c +37 -12
- data/contrib/zstd/lib/legacy/zstd_v02.h +12 -7
- data/contrib/zstd/lib/legacy/zstd_v03.c +38 -12
- data/contrib/zstd/lib/legacy/zstd_v03.h +12 -7
- data/contrib/zstd/lib/legacy/zstd_v04.c +55 -174
- data/contrib/zstd/lib/legacy/zstd_v04.h +12 -7
- data/contrib/zstd/lib/legacy/zstd_v05.c +59 -31
- data/contrib/zstd/lib/legacy/zstd_v05.h +12 -7
- data/contrib/zstd/lib/legacy/zstd_v06.c +48 -20
- data/contrib/zstd/lib/legacy/zstd_v06.h +10 -5
- data/contrib/zstd/lib/legacy/zstd_v07.c +62 -29
- data/contrib/zstd/lib/legacy/zstd_v07.h +10 -5
- data/contrib/zstd/lib/zstd.h +1346 -832
- data/ext/extzstd.c +27 -19
- data/ext/extzstd_stream.c +20 -4
- data/ext/zstd_compress.c +1 -0
- data/ext/zstd_decompress.c +4 -0
- data/ext/zstd_dictbuilder.c +4 -0
- data/ext/zstd_dictbuilder_fastcover.c +5 -0
- data/lib/extzstd.rb +52 -220
- data/lib/extzstd/version.rb +1 -1
- metadata +21 -7
- data/contrib/zstd/circle.yml +0 -63
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
/* ******************************************************************
|
|
2
|
+
hist : Histogram functions
|
|
3
|
+
part of Finite State Entropy project
|
|
4
|
+
Copyright (C) 2013-present, 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
|
+
- FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy
|
|
33
|
+
- Public forum : https://groups.google.com/forum/#!forum/lz4c
|
|
34
|
+
****************************************************************** */
|
|
35
|
+
|
|
36
|
+
/* --- dependencies --- */
|
|
37
|
+
#include "mem.h" /* U32, BYTE, etc. */
|
|
38
|
+
#include "debug.h" /* assert, DEBUGLOG */
|
|
39
|
+
#include "error_private.h" /* ERROR */
|
|
40
|
+
#include "hist.h"
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
/* --- Error management --- */
|
|
44
|
+
unsigned HIST_isError(size_t code) { return ERR_isError(code); }
|
|
45
|
+
|
|
46
|
+
/*-**************************************************************
|
|
47
|
+
* Histogram functions
|
|
48
|
+
****************************************************************/
|
|
49
|
+
unsigned HIST_count_simple(unsigned* count, unsigned* maxSymbolValuePtr,
|
|
50
|
+
const void* src, size_t srcSize)
|
|
51
|
+
{
|
|
52
|
+
const BYTE* ip = (const BYTE*)src;
|
|
53
|
+
const BYTE* const end = ip + srcSize;
|
|
54
|
+
unsigned maxSymbolValue = *maxSymbolValuePtr;
|
|
55
|
+
unsigned largestCount=0;
|
|
56
|
+
|
|
57
|
+
memset(count, 0, (maxSymbolValue+1) * sizeof(*count));
|
|
58
|
+
if (srcSize==0) { *maxSymbolValuePtr = 0; return 0; }
|
|
59
|
+
|
|
60
|
+
while (ip<end) {
|
|
61
|
+
assert(*ip <= maxSymbolValue);
|
|
62
|
+
count[*ip++]++;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
while (!count[maxSymbolValue]) maxSymbolValue--;
|
|
66
|
+
*maxSymbolValuePtr = maxSymbolValue;
|
|
67
|
+
|
|
68
|
+
{ U32 s;
|
|
69
|
+
for (s=0; s<=maxSymbolValue; s++)
|
|
70
|
+
if (count[s] > largestCount) largestCount = count[s];
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return largestCount;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
typedef enum { trustInput, checkMaxSymbolValue } HIST_checkInput_e;
|
|
77
|
+
|
|
78
|
+
/* HIST_count_parallel_wksp() :
|
|
79
|
+
* store histogram into 4 intermediate tables, recombined at the end.
|
|
80
|
+
* this design makes better use of OoO cpus,
|
|
81
|
+
* and is noticeably faster when some values are heavily repeated.
|
|
82
|
+
* But it needs some additional workspace for intermediate tables.
|
|
83
|
+
* `workSpace` size must be a table of size >= HIST_WKSP_SIZE_U32.
|
|
84
|
+
* @return : largest histogram frequency,
|
|
85
|
+
* or an error code (notably when histogram would be larger than *maxSymbolValuePtr). */
|
|
86
|
+
static size_t HIST_count_parallel_wksp(
|
|
87
|
+
unsigned* count, unsigned* maxSymbolValuePtr,
|
|
88
|
+
const void* source, size_t sourceSize,
|
|
89
|
+
HIST_checkInput_e check,
|
|
90
|
+
U32* const workSpace)
|
|
91
|
+
{
|
|
92
|
+
const BYTE* ip = (const BYTE*)source;
|
|
93
|
+
const BYTE* const iend = ip+sourceSize;
|
|
94
|
+
unsigned maxSymbolValue = *maxSymbolValuePtr;
|
|
95
|
+
unsigned max=0;
|
|
96
|
+
U32* const Counting1 = workSpace;
|
|
97
|
+
U32* const Counting2 = Counting1 + 256;
|
|
98
|
+
U32* const Counting3 = Counting2 + 256;
|
|
99
|
+
U32* const Counting4 = Counting3 + 256;
|
|
100
|
+
|
|
101
|
+
memset(workSpace, 0, 4*256*sizeof(unsigned));
|
|
102
|
+
|
|
103
|
+
/* safety checks */
|
|
104
|
+
if (!sourceSize) {
|
|
105
|
+
memset(count, 0, maxSymbolValue + 1);
|
|
106
|
+
*maxSymbolValuePtr = 0;
|
|
107
|
+
return 0;
|
|
108
|
+
}
|
|
109
|
+
if (!maxSymbolValue) maxSymbolValue = 255; /* 0 == default */
|
|
110
|
+
|
|
111
|
+
/* by stripes of 16 bytes */
|
|
112
|
+
{ U32 cached = MEM_read32(ip); ip += 4;
|
|
113
|
+
while (ip < iend-15) {
|
|
114
|
+
U32 c = cached; cached = MEM_read32(ip); ip += 4;
|
|
115
|
+
Counting1[(BYTE) c ]++;
|
|
116
|
+
Counting2[(BYTE)(c>>8) ]++;
|
|
117
|
+
Counting3[(BYTE)(c>>16)]++;
|
|
118
|
+
Counting4[ c>>24 ]++;
|
|
119
|
+
c = cached; cached = MEM_read32(ip); ip += 4;
|
|
120
|
+
Counting1[(BYTE) c ]++;
|
|
121
|
+
Counting2[(BYTE)(c>>8) ]++;
|
|
122
|
+
Counting3[(BYTE)(c>>16)]++;
|
|
123
|
+
Counting4[ c>>24 ]++;
|
|
124
|
+
c = cached; cached = MEM_read32(ip); ip += 4;
|
|
125
|
+
Counting1[(BYTE) c ]++;
|
|
126
|
+
Counting2[(BYTE)(c>>8) ]++;
|
|
127
|
+
Counting3[(BYTE)(c>>16)]++;
|
|
128
|
+
Counting4[ c>>24 ]++;
|
|
129
|
+
c = cached; cached = MEM_read32(ip); ip += 4;
|
|
130
|
+
Counting1[(BYTE) c ]++;
|
|
131
|
+
Counting2[(BYTE)(c>>8) ]++;
|
|
132
|
+
Counting3[(BYTE)(c>>16)]++;
|
|
133
|
+
Counting4[ c>>24 ]++;
|
|
134
|
+
}
|
|
135
|
+
ip-=4;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/* finish last symbols */
|
|
139
|
+
while (ip<iend) Counting1[*ip++]++;
|
|
140
|
+
|
|
141
|
+
if (check) { /* verify stats will fit into destination table */
|
|
142
|
+
U32 s; for (s=255; s>maxSymbolValue; s--) {
|
|
143
|
+
Counting1[s] += Counting2[s] + Counting3[s] + Counting4[s];
|
|
144
|
+
if (Counting1[s]) return ERROR(maxSymbolValue_tooSmall);
|
|
145
|
+
} }
|
|
146
|
+
|
|
147
|
+
{ U32 s;
|
|
148
|
+
if (maxSymbolValue > 255) maxSymbolValue = 255;
|
|
149
|
+
for (s=0; s<=maxSymbolValue; s++) {
|
|
150
|
+
count[s] = Counting1[s] + Counting2[s] + Counting3[s] + Counting4[s];
|
|
151
|
+
if (count[s] > max) max = count[s];
|
|
152
|
+
} }
|
|
153
|
+
|
|
154
|
+
while (!count[maxSymbolValue]) maxSymbolValue--;
|
|
155
|
+
*maxSymbolValuePtr = maxSymbolValue;
|
|
156
|
+
return (size_t)max;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/* HIST_countFast_wksp() :
|
|
160
|
+
* Same as HIST_countFast(), but using an externally provided scratch buffer.
|
|
161
|
+
* `workSpace` is a writable buffer which must be 4-bytes aligned,
|
|
162
|
+
* `workSpaceSize` must be >= HIST_WKSP_SIZE
|
|
163
|
+
*/
|
|
164
|
+
size_t HIST_countFast_wksp(unsigned* count, unsigned* maxSymbolValuePtr,
|
|
165
|
+
const void* source, size_t sourceSize,
|
|
166
|
+
void* workSpace, size_t workSpaceSize)
|
|
167
|
+
{
|
|
168
|
+
if (sourceSize < 1500) /* heuristic threshold */
|
|
169
|
+
return HIST_count_simple(count, maxSymbolValuePtr, source, sourceSize);
|
|
170
|
+
if ((size_t)workSpace & 3) return ERROR(GENERIC); /* must be aligned on 4-bytes boundaries */
|
|
171
|
+
if (workSpaceSize < HIST_WKSP_SIZE) return ERROR(workSpace_tooSmall);
|
|
172
|
+
return HIST_count_parallel_wksp(count, maxSymbolValuePtr, source, sourceSize, trustInput, (U32*)workSpace);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/* fast variant (unsafe : won't check if src contains values beyond count[] limit) */
|
|
176
|
+
size_t HIST_countFast(unsigned* count, unsigned* maxSymbolValuePtr,
|
|
177
|
+
const void* source, size_t sourceSize)
|
|
178
|
+
{
|
|
179
|
+
unsigned tmpCounters[HIST_WKSP_SIZE_U32];
|
|
180
|
+
return HIST_countFast_wksp(count, maxSymbolValuePtr, source, sourceSize, tmpCounters, sizeof(tmpCounters));
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/* HIST_count_wksp() :
|
|
184
|
+
* Same as HIST_count(), but using an externally provided scratch buffer.
|
|
185
|
+
* `workSpace` size must be table of >= HIST_WKSP_SIZE_U32 unsigned */
|
|
186
|
+
size_t HIST_count_wksp(unsigned* count, unsigned* maxSymbolValuePtr,
|
|
187
|
+
const void* source, size_t sourceSize,
|
|
188
|
+
void* workSpace, size_t workSpaceSize)
|
|
189
|
+
{
|
|
190
|
+
if ((size_t)workSpace & 3) return ERROR(GENERIC); /* must be aligned on 4-bytes boundaries */
|
|
191
|
+
if (workSpaceSize < HIST_WKSP_SIZE) return ERROR(workSpace_tooSmall);
|
|
192
|
+
if (*maxSymbolValuePtr < 255)
|
|
193
|
+
return HIST_count_parallel_wksp(count, maxSymbolValuePtr, source, sourceSize, checkMaxSymbolValue, (U32*)workSpace);
|
|
194
|
+
*maxSymbolValuePtr = 255;
|
|
195
|
+
return HIST_countFast_wksp(count, maxSymbolValuePtr, source, sourceSize, workSpace, workSpaceSize);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
size_t HIST_count(unsigned* count, unsigned* maxSymbolValuePtr,
|
|
199
|
+
const void* src, size_t srcSize)
|
|
200
|
+
{
|
|
201
|
+
unsigned tmpCounters[HIST_WKSP_SIZE_U32];
|
|
202
|
+
return HIST_count_wksp(count, maxSymbolValuePtr, src, srcSize, tmpCounters, sizeof(tmpCounters));
|
|
203
|
+
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/* ******************************************************************
|
|
2
|
+
hist : Histogram functions
|
|
3
|
+
part of Finite State Entropy project
|
|
4
|
+
Copyright (C) 2013-present, 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
|
+
- FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy
|
|
33
|
+
- Public forum : https://groups.google.com/forum/#!forum/lz4c
|
|
34
|
+
****************************************************************** */
|
|
35
|
+
|
|
36
|
+
/* --- dependencies --- */
|
|
37
|
+
#include <stddef.h> /* size_t */
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
/* --- simple histogram functions --- */
|
|
41
|
+
|
|
42
|
+
/*! HIST_count():
|
|
43
|
+
* Provides the precise count of each byte within a table 'count'.
|
|
44
|
+
* 'count' is a table of unsigned int, of minimum size (*maxSymbolValuePtr+1).
|
|
45
|
+
* Updates *maxSymbolValuePtr with actual largest symbol value detected.
|
|
46
|
+
* @return : count of the most frequent symbol (which isn't identified).
|
|
47
|
+
* or an error code, which can be tested using HIST_isError().
|
|
48
|
+
* note : if return == srcSize, there is only one symbol.
|
|
49
|
+
*/
|
|
50
|
+
size_t HIST_count(unsigned* count, unsigned* maxSymbolValuePtr,
|
|
51
|
+
const void* src, size_t srcSize);
|
|
52
|
+
|
|
53
|
+
unsigned HIST_isError(size_t code); /**< tells if a return value is an error code */
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
/* --- advanced histogram functions --- */
|
|
57
|
+
|
|
58
|
+
#define HIST_WKSP_SIZE_U32 1024
|
|
59
|
+
#define HIST_WKSP_SIZE (HIST_WKSP_SIZE_U32 * sizeof(unsigned))
|
|
60
|
+
/** HIST_count_wksp() :
|
|
61
|
+
* Same as HIST_count(), but using an externally provided scratch buffer.
|
|
62
|
+
* Benefit is this function will use very little stack space.
|
|
63
|
+
* `workSpace` is a writable buffer which must be 4-bytes aligned,
|
|
64
|
+
* `workSpaceSize` must be >= HIST_WKSP_SIZE
|
|
65
|
+
*/
|
|
66
|
+
size_t HIST_count_wksp(unsigned* count, unsigned* maxSymbolValuePtr,
|
|
67
|
+
const void* src, size_t srcSize,
|
|
68
|
+
void* workSpace, size_t workSpaceSize);
|
|
69
|
+
|
|
70
|
+
/** HIST_countFast() :
|
|
71
|
+
* same as HIST_count(), but blindly trusts that all byte values within src are <= *maxSymbolValuePtr.
|
|
72
|
+
* This function is unsafe, and will segfault if any value within `src` is `> *maxSymbolValuePtr`
|
|
73
|
+
*/
|
|
74
|
+
size_t HIST_countFast(unsigned* count, unsigned* maxSymbolValuePtr,
|
|
75
|
+
const void* src, size_t srcSize);
|
|
76
|
+
|
|
77
|
+
/** HIST_countFast_wksp() :
|
|
78
|
+
* Same as HIST_countFast(), but using an externally provided scratch buffer.
|
|
79
|
+
* `workSpace` is a writable buffer which must be 4-bytes aligned,
|
|
80
|
+
* `workSpaceSize` must be >= HIST_WKSP_SIZE
|
|
81
|
+
*/
|
|
82
|
+
size_t HIST_countFast_wksp(unsigned* count, unsigned* maxSymbolValuePtr,
|
|
83
|
+
const void* src, size_t srcSize,
|
|
84
|
+
void* workSpace, size_t workSpaceSize);
|
|
85
|
+
|
|
86
|
+
/*! HIST_count_simple() :
|
|
87
|
+
* Same as HIST_countFast(), this function is unsafe,
|
|
88
|
+
* and will segfault if any value within `src` is `> *maxSymbolValuePtr`.
|
|
89
|
+
* It is also a bit slower for large inputs.
|
|
90
|
+
* However, it does not need any additional memory (not even on stack).
|
|
91
|
+
* @return : count of the most frequent symbol.
|
|
92
|
+
* Note this function doesn't produce any error (i.e. it must succeed).
|
|
93
|
+
*/
|
|
94
|
+
unsigned HIST_count_simple(unsigned* count, unsigned* maxSymbolValuePtr,
|
|
95
|
+
const void* src, size_t srcSize);
|
|
@@ -45,7 +45,9 @@
|
|
|
45
45
|
****************************************************************/
|
|
46
46
|
#include <string.h> /* memcpy, memset */
|
|
47
47
|
#include <stdio.h> /* printf (debug) */
|
|
48
|
+
#include "compiler.h"
|
|
48
49
|
#include "bitstream.h"
|
|
50
|
+
#include "hist.h"
|
|
49
51
|
#define FSE_STATIC_LINKING_ONLY /* FSE_optimalTableLog_internal */
|
|
50
52
|
#include "fse.h" /* header compression */
|
|
51
53
|
#define HUF_STATIC_LINKING_ONLY
|
|
@@ -57,7 +59,7 @@
|
|
|
57
59
|
* Error Management
|
|
58
60
|
****************************************************************/
|
|
59
61
|
#define HUF_isError ERR_isError
|
|
60
|
-
#define HUF_STATIC_ASSERT(c)
|
|
62
|
+
#define HUF_STATIC_ASSERT(c) DEBUG_STATIC_ASSERT(c) /* use only *after* variable declarations */
|
|
61
63
|
#define CHECK_V_F(e, f) size_t const e = f; if (ERR_isError(e)) return e
|
|
62
64
|
#define CHECK_F(f) { CHECK_V_F(_var_err__, f); }
|
|
63
65
|
|
|
@@ -80,28 +82,28 @@ unsigned HUF_optimalTableLog(unsigned maxTableLog, size_t srcSize, unsigned maxS
|
|
|
80
82
|
* Note : all elements within weightTable are supposed to be <= HUF_TABLELOG_MAX.
|
|
81
83
|
*/
|
|
82
84
|
#define MAX_FSE_TABLELOG_FOR_HUFF_HEADER 6
|
|
83
|
-
size_t HUF_compressWeights (void* dst, size_t dstSize, const void* weightTable, size_t wtSize)
|
|
85
|
+
static size_t HUF_compressWeights (void* dst, size_t dstSize, const void* weightTable, size_t wtSize)
|
|
84
86
|
{
|
|
85
87
|
BYTE* const ostart = (BYTE*) dst;
|
|
86
88
|
BYTE* op = ostart;
|
|
87
89
|
BYTE* const oend = ostart + dstSize;
|
|
88
90
|
|
|
89
|
-
|
|
91
|
+
unsigned maxSymbolValue = HUF_TABLELOG_MAX;
|
|
90
92
|
U32 tableLog = MAX_FSE_TABLELOG_FOR_HUFF_HEADER;
|
|
91
93
|
|
|
92
94
|
FSE_CTable CTable[FSE_CTABLE_SIZE_U32(MAX_FSE_TABLELOG_FOR_HUFF_HEADER, HUF_TABLELOG_MAX)];
|
|
93
95
|
BYTE scratchBuffer[1<<MAX_FSE_TABLELOG_FOR_HUFF_HEADER];
|
|
94
96
|
|
|
95
|
-
|
|
97
|
+
unsigned count[HUF_TABLELOG_MAX+1];
|
|
96
98
|
S16 norm[HUF_TABLELOG_MAX+1];
|
|
97
99
|
|
|
98
100
|
/* init conditions */
|
|
99
101
|
if (wtSize <= 1) return 0; /* Not compressible */
|
|
100
102
|
|
|
101
103
|
/* Scan input and build symbol stats */
|
|
102
|
-
{
|
|
104
|
+
{ unsigned const maxCount = HIST_count_simple(count, &maxSymbolValue, weightTable, wtSize); /* never fails */
|
|
103
105
|
if (maxCount == wtSize) return 1; /* only a single symbol in src : rle */
|
|
104
|
-
if (maxCount == 1) return 0;
|
|
106
|
+
if (maxCount == 1) return 0; /* each symbol present maximum once => not compressible */
|
|
105
107
|
}
|
|
106
108
|
|
|
107
109
|
tableLog = FSE_optimalTableLog(tableLog, wtSize, maxSymbolValue);
|
|
@@ -132,7 +134,7 @@ struct HUF_CElt_s {
|
|
|
132
134
|
`CTable` : Huffman tree to save, using huf representation.
|
|
133
135
|
@return : size of saved CTable */
|
|
134
136
|
size_t HUF_writeCTable (void* dst, size_t maxDstSize,
|
|
135
|
-
const HUF_CElt* CTable,
|
|
137
|
+
const HUF_CElt* CTable, unsigned maxSymbolValue, unsigned huffLog)
|
|
136
138
|
{
|
|
137
139
|
BYTE bitsToWeight[HUF_TABLELOG_MAX + 1]; /* precomputed conversion table */
|
|
138
140
|
BYTE huffWeight[HUF_SYMBOLVALUE_MAX];
|
|
@@ -167,7 +169,7 @@ size_t HUF_writeCTable (void* dst, size_t maxDstSize,
|
|
|
167
169
|
}
|
|
168
170
|
|
|
169
171
|
|
|
170
|
-
size_t HUF_readCTable (HUF_CElt* CTable,
|
|
172
|
+
size_t HUF_readCTable (HUF_CElt* CTable, unsigned* maxSymbolValuePtr, const void* src, size_t srcSize)
|
|
171
173
|
{
|
|
172
174
|
BYTE huffWeight[HUF_SYMBOLVALUE_MAX + 1]; /* init not required, even though some static analyzer may complain */
|
|
173
175
|
U32 rankVal[HUF_TABLELOG_ABSOLUTEMAX + 1]; /* large enough for values from 0 to 16 */
|
|
@@ -215,6 +217,13 @@ size_t HUF_readCTable (HUF_CElt* CTable, U32* maxSymbolValuePtr, const void* src
|
|
|
215
217
|
return readSize;
|
|
216
218
|
}
|
|
217
219
|
|
|
220
|
+
U32 HUF_getNbBits(const void* symbolTable, U32 symbolValue)
|
|
221
|
+
{
|
|
222
|
+
const HUF_CElt* table = (const HUF_CElt*)symbolTable;
|
|
223
|
+
assert(symbolValue <= HUF_SYMBOLVALUE_MAX);
|
|
224
|
+
return table[symbolValue].nbBits;
|
|
225
|
+
}
|
|
226
|
+
|
|
218
227
|
|
|
219
228
|
typedef struct nodeElt_s {
|
|
220
229
|
U32 count;
|
|
@@ -306,7 +315,7 @@ typedef struct {
|
|
|
306
315
|
U32 current;
|
|
307
316
|
} rankPos;
|
|
308
317
|
|
|
309
|
-
static void HUF_sort(nodeElt* huffNode, const
|
|
318
|
+
static void HUF_sort(nodeElt* huffNode, const unsigned* count, U32 maxSymbolValue)
|
|
310
319
|
{
|
|
311
320
|
rankPos rank[32];
|
|
312
321
|
U32 n;
|
|
@@ -322,7 +331,10 @@ static void HUF_sort(nodeElt* huffNode, const U32* count, U32 maxSymbolValue)
|
|
|
322
331
|
U32 const c = count[n];
|
|
323
332
|
U32 const r = BIT_highbit32(c+1) + 1;
|
|
324
333
|
U32 pos = rank[r].current++;
|
|
325
|
-
while ((pos > rank[r].base) && (c > huffNode[pos-1].count))
|
|
334
|
+
while ((pos > rank[r].base) && (c > huffNode[pos-1].count)) {
|
|
335
|
+
huffNode[pos] = huffNode[pos-1];
|
|
336
|
+
pos--;
|
|
337
|
+
}
|
|
326
338
|
huffNode[pos].count = c;
|
|
327
339
|
huffNode[pos].byte = (BYTE)n;
|
|
328
340
|
}
|
|
@@ -331,11 +343,11 @@ static void HUF_sort(nodeElt* huffNode, const U32* count, U32 maxSymbolValue)
|
|
|
331
343
|
|
|
332
344
|
/** HUF_buildCTable_wksp() :
|
|
333
345
|
* Same as HUF_buildCTable(), but using externally allocated scratch buffer.
|
|
334
|
-
* `workSpace` must be aligned on 4-bytes boundaries, and be at least as large as a table of
|
|
346
|
+
* `workSpace` must be aligned on 4-bytes boundaries, and be at least as large as a table of HUF_CTABLE_WORKSPACE_SIZE_U32 unsigned.
|
|
335
347
|
*/
|
|
336
348
|
#define STARTNODE (HUF_SYMBOLVALUE_MAX+1)
|
|
337
|
-
typedef nodeElt huffNodeTable[
|
|
338
|
-
size_t HUF_buildCTable_wksp (HUF_CElt* tree, const
|
|
349
|
+
typedef nodeElt huffNodeTable[HUF_CTABLE_WORKSPACE_SIZE_U32];
|
|
350
|
+
size_t HUF_buildCTable_wksp (HUF_CElt* tree, const unsigned* count, U32 maxSymbolValue, U32 maxNbBits, void* workSpace, size_t wkspSize)
|
|
339
351
|
{
|
|
340
352
|
nodeElt* const huffNode0 = (nodeElt*)workSpace;
|
|
341
353
|
nodeElt* const huffNode = huffNode0+1;
|
|
@@ -345,9 +357,10 @@ size_t HUF_buildCTable_wksp (HUF_CElt* tree, const U32* count, U32 maxSymbolValu
|
|
|
345
357
|
U32 nodeRoot;
|
|
346
358
|
|
|
347
359
|
/* safety checks */
|
|
348
|
-
if (
|
|
360
|
+
if (((size_t)workSpace & 3) != 0) return ERROR(GENERIC); /* must be aligned on 4-bytes boundaries */
|
|
361
|
+
if (wkspSize < sizeof(huffNodeTable)) return ERROR(workSpace_tooSmall);
|
|
349
362
|
if (maxNbBits == 0) maxNbBits = HUF_TABLELOG_DEFAULT;
|
|
350
|
-
if (maxSymbolValue > HUF_SYMBOLVALUE_MAX) return ERROR(
|
|
363
|
+
if (maxSymbolValue > HUF_SYMBOLVALUE_MAX) return ERROR(maxSymbolValue_tooLarge);
|
|
351
364
|
memset(huffNode0, 0, sizeof(huffNodeTable));
|
|
352
365
|
|
|
353
366
|
/* sort, decreasing order */
|
|
@@ -405,9 +418,10 @@ size_t HUF_buildCTable_wksp (HUF_CElt* tree, const U32* count, U32 maxSymbolValu
|
|
|
405
418
|
}
|
|
406
419
|
|
|
407
420
|
/** HUF_buildCTable() :
|
|
421
|
+
* @return : maxNbBits
|
|
408
422
|
* Note : count is used before tree is written, so they can safely overlap
|
|
409
423
|
*/
|
|
410
|
-
size_t HUF_buildCTable (HUF_CElt* tree, const
|
|
424
|
+
size_t HUF_buildCTable (HUF_CElt* tree, const unsigned* count, unsigned maxSymbolValue, unsigned maxNbBits)
|
|
411
425
|
{
|
|
412
426
|
huffNodeTable nodeTable;
|
|
413
427
|
return HUF_buildCTable_wksp(tree, count, maxSymbolValue, maxNbBits, nodeTable, sizeof(nodeTable));
|
|
@@ -432,13 +446,14 @@ static int HUF_validateCTable(const HUF_CElt* CTable, const unsigned* count, uns
|
|
|
432
446
|
return !bad;
|
|
433
447
|
}
|
|
434
448
|
|
|
435
|
-
|
|
449
|
+
size_t HUF_compressBound(size_t size) { return HUF_COMPRESSBOUND(size); }
|
|
450
|
+
|
|
451
|
+
FORCE_INLINE_TEMPLATE void
|
|
452
|
+
HUF_encodeSymbol(BIT_CStream_t* bitCPtr, U32 symbol, const HUF_CElt* CTable)
|
|
436
453
|
{
|
|
437
454
|
BIT_addBitsFast(bitCPtr, CTable[symbol].val, CTable[symbol].nbBits);
|
|
438
455
|
}
|
|
439
456
|
|
|
440
|
-
size_t HUF_compressBound(size_t size) { return HUF_COMPRESSBOUND(size); }
|
|
441
|
-
|
|
442
457
|
#define HUF_FLUSHBITS(s) BIT_flushBits(s)
|
|
443
458
|
|
|
444
459
|
#define HUF_FLUSHBITS_1(stream) \
|
|
@@ -447,7 +462,10 @@ size_t HUF_compressBound(size_t size) { return HUF_COMPRESSBOUND(size); }
|
|
|
447
462
|
#define HUF_FLUSHBITS_2(stream) \
|
|
448
463
|
if (sizeof((stream)->bitContainer)*8 < HUF_TABLELOG_MAX*4+7) HUF_FLUSHBITS(stream)
|
|
449
464
|
|
|
450
|
-
|
|
465
|
+
FORCE_INLINE_TEMPLATE size_t
|
|
466
|
+
HUF_compress1X_usingCTable_internal_body(void* dst, size_t dstSize,
|
|
467
|
+
const void* src, size_t srcSize,
|
|
468
|
+
const HUF_CElt* CTable)
|
|
451
469
|
{
|
|
452
470
|
const BYTE* ip = (const BYTE*) src;
|
|
453
471
|
BYTE* const ostart = (BYTE*)dst;
|
|
@@ -491,8 +509,58 @@ size_t HUF_compress1X_usingCTable(void* dst, size_t dstSize, const void* src, si
|
|
|
491
509
|
return BIT_closeCStream(&bitC);
|
|
492
510
|
}
|
|
493
511
|
|
|
512
|
+
#if DYNAMIC_BMI2
|
|
494
513
|
|
|
495
|
-
|
|
514
|
+
static TARGET_ATTRIBUTE("bmi2") size_t
|
|
515
|
+
HUF_compress1X_usingCTable_internal_bmi2(void* dst, size_t dstSize,
|
|
516
|
+
const void* src, size_t srcSize,
|
|
517
|
+
const HUF_CElt* CTable)
|
|
518
|
+
{
|
|
519
|
+
return HUF_compress1X_usingCTable_internal_body(dst, dstSize, src, srcSize, CTable);
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
static size_t
|
|
523
|
+
HUF_compress1X_usingCTable_internal_default(void* dst, size_t dstSize,
|
|
524
|
+
const void* src, size_t srcSize,
|
|
525
|
+
const HUF_CElt* CTable)
|
|
526
|
+
{
|
|
527
|
+
return HUF_compress1X_usingCTable_internal_body(dst, dstSize, src, srcSize, CTable);
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
static size_t
|
|
531
|
+
HUF_compress1X_usingCTable_internal(void* dst, size_t dstSize,
|
|
532
|
+
const void* src, size_t srcSize,
|
|
533
|
+
const HUF_CElt* CTable, const int bmi2)
|
|
534
|
+
{
|
|
535
|
+
if (bmi2) {
|
|
536
|
+
return HUF_compress1X_usingCTable_internal_bmi2(dst, dstSize, src, srcSize, CTable);
|
|
537
|
+
}
|
|
538
|
+
return HUF_compress1X_usingCTable_internal_default(dst, dstSize, src, srcSize, CTable);
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
#else
|
|
542
|
+
|
|
543
|
+
static size_t
|
|
544
|
+
HUF_compress1X_usingCTable_internal(void* dst, size_t dstSize,
|
|
545
|
+
const void* src, size_t srcSize,
|
|
546
|
+
const HUF_CElt* CTable, const int bmi2)
|
|
547
|
+
{
|
|
548
|
+
(void)bmi2;
|
|
549
|
+
return HUF_compress1X_usingCTable_internal_body(dst, dstSize, src, srcSize, CTable);
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
#endif
|
|
553
|
+
|
|
554
|
+
size_t HUF_compress1X_usingCTable(void* dst, size_t dstSize, const void* src, size_t srcSize, const HUF_CElt* CTable)
|
|
555
|
+
{
|
|
556
|
+
return HUF_compress1X_usingCTable_internal(dst, dstSize, src, srcSize, CTable, /* bmi2 */ 0);
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
|
|
560
|
+
static size_t
|
|
561
|
+
HUF_compress4X_usingCTable_internal(void* dst, size_t dstSize,
|
|
562
|
+
const void* src, size_t srcSize,
|
|
563
|
+
const HUF_CElt* CTable, int bmi2)
|
|
496
564
|
{
|
|
497
565
|
size_t const segmentSize = (srcSize+3)/4; /* first 3 segments */
|
|
498
566
|
const BYTE* ip = (const BYTE*) src;
|
|
@@ -505,28 +573,31 @@ size_t HUF_compress4X_usingCTable(void* dst, size_t dstSize, const void* src, si
|
|
|
505
573
|
if (srcSize < 12) return 0; /* no saving possible : too small input */
|
|
506
574
|
op += 6; /* jumpTable */
|
|
507
575
|
|
|
508
|
-
{ CHECK_V_F(cSize,
|
|
576
|
+
{ CHECK_V_F(cSize, HUF_compress1X_usingCTable_internal(op, oend-op, ip, segmentSize, CTable, bmi2) );
|
|
509
577
|
if (cSize==0) return 0;
|
|
578
|
+
assert(cSize <= 65535);
|
|
510
579
|
MEM_writeLE16(ostart, (U16)cSize);
|
|
511
580
|
op += cSize;
|
|
512
581
|
}
|
|
513
582
|
|
|
514
583
|
ip += segmentSize;
|
|
515
|
-
{ CHECK_V_F(cSize,
|
|
584
|
+
{ CHECK_V_F(cSize, HUF_compress1X_usingCTable_internal(op, oend-op, ip, segmentSize, CTable, bmi2) );
|
|
516
585
|
if (cSize==0) return 0;
|
|
586
|
+
assert(cSize <= 65535);
|
|
517
587
|
MEM_writeLE16(ostart+2, (U16)cSize);
|
|
518
588
|
op += cSize;
|
|
519
589
|
}
|
|
520
590
|
|
|
521
591
|
ip += segmentSize;
|
|
522
|
-
{ CHECK_V_F(cSize,
|
|
592
|
+
{ CHECK_V_F(cSize, HUF_compress1X_usingCTable_internal(op, oend-op, ip, segmentSize, CTable, bmi2) );
|
|
523
593
|
if (cSize==0) return 0;
|
|
594
|
+
assert(cSize <= 65535);
|
|
524
595
|
MEM_writeLE16(ostart+4, (U16)cSize);
|
|
525
596
|
op += cSize;
|
|
526
597
|
}
|
|
527
598
|
|
|
528
599
|
ip += segmentSize;
|
|
529
|
-
{ CHECK_V_F(cSize,
|
|
600
|
+
{ CHECK_V_F(cSize, HUF_compress1X_usingCTable_internal(op, oend-op, ip, iend-ip, CTable, bmi2) );
|
|
530
601
|
if (cSize==0) return 0;
|
|
531
602
|
op += cSize;
|
|
532
603
|
}
|
|
@@ -534,15 +605,21 @@ size_t HUF_compress4X_usingCTable(void* dst, size_t dstSize, const void* src, si
|
|
|
534
605
|
return op-ostart;
|
|
535
606
|
}
|
|
536
607
|
|
|
608
|
+
size_t HUF_compress4X_usingCTable(void* dst, size_t dstSize, const void* src, size_t srcSize, const HUF_CElt* CTable)
|
|
609
|
+
{
|
|
610
|
+
return HUF_compress4X_usingCTable_internal(dst, dstSize, src, srcSize, CTable, /* bmi2 */ 0);
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
typedef enum { HUF_singleStream, HUF_fourStreams } HUF_nbStreams_e;
|
|
537
614
|
|
|
538
615
|
static size_t HUF_compressCTable_internal(
|
|
539
616
|
BYTE* const ostart, BYTE* op, BYTE* const oend,
|
|
540
617
|
const void* src, size_t srcSize,
|
|
541
|
-
|
|
618
|
+
HUF_nbStreams_e nbStreams, const HUF_CElt* CTable, const int bmi2)
|
|
542
619
|
{
|
|
543
|
-
size_t const cSize =
|
|
544
|
-
|
|
545
|
-
|
|
620
|
+
size_t const cSize = (nbStreams==HUF_singleStream) ?
|
|
621
|
+
HUF_compress1X_usingCTable_internal(op, oend - op, src, srcSize, CTable, bmi2) :
|
|
622
|
+
HUF_compress4X_usingCTable_internal(op, oend - op, src, srcSize, CTable, bmi2);
|
|
546
623
|
if (HUF_isError(cSize)) { return cSize; }
|
|
547
624
|
if (cSize==0) { return 0; } /* uncompressible */
|
|
548
625
|
op += cSize;
|
|
@@ -551,86 +628,99 @@ static size_t HUF_compressCTable_internal(
|
|
|
551
628
|
return op-ostart;
|
|
552
629
|
}
|
|
553
630
|
|
|
631
|
+
typedef struct {
|
|
632
|
+
unsigned count[HUF_SYMBOLVALUE_MAX + 1];
|
|
633
|
+
HUF_CElt CTable[HUF_SYMBOLVALUE_MAX + 1];
|
|
634
|
+
huffNodeTable nodeTable;
|
|
635
|
+
} HUF_compress_tables_t;
|
|
554
636
|
|
|
555
|
-
/*
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
637
|
+
/* HUF_compress_internal() :
|
|
638
|
+
* `workSpace` must a table of at least HUF_WORKSPACE_SIZE_U32 unsigned */
|
|
639
|
+
static size_t
|
|
640
|
+
HUF_compress_internal (void* dst, size_t dstSize,
|
|
641
|
+
const void* src, size_t srcSize,
|
|
642
|
+
unsigned maxSymbolValue, unsigned huffLog,
|
|
643
|
+
HUF_nbStreams_e nbStreams,
|
|
644
|
+
void* workSpace, size_t wkspSize,
|
|
645
|
+
HUF_CElt* oldHufTable, HUF_repeat* repeat, int preferRepeat,
|
|
646
|
+
const int bmi2)
|
|
563
647
|
{
|
|
648
|
+
HUF_compress_tables_t* const table = (HUF_compress_tables_t*)workSpace;
|
|
564
649
|
BYTE* const ostart = (BYTE*)dst;
|
|
565
650
|
BYTE* const oend = ostart + dstSize;
|
|
566
651
|
BYTE* op = ostart;
|
|
567
652
|
|
|
568
|
-
U32* count;
|
|
569
|
-
size_t const countSize = sizeof(U32) * (HUF_SYMBOLVALUE_MAX + 1);
|
|
570
|
-
HUF_CElt* CTable;
|
|
571
|
-
size_t const CTableSize = sizeof(HUF_CElt) * (HUF_SYMBOLVALUE_MAX + 1);
|
|
572
|
-
|
|
573
653
|
/* checks & inits */
|
|
574
|
-
if (
|
|
575
|
-
if (
|
|
576
|
-
if (!
|
|
654
|
+
if (((size_t)workSpace & 3) != 0) return ERROR(GENERIC); /* must be aligned on 4-bytes boundaries */
|
|
655
|
+
if (wkspSize < HUF_WORKSPACE_SIZE) return ERROR(workSpace_tooSmall);
|
|
656
|
+
if (!srcSize) return 0; /* Uncompressed */
|
|
657
|
+
if (!dstSize) return 0; /* cannot fit anything within dst budget */
|
|
577
658
|
if (srcSize > HUF_BLOCKSIZE_MAX) return ERROR(srcSize_wrong); /* current block size limit */
|
|
578
659
|
if (huffLog > HUF_TABLELOG_MAX) return ERROR(tableLog_tooLarge);
|
|
660
|
+
if (maxSymbolValue > HUF_SYMBOLVALUE_MAX) return ERROR(maxSymbolValue_tooLarge);
|
|
579
661
|
if (!maxSymbolValue) maxSymbolValue = HUF_SYMBOLVALUE_MAX;
|
|
580
662
|
if (!huffLog) huffLog = HUF_TABLELOG_DEFAULT;
|
|
581
663
|
|
|
582
|
-
|
|
583
|
-
workSpace = (BYTE*)workSpace + countSize;
|
|
584
|
-
wkspSize -= countSize;
|
|
585
|
-
CTable = (HUF_CElt*)workSpace;
|
|
586
|
-
workSpace = (BYTE*)workSpace + CTableSize;
|
|
587
|
-
wkspSize -= CTableSize;
|
|
588
|
-
|
|
589
|
-
/* Heuristic : If we don't need to check the validity of the old table use the old table for small inputs */
|
|
664
|
+
/* Heuristic : If old table is valid, use it for small inputs */
|
|
590
665
|
if (preferRepeat && repeat && *repeat == HUF_repeat_valid) {
|
|
591
|
-
return HUF_compressCTable_internal(ostart, op, oend,
|
|
666
|
+
return HUF_compressCTable_internal(ostart, op, oend,
|
|
667
|
+
src, srcSize,
|
|
668
|
+
nbStreams, oldHufTable, bmi2);
|
|
592
669
|
}
|
|
593
670
|
|
|
594
671
|
/* Scan input and build symbol stats */
|
|
595
|
-
{ CHECK_V_F(largest,
|
|
672
|
+
{ CHECK_V_F(largest, HIST_count_wksp (table->count, &maxSymbolValue, (const BYTE*)src, srcSize, workSpace, wkspSize) );
|
|
596
673
|
if (largest == srcSize) { *ostart = ((const BYTE*)src)[0]; return 1; } /* single symbol, rle */
|
|
597
|
-
if (largest <= (srcSize >> 7)+
|
|
674
|
+
if (largest <= (srcSize >> 7)+4) return 0; /* heuristic : probably not compressible enough */
|
|
598
675
|
}
|
|
599
676
|
|
|
600
677
|
/* Check validity of previous table */
|
|
601
|
-
if (
|
|
678
|
+
if ( repeat
|
|
679
|
+
&& *repeat == HUF_repeat_check
|
|
680
|
+
&& !HUF_validateCTable(oldHufTable, table->count, maxSymbolValue)) {
|
|
602
681
|
*repeat = HUF_repeat_none;
|
|
603
682
|
}
|
|
604
683
|
/* Heuristic : use existing table for small inputs */
|
|
605
684
|
if (preferRepeat && repeat && *repeat != HUF_repeat_none) {
|
|
606
|
-
return HUF_compressCTable_internal(ostart, op, oend,
|
|
685
|
+
return HUF_compressCTable_internal(ostart, op, oend,
|
|
686
|
+
src, srcSize,
|
|
687
|
+
nbStreams, oldHufTable, bmi2);
|
|
607
688
|
}
|
|
608
689
|
|
|
609
690
|
/* Build Huffman Tree */
|
|
610
691
|
huffLog = HUF_optimalTableLog(huffLog, srcSize, maxSymbolValue);
|
|
611
|
-
{
|
|
692
|
+
{ size_t const maxBits = HUF_buildCTable_wksp(table->CTable, table->count,
|
|
693
|
+
maxSymbolValue, huffLog,
|
|
694
|
+
table->nodeTable, sizeof(table->nodeTable));
|
|
695
|
+
CHECK_F(maxBits);
|
|
612
696
|
huffLog = (U32)maxBits;
|
|
613
|
-
/* Zero
|
|
614
|
-
memset(CTable + maxSymbolValue + 1, 0,
|
|
697
|
+
/* Zero unused symbols in CTable, so we can check it for validity */
|
|
698
|
+
memset(table->CTable + (maxSymbolValue + 1), 0,
|
|
699
|
+
sizeof(table->CTable) - ((maxSymbolValue + 1) * sizeof(HUF_CElt)));
|
|
615
700
|
}
|
|
616
701
|
|
|
617
702
|
/* Write table description header */
|
|
618
|
-
{ CHECK_V_F(hSize, HUF_writeCTable (op, dstSize, CTable, maxSymbolValue, huffLog) );
|
|
619
|
-
/* Check if using
|
|
703
|
+
{ CHECK_V_F(hSize, HUF_writeCTable (op, dstSize, table->CTable, maxSymbolValue, huffLog) );
|
|
704
|
+
/* Check if using previous huffman table is beneficial */
|
|
620
705
|
if (repeat && *repeat != HUF_repeat_none) {
|
|
621
|
-
size_t const oldSize = HUF_estimateCompressedSize(oldHufTable, count, maxSymbolValue);
|
|
622
|
-
size_t const newSize = HUF_estimateCompressedSize(CTable, count, maxSymbolValue);
|
|
706
|
+
size_t const oldSize = HUF_estimateCompressedSize(oldHufTable, table->count, maxSymbolValue);
|
|
707
|
+
size_t const newSize = HUF_estimateCompressedSize(table->CTable, table->count, maxSymbolValue);
|
|
623
708
|
if (oldSize <= hSize + newSize || hSize + 12 >= srcSize) {
|
|
624
|
-
return HUF_compressCTable_internal(ostart, op, oend,
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
709
|
+
return HUF_compressCTable_internal(ostart, op, oend,
|
|
710
|
+
src, srcSize,
|
|
711
|
+
nbStreams, oldHufTable, bmi2);
|
|
712
|
+
} }
|
|
713
|
+
|
|
714
|
+
/* Use the new huffman table */
|
|
628
715
|
if (hSize + 12ul >= srcSize) { return 0; }
|
|
629
716
|
op += hSize;
|
|
630
717
|
if (repeat) { *repeat = HUF_repeat_none; }
|
|
631
|
-
if (oldHufTable)
|
|
718
|
+
if (oldHufTable)
|
|
719
|
+
memcpy(oldHufTable, table->CTable, sizeof(table->CTable)); /* Save new table */
|
|
632
720
|
}
|
|
633
|
-
return HUF_compressCTable_internal(ostart, op, oend,
|
|
721
|
+
return HUF_compressCTable_internal(ostart, op, oend,
|
|
722
|
+
src, srcSize,
|
|
723
|
+
nbStreams, table->CTable, bmi2);
|
|
634
724
|
}
|
|
635
725
|
|
|
636
726
|
|
|
@@ -639,52 +729,70 @@ size_t HUF_compress1X_wksp (void* dst, size_t dstSize,
|
|
|
639
729
|
unsigned maxSymbolValue, unsigned huffLog,
|
|
640
730
|
void* workSpace, size_t wkspSize)
|
|
641
731
|
{
|
|
642
|
-
return HUF_compress_internal(dst, dstSize, src, srcSize,
|
|
732
|
+
return HUF_compress_internal(dst, dstSize, src, srcSize,
|
|
733
|
+
maxSymbolValue, huffLog, HUF_singleStream,
|
|
734
|
+
workSpace, wkspSize,
|
|
735
|
+
NULL, NULL, 0, 0 /*bmi2*/);
|
|
643
736
|
}
|
|
644
737
|
|
|
645
738
|
size_t HUF_compress1X_repeat (void* dst, size_t dstSize,
|
|
646
739
|
const void* src, size_t srcSize,
|
|
647
740
|
unsigned maxSymbolValue, unsigned huffLog,
|
|
648
741
|
void* workSpace, size_t wkspSize,
|
|
649
|
-
HUF_CElt* hufTable, HUF_repeat* repeat, int preferRepeat)
|
|
742
|
+
HUF_CElt* hufTable, HUF_repeat* repeat, int preferRepeat, int bmi2)
|
|
650
743
|
{
|
|
651
|
-
return HUF_compress_internal(dst, dstSize, src, srcSize,
|
|
744
|
+
return HUF_compress_internal(dst, dstSize, src, srcSize,
|
|
745
|
+
maxSymbolValue, huffLog, HUF_singleStream,
|
|
746
|
+
workSpace, wkspSize, hufTable,
|
|
747
|
+
repeat, preferRepeat, bmi2);
|
|
652
748
|
}
|
|
653
749
|
|
|
654
750
|
size_t HUF_compress1X (void* dst, size_t dstSize,
|
|
655
751
|
const void* src, size_t srcSize,
|
|
656
752
|
unsigned maxSymbolValue, unsigned huffLog)
|
|
657
753
|
{
|
|
658
|
-
unsigned workSpace[
|
|
754
|
+
unsigned workSpace[HUF_WORKSPACE_SIZE_U32];
|
|
659
755
|
return HUF_compress1X_wksp(dst, dstSize, src, srcSize, maxSymbolValue, huffLog, workSpace, sizeof(workSpace));
|
|
660
756
|
}
|
|
661
757
|
|
|
758
|
+
/* HUF_compress4X_repeat():
|
|
759
|
+
* compress input using 4 streams.
|
|
760
|
+
* provide workspace to generate compression tables */
|
|
662
761
|
size_t HUF_compress4X_wksp (void* dst, size_t dstSize,
|
|
663
762
|
const void* src, size_t srcSize,
|
|
664
763
|
unsigned maxSymbolValue, unsigned huffLog,
|
|
665
764
|
void* workSpace, size_t wkspSize)
|
|
666
765
|
{
|
|
667
|
-
return HUF_compress_internal(dst, dstSize, src, srcSize,
|
|
766
|
+
return HUF_compress_internal(dst, dstSize, src, srcSize,
|
|
767
|
+
maxSymbolValue, huffLog, HUF_fourStreams,
|
|
768
|
+
workSpace, wkspSize,
|
|
769
|
+
NULL, NULL, 0, 0 /*bmi2*/);
|
|
668
770
|
}
|
|
669
771
|
|
|
772
|
+
/* HUF_compress4X_repeat():
|
|
773
|
+
* compress input using 4 streams.
|
|
774
|
+
* re-use an existing huffman compression table */
|
|
670
775
|
size_t HUF_compress4X_repeat (void* dst, size_t dstSize,
|
|
671
776
|
const void* src, size_t srcSize,
|
|
672
777
|
unsigned maxSymbolValue, unsigned huffLog,
|
|
673
778
|
void* workSpace, size_t wkspSize,
|
|
674
|
-
HUF_CElt* hufTable, HUF_repeat* repeat, int preferRepeat)
|
|
779
|
+
HUF_CElt* hufTable, HUF_repeat* repeat, int preferRepeat, int bmi2)
|
|
675
780
|
{
|
|
676
|
-
return HUF_compress_internal(dst, dstSize, src, srcSize,
|
|
781
|
+
return HUF_compress_internal(dst, dstSize, src, srcSize,
|
|
782
|
+
maxSymbolValue, huffLog, HUF_fourStreams,
|
|
783
|
+
workSpace, wkspSize,
|
|
784
|
+
hufTable, repeat, preferRepeat, bmi2);
|
|
677
785
|
}
|
|
678
786
|
|
|
679
787
|
size_t HUF_compress2 (void* dst, size_t dstSize,
|
|
680
788
|
const void* src, size_t srcSize,
|
|
681
789
|
unsigned maxSymbolValue, unsigned huffLog)
|
|
682
790
|
{
|
|
683
|
-
unsigned workSpace[
|
|
791
|
+
unsigned workSpace[HUF_WORKSPACE_SIZE_U32];
|
|
684
792
|
return HUF_compress4X_wksp(dst, dstSize, src, srcSize, maxSymbolValue, huffLog, workSpace, sizeof(workSpace));
|
|
685
793
|
}
|
|
686
794
|
|
|
687
795
|
size_t HUF_compress (void* dst, size_t maxDstSize, const void* src, size_t srcSize)
|
|
688
796
|
{
|
|
689
|
-
return HUF_compress2(dst, maxDstSize, src,
|
|
797
|
+
return HUF_compress2(dst, maxDstSize, src, srcSize, 255, HUF_TABLELOG_DEFAULT);
|
|
690
798
|
}
|