^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * FSE : Finite State Entropy encoder
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (C) 2013-2015, Yann Collet.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Redistribution and use in source and binary forms, with or without
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * modification, are permitted provided that the following conditions are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * met:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * * Redistributions of source code must retain the above copyright
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * notice, this list of conditions and the following disclaimer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * * Redistributions in binary form must reproduce the above
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * copyright notice, this list of conditions and the following disclaimer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * in the documentation and/or other materials provided with the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * distribution.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * This program is free software; you can redistribute it and/or modify it under
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * the terms of the GNU General Public License version 2 as published by the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * Free Software Foundation. This program is dual-licensed; you may select
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) * either version 2 of the GNU General Public License ("GPL") or BSD license
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) * ("BSD").
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) * You can contact the author at :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) * - Source repository : https://github.com/Cyan4973/FiniteStateEntropy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) /* **************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) * Compiler specifics
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) ****************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define FORCE_INLINE static __always_inline
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) /* **************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) * Includes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) ****************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #include "bitstream.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #include "fse.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #include <linux/compiler.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #include <linux/math64.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #include <linux/string.h> /* memcpy, memset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) /* **************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) * Error Management
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) ****************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #define FSE_STATIC_ASSERT(c) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) enum { FSE_static_assert = 1 / (int)(!!(c)) }; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) } /* use only *after* variable declarations */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) /* **************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) * Templates
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) ****************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) designed to be included
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) for type-specific functions (template emulation in C)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) Objective is to write these functions only once, for improved maintenance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) /* safety checks */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) #ifndef FSE_FUNCTION_EXTENSION
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) #error "FSE_FUNCTION_EXTENSION must be defined"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #ifndef FSE_FUNCTION_TYPE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) #error "FSE_FUNCTION_TYPE must be defined"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) /* Function names */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) #define FSE_CAT(X, Y) X##Y
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) #define FSE_FUNCTION_NAME(X, Y) FSE_CAT(X, Y)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) #define FSE_TYPE_NAME(X, Y) FSE_CAT(X, Y)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) /* Function templates */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) /* FSE_buildCTable_wksp() :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) * Same as FSE_buildCTable(), but using an externally allocated scratch buffer (`workSpace`).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) * wkspSize should be sized to handle worst case situation, which is `1<<max_tableLog * sizeof(FSE_FUNCTION_TYPE)`
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) * workSpace must also be properly aligned with FSE_FUNCTION_TYPE requirements
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) size_t FSE_buildCTable_wksp(FSE_CTable *ct, const short *normalizedCounter, unsigned maxSymbolValue, unsigned tableLog, void *workspace, size_t workspaceSize)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) U32 const tableSize = 1 << tableLog;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) U32 const tableMask = tableSize - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) void *const ptr = ct;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) U16 *const tableU16 = ((U16 *)ptr) + 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) void *const FSCT = ((U32 *)ptr) + 1 /* header */ + (tableLog ? tableSize >> 1 : 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) FSE_symbolCompressionTransform *const symbolTT = (FSE_symbolCompressionTransform *)(FSCT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) U32 const step = FSE_TABLESTEP(tableSize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) U32 highThreshold = tableSize - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) U32 *cumul;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) FSE_FUNCTION_TYPE *tableSymbol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) size_t spaceUsed32 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) cumul = (U32 *)workspace + spaceUsed32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) spaceUsed32 += FSE_MAX_SYMBOL_VALUE + 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) tableSymbol = (FSE_FUNCTION_TYPE *)((U32 *)workspace + spaceUsed32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) spaceUsed32 += ALIGN(sizeof(FSE_FUNCTION_TYPE) * ((size_t)1 << tableLog), sizeof(U32)) >> 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) if ((spaceUsed32 << 2) > workspaceSize)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) return ERROR(tableLog_tooLarge);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) workspace = (U32 *)workspace + spaceUsed32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) workspaceSize -= (spaceUsed32 << 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) /* CTable header */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) tableU16[-2] = (U16)tableLog;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) tableU16[-1] = (U16)maxSymbolValue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) /* For explanations on how to distribute symbol values over the table :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) * http://fastcompression.blogspot.fr/2014/02/fse-distributing-symbol-values.html */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) /* symbol start positions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) U32 u;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) cumul[0] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) for (u = 1; u <= maxSymbolValue + 1; u++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) if (normalizedCounter[u - 1] == -1) { /* Low proba symbol */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) cumul[u] = cumul[u - 1] + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) tableSymbol[highThreshold--] = (FSE_FUNCTION_TYPE)(u - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) cumul[u] = cumul[u - 1] + normalizedCounter[u - 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) cumul[maxSymbolValue + 1] = tableSize + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) /* Spread symbols */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) U32 position = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) U32 symbol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) for (symbol = 0; symbol <= maxSymbolValue; symbol++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) int nbOccurences;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) for (nbOccurences = 0; nbOccurences < normalizedCounter[symbol]; nbOccurences++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) tableSymbol[position] = (FSE_FUNCTION_TYPE)symbol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) position = (position + step) & tableMask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) while (position > highThreshold)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) position = (position + step) & tableMask; /* Low proba area */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) if (position != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) return ERROR(GENERIC); /* Must have gone through all positions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) /* Build table */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) U32 u;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) for (u = 0; u < tableSize; u++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) FSE_FUNCTION_TYPE s = tableSymbol[u]; /* note : static analyzer may not understand tableSymbol is properly initialized */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) tableU16[cumul[s]++] = (U16)(tableSize + u); /* TableU16 : sorted by symbol order; gives next state value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) /* Build Symbol Transformation Table */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) unsigned total = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) unsigned s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) for (s = 0; s <= maxSymbolValue; s++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) switch (normalizedCounter[s]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) case 0: break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) case -1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) symbolTT[s].deltaNbBits = (tableLog << 16) - (1 << tableLog);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) symbolTT[s].deltaFindState = total - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) total++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) default: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) U32 const maxBitsOut = tableLog - BIT_highbit32(normalizedCounter[s] - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) U32 const minStatePlus = normalizedCounter[s] << maxBitsOut;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) symbolTT[s].deltaNbBits = (maxBitsOut << 16) - minStatePlus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) symbolTT[s].deltaFindState = total - normalizedCounter[s];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) total += normalizedCounter[s];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) /*-**************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) * FSE NCount encoding-decoding
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) ****************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) size_t FSE_NCountWriteBound(unsigned maxSymbolValue, unsigned tableLog)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) size_t const maxHeaderSize = (((maxSymbolValue + 1) * tableLog) >> 3) + 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) return maxSymbolValue ? maxHeaderSize : FSE_NCOUNTBOUND; /* maxSymbolValue==0 ? use default */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) static size_t FSE_writeNCount_generic(void *header, size_t headerBufferSize, const short *normalizedCounter, unsigned maxSymbolValue, unsigned tableLog,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) unsigned writeIsSafe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) BYTE *const ostart = (BYTE *)header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) BYTE *out = ostart;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) BYTE *const oend = ostart + headerBufferSize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) int nbBits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) const int tableSize = 1 << tableLog;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) int remaining;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) int threshold;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) U32 bitStream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) int bitCount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) unsigned charnum = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) int previous0 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) bitStream = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) bitCount = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) /* Table Size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) bitStream += (tableLog - FSE_MIN_TABLELOG) << bitCount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) bitCount += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) /* Init */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) remaining = tableSize + 1; /* +1 for extra accuracy */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) threshold = tableSize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) nbBits = tableLog + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) while (remaining > 1) { /* stops at 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) if (previous0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) unsigned start = charnum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) while (!normalizedCounter[charnum])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) charnum++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) while (charnum >= start + 24) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) start += 24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) bitStream += 0xFFFFU << bitCount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) if ((!writeIsSafe) && (out > oend - 2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) return ERROR(dstSize_tooSmall); /* Buffer overflow */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) out[0] = (BYTE)bitStream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) out[1] = (BYTE)(bitStream >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) out += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) bitStream >>= 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) while (charnum >= start + 3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) start += 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) bitStream += 3 << bitCount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) bitCount += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) bitStream += (charnum - start) << bitCount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) bitCount += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) if (bitCount > 16) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) if ((!writeIsSafe) && (out > oend - 2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) return ERROR(dstSize_tooSmall); /* Buffer overflow */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) out[0] = (BYTE)bitStream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) out[1] = (BYTE)(bitStream >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) out += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) bitStream >>= 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) bitCount -= 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) int count = normalizedCounter[charnum++];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) int const max = (2 * threshold - 1) - remaining;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) remaining -= count < 0 ? -count : count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) count++; /* +1 for extra accuracy */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) if (count >= threshold)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) count += max; /* [0..max[ [max..threshold[ (...) [threshold+max 2*threshold[ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) bitStream += count << bitCount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) bitCount += nbBits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) bitCount -= (count < max);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) previous0 = (count == 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) if (remaining < 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) return ERROR(GENERIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) while (remaining < threshold)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) nbBits--, threshold >>= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) if (bitCount > 16) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) if ((!writeIsSafe) && (out > oend - 2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) return ERROR(dstSize_tooSmall); /* Buffer overflow */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) out[0] = (BYTE)bitStream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) out[1] = (BYTE)(bitStream >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) out += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) bitStream >>= 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) bitCount -= 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) /* flush remaining bitStream */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) if ((!writeIsSafe) && (out > oend - 2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) return ERROR(dstSize_tooSmall); /* Buffer overflow */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) out[0] = (BYTE)bitStream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) out[1] = (BYTE)(bitStream >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) out += (bitCount + 7) / 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) if (charnum > maxSymbolValue + 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) return ERROR(GENERIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) return (out - ostart);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) size_t FSE_writeNCount(void *buffer, size_t bufferSize, const short *normalizedCounter, unsigned maxSymbolValue, unsigned tableLog)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) if (tableLog > FSE_MAX_TABLELOG)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) return ERROR(tableLog_tooLarge); /* Unsupported */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) if (tableLog < FSE_MIN_TABLELOG)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) return ERROR(GENERIC); /* Unsupported */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) if (bufferSize < FSE_NCountWriteBound(maxSymbolValue, tableLog))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) return FSE_writeNCount_generic(buffer, bufferSize, normalizedCounter, maxSymbolValue, tableLog, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) return FSE_writeNCount_generic(buffer, bufferSize, normalizedCounter, maxSymbolValue, tableLog, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) /*-**************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) * Counting histogram
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) ****************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) /*! FSE_count_simple
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) This function counts byte values within `src`, and store the histogram into table `count`.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) It doesn't use any additional memory.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) But this function is unsafe : it doesn't check that all values within `src` can fit into `count`.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) For this reason, prefer using a table `count` with 256 elements.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) @return : count of most numerous element
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) size_t FSE_count_simple(unsigned *count, unsigned *maxSymbolValuePtr, const void *src, size_t srcSize)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) const BYTE *ip = (const BYTE *)src;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) const BYTE *const end = ip + srcSize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) unsigned maxSymbolValue = *maxSymbolValuePtr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) unsigned max = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) memset(count, 0, (maxSymbolValue + 1) * sizeof(*count));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) if (srcSize == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) *maxSymbolValuePtr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) while (ip < end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) count[*ip++]++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) while (!count[maxSymbolValue])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) maxSymbolValue--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) *maxSymbolValuePtr = maxSymbolValue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) U32 s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) for (s = 0; s <= maxSymbolValue; s++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) if (count[s] > max)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) max = count[s];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) return (size_t)max;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) /* FSE_count_parallel_wksp() :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) * Same as FSE_count_parallel(), but using an externally provided scratch buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) * `workSpace` size must be a minimum of `1024 * sizeof(unsigned)`` */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) static size_t FSE_count_parallel_wksp(unsigned *count, unsigned *maxSymbolValuePtr, const void *source, size_t sourceSize, unsigned checkMax,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) unsigned *const workSpace)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) const BYTE *ip = (const BYTE *)source;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) const BYTE *const iend = ip + sourceSize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) unsigned maxSymbolValue = *maxSymbolValuePtr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) unsigned max = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) U32 *const Counting1 = workSpace;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) U32 *const Counting2 = Counting1 + 256;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) U32 *const Counting3 = Counting2 + 256;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) U32 *const Counting4 = Counting3 + 256;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) memset(Counting1, 0, 4 * 256 * sizeof(unsigned));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) /* safety checks */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) if (!sourceSize) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) memset(count, 0, maxSymbolValue + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) *maxSymbolValuePtr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) if (!maxSymbolValue)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) maxSymbolValue = 255; /* 0 == default */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) /* by stripes of 16 bytes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) U32 cached = ZSTD_read32(ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) ip += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) while (ip < iend - 15) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) U32 c = cached;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) cached = ZSTD_read32(ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) ip += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) Counting1[(BYTE)c]++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) Counting2[(BYTE)(c >> 8)]++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) Counting3[(BYTE)(c >> 16)]++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) Counting4[c >> 24]++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) c = cached;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) cached = ZSTD_read32(ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) ip += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) Counting1[(BYTE)c]++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) Counting2[(BYTE)(c >> 8)]++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) Counting3[(BYTE)(c >> 16)]++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) Counting4[c >> 24]++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) c = cached;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) cached = ZSTD_read32(ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) ip += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) Counting1[(BYTE)c]++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) Counting2[(BYTE)(c >> 8)]++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) Counting3[(BYTE)(c >> 16)]++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) Counting4[c >> 24]++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) c = cached;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) cached = ZSTD_read32(ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) ip += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) Counting1[(BYTE)c]++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) Counting2[(BYTE)(c >> 8)]++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) Counting3[(BYTE)(c >> 16)]++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) Counting4[c >> 24]++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) ip -= 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) /* finish last symbols */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) while (ip < iend)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) Counting1[*ip++]++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) if (checkMax) { /* verify stats will fit into destination table */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) U32 s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) for (s = 255; s > maxSymbolValue; s--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) Counting1[s] += Counting2[s] + Counting3[s] + Counting4[s];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) if (Counting1[s])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) return ERROR(maxSymbolValue_tooSmall);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) U32 s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) for (s = 0; s <= maxSymbolValue; s++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) count[s] = Counting1[s] + Counting2[s] + Counting3[s] + Counting4[s];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) if (count[s] > max)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) max = count[s];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) while (!count[maxSymbolValue])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) maxSymbolValue--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) *maxSymbolValuePtr = maxSymbolValue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) return (size_t)max;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) /* FSE_countFast_wksp() :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) * Same as FSE_countFast(), but using an externally provided scratch buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) * `workSpace` size must be table of >= `1024` unsigned */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) size_t FSE_countFast_wksp(unsigned *count, unsigned *maxSymbolValuePtr, const void *source, size_t sourceSize, unsigned *workSpace)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) if (sourceSize < 1500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) return FSE_count_simple(count, maxSymbolValuePtr, source, sourceSize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) return FSE_count_parallel_wksp(count, maxSymbolValuePtr, source, sourceSize, 0, workSpace);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) /* FSE_count_wksp() :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) * Same as FSE_count(), but using an externally provided scratch buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) * `workSpace` size must be table of >= `1024` unsigned */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) size_t FSE_count_wksp(unsigned *count, unsigned *maxSymbolValuePtr, const void *source, size_t sourceSize, unsigned *workSpace)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) if (*maxSymbolValuePtr < 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) return FSE_count_parallel_wksp(count, maxSymbolValuePtr, source, sourceSize, 1, workSpace);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) *maxSymbolValuePtr = 255;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) return FSE_countFast_wksp(count, maxSymbolValuePtr, source, sourceSize, workSpace);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) /*-**************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) * FSE Compression Code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) ****************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) /*! FSE_sizeof_CTable() :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) FSE_CTable is a variable size structure which contains :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) `U16 tableLog;`
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) `U16 maxSymbolValue;`
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) `U16 nextStateNumber[1 << tableLog];` // This size is variable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) `FSE_symbolCompressionTransform symbolTT[maxSymbolValue+1];` // This size is variable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) Allocation is manual (C standard does not support variable-size structures).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) size_t FSE_sizeof_CTable(unsigned maxSymbolValue, unsigned tableLog)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) if (tableLog > FSE_MAX_TABLELOG)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) return ERROR(tableLog_tooLarge);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) return FSE_CTABLE_SIZE_U32(tableLog, maxSymbolValue) * sizeof(U32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) /* provides the minimum logSize to safely represent a distribution */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) static unsigned FSE_minTableLog(size_t srcSize, unsigned maxSymbolValue)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) U32 minBitsSrc = BIT_highbit32((U32)(srcSize - 1)) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) U32 minBitsSymbols = BIT_highbit32(maxSymbolValue) + 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) U32 minBits = minBitsSrc < minBitsSymbols ? minBitsSrc : minBitsSymbols;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) return minBits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) unsigned FSE_optimalTableLog_internal(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue, unsigned minus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) U32 maxBitsSrc = BIT_highbit32((U32)(srcSize - 1)) - minus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) U32 tableLog = maxTableLog;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) U32 minBits = FSE_minTableLog(srcSize, maxSymbolValue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) if (tableLog == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) tableLog = FSE_DEFAULT_TABLELOG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) if (maxBitsSrc < tableLog)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) tableLog = maxBitsSrc; /* Accuracy can be reduced */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) if (minBits > tableLog)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) tableLog = minBits; /* Need a minimum to safely represent all symbol values */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) if (tableLog < FSE_MIN_TABLELOG)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) tableLog = FSE_MIN_TABLELOG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) if (tableLog > FSE_MAX_TABLELOG)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) tableLog = FSE_MAX_TABLELOG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) return tableLog;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) unsigned FSE_optimalTableLog(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) return FSE_optimalTableLog_internal(maxTableLog, srcSize, maxSymbolValue, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) /* Secondary normalization method.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) To be used when primary method fails. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) static size_t FSE_normalizeM2(short *norm, U32 tableLog, const unsigned *count, size_t total, U32 maxSymbolValue)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) short const NOT_YET_ASSIGNED = -2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) U32 s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) U32 distributed = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) U32 ToDistribute;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) /* Init */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) U32 const lowThreshold = (U32)(total >> tableLog);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) U32 lowOne = (U32)((total * 3) >> (tableLog + 1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) for (s = 0; s <= maxSymbolValue; s++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) if (count[s] == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) norm[s] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) if (count[s] <= lowThreshold) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) norm[s] = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) distributed++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) total -= count[s];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) if (count[s] <= lowOne) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) norm[s] = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) distributed++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) total -= count[s];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) norm[s] = NOT_YET_ASSIGNED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) ToDistribute = (1 << tableLog) - distributed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) if ((total / ToDistribute) > lowOne) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) /* risk of rounding to zero */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) lowOne = (U32)((total * 3) / (ToDistribute * 2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) for (s = 0; s <= maxSymbolValue; s++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) if ((norm[s] == NOT_YET_ASSIGNED) && (count[s] <= lowOne)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) norm[s] = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) distributed++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) total -= count[s];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) ToDistribute = (1 << tableLog) - distributed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) if (distributed == maxSymbolValue + 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) /* all values are pretty poor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) probably incompressible data (should have already been detected);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) find max, then give all remaining points to max */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) U32 maxV = 0, maxC = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) for (s = 0; s <= maxSymbolValue; s++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) if (count[s] > maxC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) maxV = s, maxC = count[s];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) norm[maxV] += (short)ToDistribute;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) if (total == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) /* all of the symbols were low enough for the lowOne or lowThreshold */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) for (s = 0; ToDistribute > 0; s = (s + 1) % (maxSymbolValue + 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) if (norm[s] > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) ToDistribute--, norm[s]++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) U64 const vStepLog = 62 - tableLog;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) U64 const mid = (1ULL << (vStepLog - 1)) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) U64 const rStep = div_u64((((U64)1 << vStepLog) * ToDistribute) + mid, (U32)total); /* scale on remaining */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) U64 tmpTotal = mid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) for (s = 0; s <= maxSymbolValue; s++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) if (norm[s] == NOT_YET_ASSIGNED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) U64 const end = tmpTotal + (count[s] * rStep);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) U32 const sStart = (U32)(tmpTotal >> vStepLog);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) U32 const sEnd = (U32)(end >> vStepLog);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) U32 const weight = sEnd - sStart;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) if (weight < 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) return ERROR(GENERIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) norm[s] = (short)weight;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) tmpTotal = end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) size_t FSE_normalizeCount(short *normalizedCounter, unsigned tableLog, const unsigned *count, size_t total, unsigned maxSymbolValue)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) /* Sanity checks */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) if (tableLog == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) tableLog = FSE_DEFAULT_TABLELOG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) if (tableLog < FSE_MIN_TABLELOG)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) return ERROR(GENERIC); /* Unsupported size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) if (tableLog > FSE_MAX_TABLELOG)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) return ERROR(tableLog_tooLarge); /* Unsupported size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) if (tableLog < FSE_minTableLog(total, maxSymbolValue))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) return ERROR(GENERIC); /* Too small tableLog, compression potentially impossible */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) U32 const rtbTable[] = {0, 473195, 504333, 520860, 550000, 700000, 750000, 830000};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) U64 const scale = 62 - tableLog;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) U64 const step = div_u64((U64)1 << 62, (U32)total); /* <== here, one division ! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) U64 const vStep = 1ULL << (scale - 20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) int stillToDistribute = 1 << tableLog;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) unsigned s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) unsigned largest = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) short largestP = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) U32 lowThreshold = (U32)(total >> tableLog);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) for (s = 0; s <= maxSymbolValue; s++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) if (count[s] == total)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) return 0; /* rle special case */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) if (count[s] == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) normalizedCounter[s] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) if (count[s] <= lowThreshold) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) normalizedCounter[s] = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) stillToDistribute--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) short proba = (short)((count[s] * step) >> scale);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) if (proba < 8) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) U64 restToBeat = vStep * rtbTable[proba];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) proba += (count[s] * step) - ((U64)proba << scale) > restToBeat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) if (proba > largestP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) largestP = proba, largest = s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) normalizedCounter[s] = proba;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) stillToDistribute -= proba;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) if (-stillToDistribute >= (normalizedCounter[largest] >> 1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) /* corner case, need another normalization method */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) size_t const errorCode = FSE_normalizeM2(normalizedCounter, tableLog, count, total, maxSymbolValue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) if (FSE_isError(errorCode))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) return errorCode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) normalizedCounter[largest] += (short)stillToDistribute;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) return tableLog;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) /* fake FSE_CTable, for raw (uncompressed) input */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) size_t FSE_buildCTable_raw(FSE_CTable *ct, unsigned nbBits)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) const unsigned tableSize = 1 << nbBits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) const unsigned tableMask = tableSize - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) const unsigned maxSymbolValue = tableMask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) void *const ptr = ct;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) U16 *const tableU16 = ((U16 *)ptr) + 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) void *const FSCT = ((U32 *)ptr) + 1 /* header */ + (tableSize >> 1); /* assumption : tableLog >= 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) FSE_symbolCompressionTransform *const symbolTT = (FSE_symbolCompressionTransform *)(FSCT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) unsigned s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) /* Sanity checks */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) if (nbBits < 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) return ERROR(GENERIC); /* min size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) /* header */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) tableU16[-2] = (U16)nbBits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) tableU16[-1] = (U16)maxSymbolValue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) /* Build table */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) for (s = 0; s < tableSize; s++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) tableU16[s] = (U16)(tableSize + s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) /* Build Symbol Transformation Table */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) const U32 deltaNbBits = (nbBits << 16) - (1 << nbBits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) for (s = 0; s <= maxSymbolValue; s++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) symbolTT[s].deltaNbBits = deltaNbBits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) symbolTT[s].deltaFindState = s - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) /* fake FSE_CTable, for rle input (always same symbol) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) size_t FSE_buildCTable_rle(FSE_CTable *ct, BYTE symbolValue)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) void *ptr = ct;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) U16 *tableU16 = ((U16 *)ptr) + 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) void *FSCTptr = (U32 *)ptr + 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) FSE_symbolCompressionTransform *symbolTT = (FSE_symbolCompressionTransform *)FSCTptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) /* header */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) tableU16[-2] = (U16)0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) tableU16[-1] = (U16)symbolValue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) /* Build table */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) tableU16[0] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) tableU16[1] = 0; /* just in case */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) /* Build Symbol Transformation Table */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) symbolTT[symbolValue].deltaNbBits = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) symbolTT[symbolValue].deltaFindState = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 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)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) const BYTE *const istart = (const BYTE *)src;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) const BYTE *const iend = istart + srcSize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) const BYTE *ip = iend;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) BIT_CStream_t bitC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) FSE_CState_t CState1, CState2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) /* init */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) if (srcSize <= 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) size_t const initError = BIT_initCStream(&bitC, dst, dstSize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) if (FSE_isError(initError))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) return 0; /* not enough space available to write a bitstream */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) #define FSE_FLUSHBITS(s) (fast ? BIT_flushBitsFast(s) : BIT_flushBits(s))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) if (srcSize & 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) FSE_initCState2(&CState1, ct, *--ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) FSE_initCState2(&CState2, ct, *--ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) FSE_encodeSymbol(&bitC, &CState1, *--ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) FSE_FLUSHBITS(&bitC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) FSE_initCState2(&CState2, ct, *--ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) FSE_initCState2(&CState1, ct, *--ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) /* join to mod 4 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) srcSize -= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) if ((sizeof(bitC.bitContainer) * 8 > FSE_MAX_TABLELOG * 4 + 7) && (srcSize & 2)) { /* test bit 2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) FSE_encodeSymbol(&bitC, &CState2, *--ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) FSE_encodeSymbol(&bitC, &CState1, *--ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) FSE_FLUSHBITS(&bitC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) /* 2 or 4 encoding per loop */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) while (ip > istart) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) FSE_encodeSymbol(&bitC, &CState2, *--ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) if (sizeof(bitC.bitContainer) * 8 < FSE_MAX_TABLELOG * 2 + 7) /* this test must be static */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) FSE_FLUSHBITS(&bitC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) FSE_encodeSymbol(&bitC, &CState1, *--ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) if (sizeof(bitC.bitContainer) * 8 > FSE_MAX_TABLELOG * 4 + 7) { /* this test must be static */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) FSE_encodeSymbol(&bitC, &CState2, *--ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) FSE_encodeSymbol(&bitC, &CState1, *--ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) FSE_FLUSHBITS(&bitC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) FSE_flushCState(&bitC, &CState2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) FSE_flushCState(&bitC, &CState1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) return BIT_closeCStream(&bitC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) size_t FSE_compress_usingCTable(void *dst, size_t dstSize, const void *src, size_t srcSize, const FSE_CTable *ct)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) unsigned const fast = (dstSize >= FSE_BLOCKBOUND(srcSize));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) if (fast)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) return FSE_compress_usingCTable_generic(dst, dstSize, src, srcSize, ct, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) return FSE_compress_usingCTable_generic(dst, dstSize, src, srcSize, ct, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) size_t FSE_compressBound(size_t size) { return FSE_COMPRESSBOUND(size); }