xref: /aosp_15_r20/external/zstd/lib/common/entropy_common.c (revision 01826a4963a0d8a59bc3812d29bdf0fb76416722)
1*01826a49SYabin Cui /* ******************************************************************
2*01826a49SYabin Cui  * Common functions of New Generation Entropy library
3*01826a49SYabin Cui  * Copyright (c) Meta Platforms, Inc. and affiliates.
4*01826a49SYabin Cui  *
5*01826a49SYabin Cui  *  You can contact the author at :
6*01826a49SYabin Cui  *  - FSE+HUF source repository : https://github.com/Cyan4973/FiniteStateEntropy
7*01826a49SYabin Cui  *  - Public forum : https://groups.google.com/forum/#!forum/lz4c
8*01826a49SYabin Cui  *
9*01826a49SYabin Cui  * This source code is licensed under both the BSD-style license (found in the
10*01826a49SYabin Cui  * LICENSE file in the root directory of this source tree) and the GPLv2 (found
11*01826a49SYabin Cui  * in the COPYING file in the root directory of this source tree).
12*01826a49SYabin Cui  * You may select, at your option, one of the above-listed licenses.
13*01826a49SYabin Cui ****************************************************************** */
14*01826a49SYabin Cui 
15*01826a49SYabin Cui /* *************************************
16*01826a49SYabin Cui *  Dependencies
17*01826a49SYabin Cui ***************************************/
18*01826a49SYabin Cui #include "mem.h"
19*01826a49SYabin Cui #include "error_private.h"       /* ERR_*, ERROR */
20*01826a49SYabin Cui #define FSE_STATIC_LINKING_ONLY  /* FSE_MIN_TABLELOG */
21*01826a49SYabin Cui #include "fse.h"
22*01826a49SYabin Cui #include "huf.h"
23*01826a49SYabin Cui #include "bits.h"                /* ZSDT_highbit32, ZSTD_countTrailingZeros32 */
24*01826a49SYabin Cui 
25*01826a49SYabin Cui 
26*01826a49SYabin Cui /*===   Version   ===*/
FSE_versionNumber(void)27*01826a49SYabin Cui unsigned FSE_versionNumber(void) { return FSE_VERSION_NUMBER; }
28*01826a49SYabin Cui 
29*01826a49SYabin Cui 
30*01826a49SYabin Cui /*===   Error Management   ===*/
FSE_isError(size_t code)31*01826a49SYabin Cui unsigned FSE_isError(size_t code) { return ERR_isError(code); }
FSE_getErrorName(size_t code)32*01826a49SYabin Cui const char* FSE_getErrorName(size_t code) { return ERR_getErrorName(code); }
33*01826a49SYabin Cui 
HUF_isError(size_t code)34*01826a49SYabin Cui unsigned HUF_isError(size_t code) { return ERR_isError(code); }
HUF_getErrorName(size_t code)35*01826a49SYabin Cui const char* HUF_getErrorName(size_t code) { return ERR_getErrorName(code); }
36*01826a49SYabin Cui 
37*01826a49SYabin Cui 
38*01826a49SYabin Cui /*-**************************************************************
39*01826a49SYabin Cui *  FSE NCount encoding-decoding
40*01826a49SYabin Cui ****************************************************************/
41*01826a49SYabin Cui FORCE_INLINE_TEMPLATE
FSE_readNCount_body(short * normalizedCounter,unsigned * maxSVPtr,unsigned * tableLogPtr,const void * headerBuffer,size_t hbSize)42*01826a49SYabin Cui size_t FSE_readNCount_body(short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr,
43*01826a49SYabin Cui                            const void* headerBuffer, size_t hbSize)
44*01826a49SYabin Cui {
45*01826a49SYabin Cui     const BYTE* const istart = (const BYTE*) headerBuffer;
46*01826a49SYabin Cui     const BYTE* const iend = istart + hbSize;
47*01826a49SYabin Cui     const BYTE* ip = istart;
48*01826a49SYabin Cui     int nbBits;
49*01826a49SYabin Cui     int remaining;
50*01826a49SYabin Cui     int threshold;
51*01826a49SYabin Cui     U32 bitStream;
52*01826a49SYabin Cui     int bitCount;
53*01826a49SYabin Cui     unsigned charnum = 0;
54*01826a49SYabin Cui     unsigned const maxSV1 = *maxSVPtr + 1;
55*01826a49SYabin Cui     int previous0 = 0;
56*01826a49SYabin Cui 
57*01826a49SYabin Cui     if (hbSize < 8) {
58*01826a49SYabin Cui         /* This function only works when hbSize >= 8 */
59*01826a49SYabin Cui         char buffer[8] = {0};
60*01826a49SYabin Cui         ZSTD_memcpy(buffer, headerBuffer, hbSize);
61*01826a49SYabin Cui         {   size_t const countSize = FSE_readNCount(normalizedCounter, maxSVPtr, tableLogPtr,
62*01826a49SYabin Cui                                                     buffer, sizeof(buffer));
63*01826a49SYabin Cui             if (FSE_isError(countSize)) return countSize;
64*01826a49SYabin Cui             if (countSize > hbSize) return ERROR(corruption_detected);
65*01826a49SYabin Cui             return countSize;
66*01826a49SYabin Cui     }   }
67*01826a49SYabin Cui     assert(hbSize >= 8);
68*01826a49SYabin Cui 
69*01826a49SYabin Cui     /* init */
70*01826a49SYabin Cui     ZSTD_memset(normalizedCounter, 0, (*maxSVPtr+1) * sizeof(normalizedCounter[0]));   /* all symbols not present in NCount have a frequency of 0 */
71*01826a49SYabin Cui     bitStream = MEM_readLE32(ip);
72*01826a49SYabin Cui     nbBits = (bitStream & 0xF) + FSE_MIN_TABLELOG;   /* extract tableLog */
73*01826a49SYabin Cui     if (nbBits > FSE_TABLELOG_ABSOLUTE_MAX) return ERROR(tableLog_tooLarge);
74*01826a49SYabin Cui     bitStream >>= 4;
75*01826a49SYabin Cui     bitCount = 4;
76*01826a49SYabin Cui     *tableLogPtr = nbBits;
77*01826a49SYabin Cui     remaining = (1<<nbBits)+1;
78*01826a49SYabin Cui     threshold = 1<<nbBits;
79*01826a49SYabin Cui     nbBits++;
80*01826a49SYabin Cui 
81*01826a49SYabin Cui     for (;;) {
82*01826a49SYabin Cui         if (previous0) {
83*01826a49SYabin Cui             /* Count the number of repeats. Each time the
84*01826a49SYabin Cui              * 2-bit repeat code is 0b11 there is another
85*01826a49SYabin Cui              * repeat.
86*01826a49SYabin Cui              * Avoid UB by setting the high bit to 1.
87*01826a49SYabin Cui              */
88*01826a49SYabin Cui             int repeats = ZSTD_countTrailingZeros32(~bitStream | 0x80000000) >> 1;
89*01826a49SYabin Cui             while (repeats >= 12) {
90*01826a49SYabin Cui                 charnum += 3 * 12;
91*01826a49SYabin Cui                 if (LIKELY(ip <= iend-7)) {
92*01826a49SYabin Cui                     ip += 3;
93*01826a49SYabin Cui                 } else {
94*01826a49SYabin Cui                     bitCount -= (int)(8 * (iend - 7 - ip));
95*01826a49SYabin Cui                     bitCount &= 31;
96*01826a49SYabin Cui                     ip = iend - 4;
97*01826a49SYabin Cui                 }
98*01826a49SYabin Cui                 bitStream = MEM_readLE32(ip) >> bitCount;
99*01826a49SYabin Cui                 repeats = ZSTD_countTrailingZeros32(~bitStream | 0x80000000) >> 1;
100*01826a49SYabin Cui             }
101*01826a49SYabin Cui             charnum += 3 * repeats;
102*01826a49SYabin Cui             bitStream >>= 2 * repeats;
103*01826a49SYabin Cui             bitCount += 2 * repeats;
104*01826a49SYabin Cui 
105*01826a49SYabin Cui             /* Add the final repeat which isn't 0b11. */
106*01826a49SYabin Cui             assert((bitStream & 3) < 3);
107*01826a49SYabin Cui             charnum += bitStream & 3;
108*01826a49SYabin Cui             bitCount += 2;
109*01826a49SYabin Cui 
110*01826a49SYabin Cui             /* This is an error, but break and return an error
111*01826a49SYabin Cui              * at the end, because returning out of a loop makes
112*01826a49SYabin Cui              * it harder for the compiler to optimize.
113*01826a49SYabin Cui              */
114*01826a49SYabin Cui             if (charnum >= maxSV1) break;
115*01826a49SYabin Cui 
116*01826a49SYabin Cui             /* We don't need to set the normalized count to 0
117*01826a49SYabin Cui              * because we already memset the whole buffer to 0.
118*01826a49SYabin Cui              */
119*01826a49SYabin Cui 
120*01826a49SYabin Cui             if (LIKELY(ip <= iend-7) || (ip + (bitCount>>3) <= iend-4)) {
121*01826a49SYabin Cui                 assert((bitCount >> 3) <= 3); /* For first condition to work */
122*01826a49SYabin Cui                 ip += bitCount>>3;
123*01826a49SYabin Cui                 bitCount &= 7;
124*01826a49SYabin Cui             } else {
125*01826a49SYabin Cui                 bitCount -= (int)(8 * (iend - 4 - ip));
126*01826a49SYabin Cui                 bitCount &= 31;
127*01826a49SYabin Cui                 ip = iend - 4;
128*01826a49SYabin Cui             }
129*01826a49SYabin Cui             bitStream = MEM_readLE32(ip) >> bitCount;
130*01826a49SYabin Cui         }
131*01826a49SYabin Cui         {
132*01826a49SYabin Cui             int const max = (2*threshold-1) - remaining;
133*01826a49SYabin Cui             int count;
134*01826a49SYabin Cui 
135*01826a49SYabin Cui             if ((bitStream & (threshold-1)) < (U32)max) {
136*01826a49SYabin Cui                 count = bitStream & (threshold-1);
137*01826a49SYabin Cui                 bitCount += nbBits-1;
138*01826a49SYabin Cui             } else {
139*01826a49SYabin Cui                 count = bitStream & (2*threshold-1);
140*01826a49SYabin Cui                 if (count >= threshold) count -= max;
141*01826a49SYabin Cui                 bitCount += nbBits;
142*01826a49SYabin Cui             }
143*01826a49SYabin Cui 
144*01826a49SYabin Cui             count--;   /* extra accuracy */
145*01826a49SYabin Cui             /* When it matters (small blocks), this is a
146*01826a49SYabin Cui              * predictable branch, because we don't use -1.
147*01826a49SYabin Cui              */
148*01826a49SYabin Cui             if (count >= 0) {
149*01826a49SYabin Cui                 remaining -= count;
150*01826a49SYabin Cui             } else {
151*01826a49SYabin Cui                 assert(count == -1);
152*01826a49SYabin Cui                 remaining += count;
153*01826a49SYabin Cui             }
154*01826a49SYabin Cui             normalizedCounter[charnum++] = (short)count;
155*01826a49SYabin Cui             previous0 = !count;
156*01826a49SYabin Cui 
157*01826a49SYabin Cui             assert(threshold > 1);
158*01826a49SYabin Cui             if (remaining < threshold) {
159*01826a49SYabin Cui                 /* This branch can be folded into the
160*01826a49SYabin Cui                  * threshold update condition because we
161*01826a49SYabin Cui                  * know that threshold > 1.
162*01826a49SYabin Cui                  */
163*01826a49SYabin Cui                 if (remaining <= 1) break;
164*01826a49SYabin Cui                 nbBits = ZSTD_highbit32(remaining) + 1;
165*01826a49SYabin Cui                 threshold = 1 << (nbBits - 1);
166*01826a49SYabin Cui             }
167*01826a49SYabin Cui             if (charnum >= maxSV1) break;
168*01826a49SYabin Cui 
169*01826a49SYabin Cui             if (LIKELY(ip <= iend-7) || (ip + (bitCount>>3) <= iend-4)) {
170*01826a49SYabin Cui                 ip += bitCount>>3;
171*01826a49SYabin Cui                 bitCount &= 7;
172*01826a49SYabin Cui             } else {
173*01826a49SYabin Cui                 bitCount -= (int)(8 * (iend - 4 - ip));
174*01826a49SYabin Cui                 bitCount &= 31;
175*01826a49SYabin Cui                 ip = iend - 4;
176*01826a49SYabin Cui             }
177*01826a49SYabin Cui             bitStream = MEM_readLE32(ip) >> bitCount;
178*01826a49SYabin Cui     }   }
179*01826a49SYabin Cui     if (remaining != 1) return ERROR(corruption_detected);
180*01826a49SYabin Cui     /* Only possible when there are too many zeros. */
181*01826a49SYabin Cui     if (charnum > maxSV1) return ERROR(maxSymbolValue_tooSmall);
182*01826a49SYabin Cui     if (bitCount > 32) return ERROR(corruption_detected);
183*01826a49SYabin Cui     *maxSVPtr = charnum-1;
184*01826a49SYabin Cui 
185*01826a49SYabin Cui     ip += (bitCount+7)>>3;
186*01826a49SYabin Cui     return ip-istart;
187*01826a49SYabin Cui }
188*01826a49SYabin Cui 
189*01826a49SYabin Cui /* Avoids the FORCE_INLINE of the _body() function. */
FSE_readNCount_body_default(short * normalizedCounter,unsigned * maxSVPtr,unsigned * tableLogPtr,const void * headerBuffer,size_t hbSize)190*01826a49SYabin Cui static size_t FSE_readNCount_body_default(
191*01826a49SYabin Cui         short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr,
192*01826a49SYabin Cui         const void* headerBuffer, size_t hbSize)
193*01826a49SYabin Cui {
194*01826a49SYabin Cui     return FSE_readNCount_body(normalizedCounter, maxSVPtr, tableLogPtr, headerBuffer, hbSize);
195*01826a49SYabin Cui }
196*01826a49SYabin Cui 
197*01826a49SYabin Cui #if DYNAMIC_BMI2
FSE_readNCount_body_bmi2(short * normalizedCounter,unsigned * maxSVPtr,unsigned * tableLogPtr,const void * headerBuffer,size_t hbSize)198*01826a49SYabin Cui BMI2_TARGET_ATTRIBUTE static size_t FSE_readNCount_body_bmi2(
199*01826a49SYabin Cui         short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr,
200*01826a49SYabin Cui         const void* headerBuffer, size_t hbSize)
201*01826a49SYabin Cui {
202*01826a49SYabin Cui     return FSE_readNCount_body(normalizedCounter, maxSVPtr, tableLogPtr, headerBuffer, hbSize);
203*01826a49SYabin Cui }
204*01826a49SYabin Cui #endif
205*01826a49SYabin Cui 
FSE_readNCount_bmi2(short * normalizedCounter,unsigned * maxSVPtr,unsigned * tableLogPtr,const void * headerBuffer,size_t hbSize,int bmi2)206*01826a49SYabin Cui size_t FSE_readNCount_bmi2(
207*01826a49SYabin Cui         short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr,
208*01826a49SYabin Cui         const void* headerBuffer, size_t hbSize, int bmi2)
209*01826a49SYabin Cui {
210*01826a49SYabin Cui #if DYNAMIC_BMI2
211*01826a49SYabin Cui     if (bmi2) {
212*01826a49SYabin Cui         return FSE_readNCount_body_bmi2(normalizedCounter, maxSVPtr, tableLogPtr, headerBuffer, hbSize);
213*01826a49SYabin Cui     }
214*01826a49SYabin Cui #endif
215*01826a49SYabin Cui     (void)bmi2;
216*01826a49SYabin Cui     return FSE_readNCount_body_default(normalizedCounter, maxSVPtr, tableLogPtr, headerBuffer, hbSize);
217*01826a49SYabin Cui }
218*01826a49SYabin Cui 
FSE_readNCount(short * normalizedCounter,unsigned * maxSVPtr,unsigned * tableLogPtr,const void * headerBuffer,size_t hbSize)219*01826a49SYabin Cui size_t FSE_readNCount(
220*01826a49SYabin Cui         short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr,
221*01826a49SYabin Cui         const void* headerBuffer, size_t hbSize)
222*01826a49SYabin Cui {
223*01826a49SYabin Cui     return FSE_readNCount_bmi2(normalizedCounter, maxSVPtr, tableLogPtr, headerBuffer, hbSize, /* bmi2 */ 0);
224*01826a49SYabin Cui }
225*01826a49SYabin Cui 
226*01826a49SYabin Cui 
227*01826a49SYabin Cui /*! HUF_readStats() :
228*01826a49SYabin Cui     Read compact Huffman tree, saved by HUF_writeCTable().
229*01826a49SYabin Cui     `huffWeight` is destination buffer.
230*01826a49SYabin Cui     `rankStats` is assumed to be a table of at least HUF_TABLELOG_MAX U32.
231*01826a49SYabin Cui     @return : size read from `src` , or an error Code .
232*01826a49SYabin Cui     Note : Needed by HUF_readCTable() and HUF_readDTableX?() .
233*01826a49SYabin Cui */
HUF_readStats(BYTE * huffWeight,size_t hwSize,U32 * rankStats,U32 * nbSymbolsPtr,U32 * tableLogPtr,const void * src,size_t srcSize)234*01826a49SYabin Cui size_t HUF_readStats(BYTE* huffWeight, size_t hwSize, U32* rankStats,
235*01826a49SYabin Cui                      U32* nbSymbolsPtr, U32* tableLogPtr,
236*01826a49SYabin Cui                      const void* src, size_t srcSize)
237*01826a49SYabin Cui {
238*01826a49SYabin Cui     U32 wksp[HUF_READ_STATS_WORKSPACE_SIZE_U32];
239*01826a49SYabin Cui     return HUF_readStats_wksp(huffWeight, hwSize, rankStats, nbSymbolsPtr, tableLogPtr, src, srcSize, wksp, sizeof(wksp), /* flags */ 0);
240*01826a49SYabin Cui }
241*01826a49SYabin Cui 
242*01826a49SYabin Cui FORCE_INLINE_TEMPLATE size_t
HUF_readStats_body(BYTE * huffWeight,size_t hwSize,U32 * rankStats,U32 * nbSymbolsPtr,U32 * tableLogPtr,const void * src,size_t srcSize,void * workSpace,size_t wkspSize,int bmi2)243*01826a49SYabin Cui HUF_readStats_body(BYTE* huffWeight, size_t hwSize, U32* rankStats,
244*01826a49SYabin Cui                    U32* nbSymbolsPtr, U32* tableLogPtr,
245*01826a49SYabin Cui                    const void* src, size_t srcSize,
246*01826a49SYabin Cui                    void* workSpace, size_t wkspSize,
247*01826a49SYabin Cui                    int bmi2)
248*01826a49SYabin Cui {
249*01826a49SYabin Cui     U32 weightTotal;
250*01826a49SYabin Cui     const BYTE* ip = (const BYTE*) src;
251*01826a49SYabin Cui     size_t iSize;
252*01826a49SYabin Cui     size_t oSize;
253*01826a49SYabin Cui 
254*01826a49SYabin Cui     if (!srcSize) return ERROR(srcSize_wrong);
255*01826a49SYabin Cui     iSize = ip[0];
256*01826a49SYabin Cui     /* ZSTD_memset(huffWeight, 0, hwSize);   *//* is not necessary, even though some analyzer complain ... */
257*01826a49SYabin Cui 
258*01826a49SYabin Cui     if (iSize >= 128) {  /* special header */
259*01826a49SYabin Cui         oSize = iSize - 127;
260*01826a49SYabin Cui         iSize = ((oSize+1)/2);
261*01826a49SYabin Cui         if (iSize+1 > srcSize) return ERROR(srcSize_wrong);
262*01826a49SYabin Cui         if (oSize >= hwSize) return ERROR(corruption_detected);
263*01826a49SYabin Cui         ip += 1;
264*01826a49SYabin Cui         {   U32 n;
265*01826a49SYabin Cui             for (n=0; n<oSize; n+=2) {
266*01826a49SYabin Cui                 huffWeight[n]   = ip[n/2] >> 4;
267*01826a49SYabin Cui                 huffWeight[n+1] = ip[n/2] & 15;
268*01826a49SYabin Cui     }   }   }
269*01826a49SYabin Cui     else  {   /* header compressed with FSE (normal case) */
270*01826a49SYabin Cui         if (iSize+1 > srcSize) return ERROR(srcSize_wrong);
271*01826a49SYabin Cui         /* max (hwSize-1) values decoded, as last one is implied */
272*01826a49SYabin Cui         oSize = FSE_decompress_wksp_bmi2(huffWeight, hwSize-1, ip+1, iSize, 6, workSpace, wkspSize, bmi2);
273*01826a49SYabin Cui         if (FSE_isError(oSize)) return oSize;
274*01826a49SYabin Cui     }
275*01826a49SYabin Cui 
276*01826a49SYabin Cui     /* collect weight stats */
277*01826a49SYabin Cui     ZSTD_memset(rankStats, 0, (HUF_TABLELOG_MAX + 1) * sizeof(U32));
278*01826a49SYabin Cui     weightTotal = 0;
279*01826a49SYabin Cui     {   U32 n; for (n=0; n<oSize; n++) {
280*01826a49SYabin Cui             if (huffWeight[n] > HUF_TABLELOG_MAX) return ERROR(corruption_detected);
281*01826a49SYabin Cui             rankStats[huffWeight[n]]++;
282*01826a49SYabin Cui             weightTotal += (1 << huffWeight[n]) >> 1;
283*01826a49SYabin Cui     }   }
284*01826a49SYabin Cui     if (weightTotal == 0) return ERROR(corruption_detected);
285*01826a49SYabin Cui 
286*01826a49SYabin Cui     /* get last non-null symbol weight (implied, total must be 2^n) */
287*01826a49SYabin Cui     {   U32 const tableLog = ZSTD_highbit32(weightTotal) + 1;
288*01826a49SYabin Cui         if (tableLog > HUF_TABLELOG_MAX) return ERROR(corruption_detected);
289*01826a49SYabin Cui         *tableLogPtr = tableLog;
290*01826a49SYabin Cui         /* determine last weight */
291*01826a49SYabin Cui         {   U32 const total = 1 << tableLog;
292*01826a49SYabin Cui             U32 const rest = total - weightTotal;
293*01826a49SYabin Cui             U32 const verif = 1 << ZSTD_highbit32(rest);
294*01826a49SYabin Cui             U32 const lastWeight = ZSTD_highbit32(rest) + 1;
295*01826a49SYabin Cui             if (verif != rest) return ERROR(corruption_detected);    /* last value must be a clean power of 2 */
296*01826a49SYabin Cui             huffWeight[oSize] = (BYTE)lastWeight;
297*01826a49SYabin Cui             rankStats[lastWeight]++;
298*01826a49SYabin Cui     }   }
299*01826a49SYabin Cui 
300*01826a49SYabin Cui     /* check tree construction validity */
301*01826a49SYabin Cui     if ((rankStats[1] < 2) || (rankStats[1] & 1)) return ERROR(corruption_detected);   /* by construction : at least 2 elts of rank 1, must be even */
302*01826a49SYabin Cui 
303*01826a49SYabin Cui     /* results */
304*01826a49SYabin Cui     *nbSymbolsPtr = (U32)(oSize+1);
305*01826a49SYabin Cui     return iSize+1;
306*01826a49SYabin Cui }
307*01826a49SYabin Cui 
308*01826a49SYabin Cui /* Avoids the FORCE_INLINE of the _body() function. */
HUF_readStats_body_default(BYTE * huffWeight,size_t hwSize,U32 * rankStats,U32 * nbSymbolsPtr,U32 * tableLogPtr,const void * src,size_t srcSize,void * workSpace,size_t wkspSize)309*01826a49SYabin Cui static size_t HUF_readStats_body_default(BYTE* huffWeight, size_t hwSize, U32* rankStats,
310*01826a49SYabin Cui                      U32* nbSymbolsPtr, U32* tableLogPtr,
311*01826a49SYabin Cui                      const void* src, size_t srcSize,
312*01826a49SYabin Cui                      void* workSpace, size_t wkspSize)
313*01826a49SYabin Cui {
314*01826a49SYabin Cui     return HUF_readStats_body(huffWeight, hwSize, rankStats, nbSymbolsPtr, tableLogPtr, src, srcSize, workSpace, wkspSize, 0);
315*01826a49SYabin Cui }
316*01826a49SYabin Cui 
317*01826a49SYabin Cui #if DYNAMIC_BMI2
HUF_readStats_body_bmi2(BYTE * huffWeight,size_t hwSize,U32 * rankStats,U32 * nbSymbolsPtr,U32 * tableLogPtr,const void * src,size_t srcSize,void * workSpace,size_t wkspSize)318*01826a49SYabin Cui static BMI2_TARGET_ATTRIBUTE size_t HUF_readStats_body_bmi2(BYTE* huffWeight, size_t hwSize, U32* rankStats,
319*01826a49SYabin Cui                      U32* nbSymbolsPtr, U32* tableLogPtr,
320*01826a49SYabin Cui                      const void* src, size_t srcSize,
321*01826a49SYabin Cui                      void* workSpace, size_t wkspSize)
322*01826a49SYabin Cui {
323*01826a49SYabin Cui     return HUF_readStats_body(huffWeight, hwSize, rankStats, nbSymbolsPtr, tableLogPtr, src, srcSize, workSpace, wkspSize, 1);
324*01826a49SYabin Cui }
325*01826a49SYabin Cui #endif
326*01826a49SYabin Cui 
HUF_readStats_wksp(BYTE * huffWeight,size_t hwSize,U32 * rankStats,U32 * nbSymbolsPtr,U32 * tableLogPtr,const void * src,size_t srcSize,void * workSpace,size_t wkspSize,int flags)327*01826a49SYabin Cui size_t HUF_readStats_wksp(BYTE* huffWeight, size_t hwSize, U32* rankStats,
328*01826a49SYabin Cui                      U32* nbSymbolsPtr, U32* tableLogPtr,
329*01826a49SYabin Cui                      const void* src, size_t srcSize,
330*01826a49SYabin Cui                      void* workSpace, size_t wkspSize,
331*01826a49SYabin Cui                      int flags)
332*01826a49SYabin Cui {
333*01826a49SYabin Cui #if DYNAMIC_BMI2
334*01826a49SYabin Cui     if (flags & HUF_flags_bmi2) {
335*01826a49SYabin Cui         return HUF_readStats_body_bmi2(huffWeight, hwSize, rankStats, nbSymbolsPtr, tableLogPtr, src, srcSize, workSpace, wkspSize);
336*01826a49SYabin Cui     }
337*01826a49SYabin Cui #endif
338*01826a49SYabin Cui     (void)flags;
339*01826a49SYabin Cui     return HUF_readStats_body_default(huffWeight, hwSize, rankStats, nbSymbolsPtr, tableLogPtr, src, srcSize, workSpace, wkspSize);
340*01826a49SYabin Cui }
341