137f1f268SConrad Meyer /* ****************************************************************** 237f1f268SConrad Meyer * Common functions of New Generation Entropy library 337f1f268SConrad Meyer * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc. 437f1f268SConrad Meyer * 537f1f268SConrad Meyer * You can contact the author at : 637f1f268SConrad Meyer * - FSE+HUF source repository : https://github.com/Cyan4973/FiniteStateEntropy 737f1f268SConrad Meyer * - Public forum : https://groups.google.com/forum/#!forum/lz4c 837f1f268SConrad Meyer * 937f1f268SConrad Meyer * This source code is licensed under both the BSD-style license (found in the 1037f1f268SConrad Meyer * LICENSE file in the root directory of this source tree) and the GPLv2 (found 1137f1f268SConrad Meyer * in the COPYING file in the root directory of this source tree). 1237f1f268SConrad Meyer * You may select, at your option, one of the above-listed licenses. 1337f1f268SConrad Meyer ****************************************************************** */ 140c16b537SWarner Losh 150c16b537SWarner Losh /* ************************************* 160c16b537SWarner Losh * Dependencies 170c16b537SWarner Losh ***************************************/ 180c16b537SWarner Losh #include "mem.h" 190c16b537SWarner Losh #include "error_private.h" /* ERR_*, ERROR */ 200c16b537SWarner Losh #define FSE_STATIC_LINKING_ONLY /* FSE_MIN_TABLELOG */ 210c16b537SWarner Losh #include "fse.h" 220c16b537SWarner Losh #define HUF_STATIC_LINKING_ONLY /* HUF_TABLELOG_ABSOLUTEMAX */ 230c16b537SWarner Losh #include "huf.h" 240c16b537SWarner Losh 250c16b537SWarner Losh 260c16b537SWarner Losh /*=== Version ===*/ 270c16b537SWarner Losh unsigned FSE_versionNumber(void) { return FSE_VERSION_NUMBER; } 280c16b537SWarner Losh 290c16b537SWarner Losh 300c16b537SWarner Losh /*=== Error Management ===*/ 310c16b537SWarner Losh unsigned FSE_isError(size_t code) { return ERR_isError(code); } 320c16b537SWarner Losh const char* FSE_getErrorName(size_t code) { return ERR_getErrorName(code); } 330c16b537SWarner Losh 340c16b537SWarner Losh unsigned HUF_isError(size_t code) { return ERR_isError(code); } 350c16b537SWarner Losh const char* HUF_getErrorName(size_t code) { return ERR_getErrorName(code); } 360c16b537SWarner Losh 370c16b537SWarner Losh 380c16b537SWarner Losh /*-************************************************************** 390c16b537SWarner Losh * FSE NCount encoding-decoding 400c16b537SWarner Losh ****************************************************************/ 41*f7cd7fe5SConrad Meyer static U32 FSE_ctz(U32 val) 42*f7cd7fe5SConrad Meyer { 43*f7cd7fe5SConrad Meyer assert(val != 0); 44*f7cd7fe5SConrad Meyer { 45*f7cd7fe5SConrad Meyer # if defined(_MSC_VER) /* Visual */ 46*f7cd7fe5SConrad Meyer unsigned long r=0; 47*f7cd7fe5SConrad Meyer return _BitScanForward(&r, val) ? (unsigned)r : 0; 48*f7cd7fe5SConrad Meyer # elif defined(__GNUC__) && (__GNUC__ >= 3) /* GCC Intrinsic */ 49*f7cd7fe5SConrad Meyer return __builtin_ctz(val); 50*f7cd7fe5SConrad Meyer # elif defined(__ICCARM__) /* IAR Intrinsic */ 51*f7cd7fe5SConrad Meyer return __CTZ(val); 52*f7cd7fe5SConrad Meyer # else /* Software version */ 53*f7cd7fe5SConrad Meyer U32 count = 0; 54*f7cd7fe5SConrad Meyer while ((val & 1) == 0) { 55*f7cd7fe5SConrad Meyer val >>= 1; 56*f7cd7fe5SConrad Meyer ++count; 57*f7cd7fe5SConrad Meyer } 58*f7cd7fe5SConrad Meyer return count; 59*f7cd7fe5SConrad Meyer # endif 60*f7cd7fe5SConrad Meyer } 61*f7cd7fe5SConrad Meyer } 62*f7cd7fe5SConrad Meyer 63*f7cd7fe5SConrad Meyer FORCE_INLINE_TEMPLATE 64*f7cd7fe5SConrad Meyer size_t FSE_readNCount_body(short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr, 650c16b537SWarner Losh const void* headerBuffer, size_t hbSize) 660c16b537SWarner Losh { 670c16b537SWarner Losh const BYTE* const istart = (const BYTE*) headerBuffer; 680c16b537SWarner Losh const BYTE* const iend = istart + hbSize; 690c16b537SWarner Losh const BYTE* ip = istart; 700c16b537SWarner Losh int nbBits; 710c16b537SWarner Losh int remaining; 720c16b537SWarner Losh int threshold; 730c16b537SWarner Losh U32 bitStream; 740c16b537SWarner Losh int bitCount; 750c16b537SWarner Losh unsigned charnum = 0; 76*f7cd7fe5SConrad Meyer unsigned const maxSV1 = *maxSVPtr + 1; 770c16b537SWarner Losh int previous0 = 0; 780c16b537SWarner Losh 79*f7cd7fe5SConrad Meyer if (hbSize < 8) { 80*f7cd7fe5SConrad Meyer /* This function only works when hbSize >= 8 */ 81*f7cd7fe5SConrad Meyer char buffer[8] = {0}; 82*f7cd7fe5SConrad Meyer ZSTD_memcpy(buffer, headerBuffer, hbSize); 830f743729SConrad Meyer { size_t const countSize = FSE_readNCount(normalizedCounter, maxSVPtr, tableLogPtr, 840f743729SConrad Meyer buffer, sizeof(buffer)); 850f743729SConrad Meyer if (FSE_isError(countSize)) return countSize; 860f743729SConrad Meyer if (countSize > hbSize) return ERROR(corruption_detected); 870f743729SConrad Meyer return countSize; 880f743729SConrad Meyer } } 89*f7cd7fe5SConrad Meyer assert(hbSize >= 8); 900f743729SConrad Meyer 910f743729SConrad Meyer /* init */ 92*f7cd7fe5SConrad Meyer ZSTD_memset(normalizedCounter, 0, (*maxSVPtr+1) * sizeof(normalizedCounter[0])); /* all symbols not present in NCount have a frequency of 0 */ 930c16b537SWarner Losh bitStream = MEM_readLE32(ip); 940c16b537SWarner Losh nbBits = (bitStream & 0xF) + FSE_MIN_TABLELOG; /* extract tableLog */ 950c16b537SWarner Losh if (nbBits > FSE_TABLELOG_ABSOLUTE_MAX) return ERROR(tableLog_tooLarge); 960c16b537SWarner Losh bitStream >>= 4; 970c16b537SWarner Losh bitCount = 4; 980c16b537SWarner Losh *tableLogPtr = nbBits; 990c16b537SWarner Losh remaining = (1<<nbBits)+1; 1000c16b537SWarner Losh threshold = 1<<nbBits; 1010c16b537SWarner Losh nbBits++; 1020c16b537SWarner Losh 103*f7cd7fe5SConrad Meyer for (;;) { 1040c16b537SWarner Losh if (previous0) { 105*f7cd7fe5SConrad Meyer /* Count the number of repeats. Each time the 106*f7cd7fe5SConrad Meyer * 2-bit repeat code is 0b11 there is another 107*f7cd7fe5SConrad Meyer * repeat. 108*f7cd7fe5SConrad Meyer * Avoid UB by setting the high bit to 1. 109*f7cd7fe5SConrad Meyer */ 110*f7cd7fe5SConrad Meyer int repeats = FSE_ctz(~bitStream | 0x80000000) >> 1; 111*f7cd7fe5SConrad Meyer while (repeats >= 12) { 112*f7cd7fe5SConrad Meyer charnum += 3 * 12; 113*f7cd7fe5SConrad Meyer if (LIKELY(ip <= iend-7)) { 114*f7cd7fe5SConrad Meyer ip += 3; 1150c16b537SWarner Losh } else { 116*f7cd7fe5SConrad Meyer bitCount -= (int)(8 * (iend - 7 - ip)); 117*f7cd7fe5SConrad Meyer bitCount &= 31; 118*f7cd7fe5SConrad Meyer ip = iend - 4; 1190c16b537SWarner Losh } 120*f7cd7fe5SConrad Meyer bitStream = MEM_readLE32(ip) >> bitCount; 121*f7cd7fe5SConrad Meyer repeats = FSE_ctz(~bitStream | 0x80000000) >> 1; 122*f7cd7fe5SConrad Meyer } 123*f7cd7fe5SConrad Meyer charnum += 3 * repeats; 124*f7cd7fe5SConrad Meyer bitStream >>= 2 * repeats; 125*f7cd7fe5SConrad Meyer bitCount += 2 * repeats; 126*f7cd7fe5SConrad Meyer 127*f7cd7fe5SConrad Meyer /* Add the final repeat which isn't 0b11. */ 128*f7cd7fe5SConrad Meyer assert((bitStream & 3) < 3); 129*f7cd7fe5SConrad Meyer charnum += bitStream & 3; 1300c16b537SWarner Losh bitCount += 2; 131*f7cd7fe5SConrad Meyer 132*f7cd7fe5SConrad Meyer /* This is an error, but break and return an error 133*f7cd7fe5SConrad Meyer * at the end, because returning out of a loop makes 134*f7cd7fe5SConrad Meyer * it harder for the compiler to optimize. 135*f7cd7fe5SConrad Meyer */ 136*f7cd7fe5SConrad Meyer if (charnum >= maxSV1) break; 137*f7cd7fe5SConrad Meyer 138*f7cd7fe5SConrad Meyer /* We don't need to set the normalized count to 0 139*f7cd7fe5SConrad Meyer * because we already memset the whole buffer to 0. 140*f7cd7fe5SConrad Meyer */ 141*f7cd7fe5SConrad Meyer 142*f7cd7fe5SConrad Meyer if (LIKELY(ip <= iend-7) || (ip + (bitCount>>3) <= iend-4)) { 1430f743729SConrad Meyer assert((bitCount >> 3) <= 3); /* For first condition to work */ 1440c16b537SWarner Losh ip += bitCount>>3; 1450c16b537SWarner Losh bitCount &= 7; 1460c16b537SWarner Losh } else { 147*f7cd7fe5SConrad Meyer bitCount -= (int)(8 * (iend - 4 - ip)); 148*f7cd7fe5SConrad Meyer bitCount &= 31; 149*f7cd7fe5SConrad Meyer ip = iend - 4; 150*f7cd7fe5SConrad Meyer } 151*f7cd7fe5SConrad Meyer bitStream = MEM_readLE32(ip) >> bitCount; 152*f7cd7fe5SConrad Meyer } 153*f7cd7fe5SConrad Meyer { 154*f7cd7fe5SConrad Meyer int const max = (2*threshold-1) - remaining; 1550c16b537SWarner Losh int count; 1560c16b537SWarner Losh 1570c16b537SWarner Losh if ((bitStream & (threshold-1)) < (U32)max) { 1580c16b537SWarner Losh count = bitStream & (threshold-1); 1590c16b537SWarner Losh bitCount += nbBits-1; 1600c16b537SWarner Losh } else { 1610c16b537SWarner Losh count = bitStream & (2*threshold-1); 1620c16b537SWarner Losh if (count >= threshold) count -= max; 1630c16b537SWarner Losh bitCount += nbBits; 1640c16b537SWarner Losh } 1650c16b537SWarner Losh 1660c16b537SWarner Losh count--; /* extra accuracy */ 167*f7cd7fe5SConrad Meyer /* When it matters (small blocks), this is a 168*f7cd7fe5SConrad Meyer * predictable branch, because we don't use -1. 169*f7cd7fe5SConrad Meyer */ 170*f7cd7fe5SConrad Meyer if (count >= 0) { 171*f7cd7fe5SConrad Meyer remaining -= count; 172*f7cd7fe5SConrad Meyer } else { 173*f7cd7fe5SConrad Meyer assert(count == -1); 174*f7cd7fe5SConrad Meyer remaining += count; 175*f7cd7fe5SConrad Meyer } 1760c16b537SWarner Losh normalizedCounter[charnum++] = (short)count; 1770c16b537SWarner Losh previous0 = !count; 1780c16b537SWarner Losh 179*f7cd7fe5SConrad Meyer assert(threshold > 1); 180*f7cd7fe5SConrad Meyer if (remaining < threshold) { 181*f7cd7fe5SConrad Meyer /* This branch can be folded into the 182*f7cd7fe5SConrad Meyer * threshold update condition because we 183*f7cd7fe5SConrad Meyer * know that threshold > 1. 184*f7cd7fe5SConrad Meyer */ 185*f7cd7fe5SConrad Meyer if (remaining <= 1) break; 186*f7cd7fe5SConrad Meyer nbBits = BIT_highbit32(remaining) + 1; 187*f7cd7fe5SConrad Meyer threshold = 1 << (nbBits - 1); 188*f7cd7fe5SConrad Meyer } 189*f7cd7fe5SConrad Meyer if (charnum >= maxSV1) break; 190*f7cd7fe5SConrad Meyer 191*f7cd7fe5SConrad Meyer if (LIKELY(ip <= iend-7) || (ip + (bitCount>>3) <= iend-4)) { 1920c16b537SWarner Losh ip += bitCount>>3; 1930c16b537SWarner Losh bitCount &= 7; 1940c16b537SWarner Losh } else { 1950c16b537SWarner Losh bitCount -= (int)(8 * (iend - 4 - ip)); 196*f7cd7fe5SConrad Meyer bitCount &= 31; 1970c16b537SWarner Losh ip = iend - 4; 1980c16b537SWarner Losh } 199*f7cd7fe5SConrad Meyer bitStream = MEM_readLE32(ip) >> bitCount; 200*f7cd7fe5SConrad Meyer } } 2010c16b537SWarner Losh if (remaining != 1) return ERROR(corruption_detected); 202*f7cd7fe5SConrad Meyer /* Only possible when there are too many zeros. */ 203*f7cd7fe5SConrad Meyer if (charnum > maxSV1) return ERROR(maxSymbolValue_tooSmall); 2040c16b537SWarner Losh if (bitCount > 32) return ERROR(corruption_detected); 2050c16b537SWarner Losh *maxSVPtr = charnum-1; 2060c16b537SWarner Losh 2070c16b537SWarner Losh ip += (bitCount+7)>>3; 2080c16b537SWarner Losh return ip-istart; 2090c16b537SWarner Losh } 2100c16b537SWarner Losh 211*f7cd7fe5SConrad Meyer /* Avoids the FORCE_INLINE of the _body() function. */ 212*f7cd7fe5SConrad Meyer static size_t FSE_readNCount_body_default( 213*f7cd7fe5SConrad Meyer short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr, 214*f7cd7fe5SConrad Meyer const void* headerBuffer, size_t hbSize) 215*f7cd7fe5SConrad Meyer { 216*f7cd7fe5SConrad Meyer return FSE_readNCount_body(normalizedCounter, maxSVPtr, tableLogPtr, headerBuffer, hbSize); 217*f7cd7fe5SConrad Meyer } 218*f7cd7fe5SConrad Meyer 219*f7cd7fe5SConrad Meyer #if DYNAMIC_BMI2 220*f7cd7fe5SConrad Meyer TARGET_ATTRIBUTE("bmi2") static size_t FSE_readNCount_body_bmi2( 221*f7cd7fe5SConrad Meyer short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr, 222*f7cd7fe5SConrad Meyer const void* headerBuffer, size_t hbSize) 223*f7cd7fe5SConrad Meyer { 224*f7cd7fe5SConrad Meyer return FSE_readNCount_body(normalizedCounter, maxSVPtr, tableLogPtr, headerBuffer, hbSize); 225*f7cd7fe5SConrad Meyer } 226*f7cd7fe5SConrad Meyer #endif 227*f7cd7fe5SConrad Meyer 228*f7cd7fe5SConrad Meyer size_t FSE_readNCount_bmi2( 229*f7cd7fe5SConrad Meyer short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr, 230*f7cd7fe5SConrad Meyer const void* headerBuffer, size_t hbSize, int bmi2) 231*f7cd7fe5SConrad Meyer { 232*f7cd7fe5SConrad Meyer #if DYNAMIC_BMI2 233*f7cd7fe5SConrad Meyer if (bmi2) { 234*f7cd7fe5SConrad Meyer return FSE_readNCount_body_bmi2(normalizedCounter, maxSVPtr, tableLogPtr, headerBuffer, hbSize); 235*f7cd7fe5SConrad Meyer } 236*f7cd7fe5SConrad Meyer #endif 237*f7cd7fe5SConrad Meyer (void)bmi2; 238*f7cd7fe5SConrad Meyer return FSE_readNCount_body_default(normalizedCounter, maxSVPtr, tableLogPtr, headerBuffer, hbSize); 239*f7cd7fe5SConrad Meyer } 240*f7cd7fe5SConrad Meyer 241*f7cd7fe5SConrad Meyer size_t FSE_readNCount( 242*f7cd7fe5SConrad Meyer short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr, 243*f7cd7fe5SConrad Meyer const void* headerBuffer, size_t hbSize) 244*f7cd7fe5SConrad Meyer { 245*f7cd7fe5SConrad Meyer return FSE_readNCount_bmi2(normalizedCounter, maxSVPtr, tableLogPtr, headerBuffer, hbSize, /* bmi2 */ 0); 246*f7cd7fe5SConrad Meyer } 247*f7cd7fe5SConrad Meyer 2480c16b537SWarner Losh 2490c16b537SWarner Losh /*! HUF_readStats() : 2500c16b537SWarner Losh Read compact Huffman tree, saved by HUF_writeCTable(). 2510c16b537SWarner Losh `huffWeight` is destination buffer. 2520c16b537SWarner Losh `rankStats` is assumed to be a table of at least HUF_TABLELOG_MAX U32. 2530c16b537SWarner Losh @return : size read from `src` , or an error Code . 2540c16b537SWarner Losh Note : Needed by HUF_readCTable() and HUF_readDTableX?() . 2550c16b537SWarner Losh */ 2560c16b537SWarner Losh size_t HUF_readStats(BYTE* huffWeight, size_t hwSize, U32* rankStats, 2570c16b537SWarner Losh U32* nbSymbolsPtr, U32* tableLogPtr, 2580c16b537SWarner Losh const void* src, size_t srcSize) 2590c16b537SWarner Losh { 260*f7cd7fe5SConrad Meyer U32 wksp[HUF_READ_STATS_WORKSPACE_SIZE_U32]; 261*f7cd7fe5SConrad Meyer return HUF_readStats_wksp(huffWeight, hwSize, rankStats, nbSymbolsPtr, tableLogPtr, src, srcSize, wksp, sizeof(wksp), /* bmi2 */ 0); 262*f7cd7fe5SConrad Meyer } 263*f7cd7fe5SConrad Meyer 264*f7cd7fe5SConrad Meyer FORCE_INLINE_TEMPLATE size_t 265*f7cd7fe5SConrad Meyer HUF_readStats_body(BYTE* huffWeight, size_t hwSize, U32* rankStats, 266*f7cd7fe5SConrad Meyer U32* nbSymbolsPtr, U32* tableLogPtr, 267*f7cd7fe5SConrad Meyer const void* src, size_t srcSize, 268*f7cd7fe5SConrad Meyer void* workSpace, size_t wkspSize, 269*f7cd7fe5SConrad Meyer int bmi2) 270*f7cd7fe5SConrad Meyer { 2710c16b537SWarner Losh U32 weightTotal; 2720c16b537SWarner Losh const BYTE* ip = (const BYTE*) src; 2730c16b537SWarner Losh size_t iSize; 2740c16b537SWarner Losh size_t oSize; 2750c16b537SWarner Losh 2760c16b537SWarner Losh if (!srcSize) return ERROR(srcSize_wrong); 2770c16b537SWarner Losh iSize = ip[0]; 278*f7cd7fe5SConrad Meyer /* ZSTD_memset(huffWeight, 0, hwSize); *//* is not necessary, even though some analyzer complain ... */ 2790c16b537SWarner Losh 2800c16b537SWarner Losh if (iSize >= 128) { /* special header */ 2810c16b537SWarner Losh oSize = iSize - 127; 2820c16b537SWarner Losh iSize = ((oSize+1)/2); 2830c16b537SWarner Losh if (iSize+1 > srcSize) return ERROR(srcSize_wrong); 2840c16b537SWarner Losh if (oSize >= hwSize) return ERROR(corruption_detected); 2850c16b537SWarner Losh ip += 1; 2860c16b537SWarner Losh { U32 n; 2870c16b537SWarner Losh for (n=0; n<oSize; n+=2) { 2880c16b537SWarner Losh huffWeight[n] = ip[n/2] >> 4; 2890c16b537SWarner Losh huffWeight[n+1] = ip[n/2] & 15; 2900c16b537SWarner Losh } } } 2910c16b537SWarner Losh else { /* header compressed with FSE (normal case) */ 2920c16b537SWarner Losh if (iSize+1 > srcSize) return ERROR(srcSize_wrong); 293*f7cd7fe5SConrad Meyer /* max (hwSize-1) values decoded, as last one is implied */ 294*f7cd7fe5SConrad Meyer oSize = FSE_decompress_wksp_bmi2(huffWeight, hwSize-1, ip+1, iSize, 6, workSpace, wkspSize, bmi2); 2950c16b537SWarner Losh if (FSE_isError(oSize)) return oSize; 2960c16b537SWarner Losh } 2970c16b537SWarner Losh 2980c16b537SWarner Losh /* collect weight stats */ 299*f7cd7fe5SConrad Meyer ZSTD_memset(rankStats, 0, (HUF_TABLELOG_MAX + 1) * sizeof(U32)); 3000c16b537SWarner Losh weightTotal = 0; 3010c16b537SWarner Losh { U32 n; for (n=0; n<oSize; n++) { 3020c16b537SWarner Losh if (huffWeight[n] >= HUF_TABLELOG_MAX) return ERROR(corruption_detected); 3030c16b537SWarner Losh rankStats[huffWeight[n]]++; 3040c16b537SWarner Losh weightTotal += (1 << huffWeight[n]) >> 1; 3050c16b537SWarner Losh } } 3060c16b537SWarner Losh if (weightTotal == 0) return ERROR(corruption_detected); 3070c16b537SWarner Losh 3080c16b537SWarner Losh /* get last non-null symbol weight (implied, total must be 2^n) */ 3090c16b537SWarner Losh { U32 const tableLog = BIT_highbit32(weightTotal) + 1; 3100c16b537SWarner Losh if (tableLog > HUF_TABLELOG_MAX) return ERROR(corruption_detected); 3110c16b537SWarner Losh *tableLogPtr = tableLog; 3120c16b537SWarner Losh /* determine last weight */ 3130c16b537SWarner Losh { U32 const total = 1 << tableLog; 3140c16b537SWarner Losh U32 const rest = total - weightTotal; 3150c16b537SWarner Losh U32 const verif = 1 << BIT_highbit32(rest); 3160c16b537SWarner Losh U32 const lastWeight = BIT_highbit32(rest) + 1; 3170c16b537SWarner Losh if (verif != rest) return ERROR(corruption_detected); /* last value must be a clean power of 2 */ 3180c16b537SWarner Losh huffWeight[oSize] = (BYTE)lastWeight; 3190c16b537SWarner Losh rankStats[lastWeight]++; 3200c16b537SWarner Losh } } 3210c16b537SWarner Losh 3220c16b537SWarner Losh /* check tree construction validity */ 3230c16b537SWarner Losh if ((rankStats[1] < 2) || (rankStats[1] & 1)) return ERROR(corruption_detected); /* by construction : at least 2 elts of rank 1, must be even */ 3240c16b537SWarner Losh 3250c16b537SWarner Losh /* results */ 3260c16b537SWarner Losh *nbSymbolsPtr = (U32)(oSize+1); 3270c16b537SWarner Losh return iSize+1; 3280c16b537SWarner Losh } 329*f7cd7fe5SConrad Meyer 330*f7cd7fe5SConrad Meyer /* Avoids the FORCE_INLINE of the _body() function. */ 331*f7cd7fe5SConrad Meyer static size_t HUF_readStats_body_default(BYTE* huffWeight, size_t hwSize, U32* rankStats, 332*f7cd7fe5SConrad Meyer U32* nbSymbolsPtr, U32* tableLogPtr, 333*f7cd7fe5SConrad Meyer const void* src, size_t srcSize, 334*f7cd7fe5SConrad Meyer void* workSpace, size_t wkspSize) 335*f7cd7fe5SConrad Meyer { 336*f7cd7fe5SConrad Meyer return HUF_readStats_body(huffWeight, hwSize, rankStats, nbSymbolsPtr, tableLogPtr, src, srcSize, workSpace, wkspSize, 0); 337*f7cd7fe5SConrad Meyer } 338*f7cd7fe5SConrad Meyer 339*f7cd7fe5SConrad Meyer #if DYNAMIC_BMI2 340*f7cd7fe5SConrad Meyer static TARGET_ATTRIBUTE("bmi2") size_t HUF_readStats_body_bmi2(BYTE* huffWeight, size_t hwSize, U32* rankStats, 341*f7cd7fe5SConrad Meyer U32* nbSymbolsPtr, U32* tableLogPtr, 342*f7cd7fe5SConrad Meyer const void* src, size_t srcSize, 343*f7cd7fe5SConrad Meyer void* workSpace, size_t wkspSize) 344*f7cd7fe5SConrad Meyer { 345*f7cd7fe5SConrad Meyer return HUF_readStats_body(huffWeight, hwSize, rankStats, nbSymbolsPtr, tableLogPtr, src, srcSize, workSpace, wkspSize, 1); 346*f7cd7fe5SConrad Meyer } 347*f7cd7fe5SConrad Meyer #endif 348*f7cd7fe5SConrad Meyer 349*f7cd7fe5SConrad Meyer size_t HUF_readStats_wksp(BYTE* huffWeight, size_t hwSize, U32* rankStats, 350*f7cd7fe5SConrad Meyer U32* nbSymbolsPtr, U32* tableLogPtr, 351*f7cd7fe5SConrad Meyer const void* src, size_t srcSize, 352*f7cd7fe5SConrad Meyer void* workSpace, size_t wkspSize, 353*f7cd7fe5SConrad Meyer int bmi2) 354*f7cd7fe5SConrad Meyer { 355*f7cd7fe5SConrad Meyer #if DYNAMIC_BMI2 356*f7cd7fe5SConrad Meyer if (bmi2) { 357*f7cd7fe5SConrad Meyer return HUF_readStats_body_bmi2(huffWeight, hwSize, rankStats, nbSymbolsPtr, tableLogPtr, src, srcSize, workSpace, wkspSize); 358*f7cd7fe5SConrad Meyer } 359*f7cd7fe5SConrad Meyer #endif 360*f7cd7fe5SConrad Meyer (void)bmi2; 361*f7cd7fe5SConrad Meyer return HUF_readStats_body_default(huffWeight, hwSize, rankStats, nbSymbolsPtr, tableLogPtr, src, srcSize, workSpace, wkspSize); 362*f7cd7fe5SConrad Meyer } 363