Path: blob/main/sys/contrib/zstd/lib/compress/hist.c
48378 views
/* ******************************************************************1* hist : Histogram functions2* part of Finite State Entropy project3* Copyright (c) Yann Collet, Facebook, Inc.4*5* You can contact the author at :6* - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy7* - Public forum : https://groups.google.com/forum/#!forum/lz4c8*9* This source code is licensed under both the BSD-style license (found in the10* LICENSE file in the root directory of this source tree) and the GPLv2 (found11* in the COPYING file in the root directory of this source tree).12* You may select, at your option, one of the above-listed licenses.13****************************************************************** */1415/* --- dependencies --- */16#include "../common/mem.h" /* U32, BYTE, etc. */17#include "../common/debug.h" /* assert, DEBUGLOG */18#include "../common/error_private.h" /* ERROR */19#include "hist.h"202122/* --- Error management --- */23unsigned HIST_isError(size_t code) { return ERR_isError(code); }2425/*-**************************************************************26* Histogram functions27****************************************************************/28unsigned HIST_count_simple(unsigned* count, unsigned* maxSymbolValuePtr,29const void* src, size_t srcSize)30{31const BYTE* ip = (const BYTE*)src;32const BYTE* const end = ip + srcSize;33unsigned maxSymbolValue = *maxSymbolValuePtr;34unsigned largestCount=0;3536ZSTD_memset(count, 0, (maxSymbolValue+1) * sizeof(*count));37if (srcSize==0) { *maxSymbolValuePtr = 0; return 0; }3839while (ip<end) {40assert(*ip <= maxSymbolValue);41count[*ip++]++;42}4344while (!count[maxSymbolValue]) maxSymbolValue--;45*maxSymbolValuePtr = maxSymbolValue;4647{ U32 s;48for (s=0; s<=maxSymbolValue; s++)49if (count[s] > largestCount) largestCount = count[s];50}5152return largestCount;53}5455typedef enum { trustInput, checkMaxSymbolValue } HIST_checkInput_e;5657/* HIST_count_parallel_wksp() :58* store histogram into 4 intermediate tables, recombined at the end.59* this design makes better use of OoO cpus,60* and is noticeably faster when some values are heavily repeated.61* But it needs some additional workspace for intermediate tables.62* `workSpace` must be a U32 table of size >= HIST_WKSP_SIZE_U32.63* @return : largest histogram frequency,64* or an error code (notably when histogram's alphabet is larger than *maxSymbolValuePtr) */65static size_t HIST_count_parallel_wksp(66unsigned* count, unsigned* maxSymbolValuePtr,67const void* source, size_t sourceSize,68HIST_checkInput_e check,69U32* const workSpace)70{71const BYTE* ip = (const BYTE*)source;72const BYTE* const iend = ip+sourceSize;73size_t const countSize = (*maxSymbolValuePtr + 1) * sizeof(*count);74unsigned max=0;75U32* const Counting1 = workSpace;76U32* const Counting2 = Counting1 + 256;77U32* const Counting3 = Counting2 + 256;78U32* const Counting4 = Counting3 + 256;7980/* safety checks */81assert(*maxSymbolValuePtr <= 255);82if (!sourceSize) {83ZSTD_memset(count, 0, countSize);84*maxSymbolValuePtr = 0;85return 0;86}87ZSTD_memset(workSpace, 0, 4*256*sizeof(unsigned));8889/* by stripes of 16 bytes */90{ U32 cached = MEM_read32(ip); ip += 4;91while (ip < iend-15) {92U32 c = cached; cached = MEM_read32(ip); ip += 4;93Counting1[(BYTE) c ]++;94Counting2[(BYTE)(c>>8) ]++;95Counting3[(BYTE)(c>>16)]++;96Counting4[ c>>24 ]++;97c = cached; cached = MEM_read32(ip); ip += 4;98Counting1[(BYTE) c ]++;99Counting2[(BYTE)(c>>8) ]++;100Counting3[(BYTE)(c>>16)]++;101Counting4[ c>>24 ]++;102c = cached; cached = MEM_read32(ip); ip += 4;103Counting1[(BYTE) c ]++;104Counting2[(BYTE)(c>>8) ]++;105Counting3[(BYTE)(c>>16)]++;106Counting4[ c>>24 ]++;107c = cached; cached = MEM_read32(ip); ip += 4;108Counting1[(BYTE) c ]++;109Counting2[(BYTE)(c>>8) ]++;110Counting3[(BYTE)(c>>16)]++;111Counting4[ c>>24 ]++;112}113ip-=4;114}115116/* finish last symbols */117while (ip<iend) Counting1[*ip++]++;118119{ U32 s;120for (s=0; s<256; s++) {121Counting1[s] += Counting2[s] + Counting3[s] + Counting4[s];122if (Counting1[s] > max) max = Counting1[s];123} }124125{ unsigned maxSymbolValue = 255;126while (!Counting1[maxSymbolValue]) maxSymbolValue--;127if (check && maxSymbolValue > *maxSymbolValuePtr) return ERROR(maxSymbolValue_tooSmall);128*maxSymbolValuePtr = maxSymbolValue;129ZSTD_memmove(count, Counting1, countSize); /* in case count & Counting1 are overlapping */130}131return (size_t)max;132}133134/* HIST_countFast_wksp() :135* Same as HIST_countFast(), but using an externally provided scratch buffer.136* `workSpace` is a writable buffer which must be 4-bytes aligned,137* `workSpaceSize` must be >= HIST_WKSP_SIZE138*/139size_t HIST_countFast_wksp(unsigned* count, unsigned* maxSymbolValuePtr,140const void* source, size_t sourceSize,141void* workSpace, size_t workSpaceSize)142{143if (sourceSize < 1500) /* heuristic threshold */144return HIST_count_simple(count, maxSymbolValuePtr, source, sourceSize);145if ((size_t)workSpace & 3) return ERROR(GENERIC); /* must be aligned on 4-bytes boundaries */146if (workSpaceSize < HIST_WKSP_SIZE) return ERROR(workSpace_tooSmall);147return HIST_count_parallel_wksp(count, maxSymbolValuePtr, source, sourceSize, trustInput, (U32*)workSpace);148}149150/* HIST_count_wksp() :151* Same as HIST_count(), but using an externally provided scratch buffer.152* `workSpace` size must be table of >= HIST_WKSP_SIZE_U32 unsigned */153size_t HIST_count_wksp(unsigned* count, unsigned* maxSymbolValuePtr,154const void* source, size_t sourceSize,155void* workSpace, size_t workSpaceSize)156{157if ((size_t)workSpace & 3) return ERROR(GENERIC); /* must be aligned on 4-bytes boundaries */158if (workSpaceSize < HIST_WKSP_SIZE) return ERROR(workSpace_tooSmall);159if (*maxSymbolValuePtr < 255)160return HIST_count_parallel_wksp(count, maxSymbolValuePtr, source, sourceSize, checkMaxSymbolValue, (U32*)workSpace);161*maxSymbolValuePtr = 255;162return HIST_countFast_wksp(count, maxSymbolValuePtr, source, sourceSize, workSpace, workSpaceSize);163}164165#ifndef ZSTD_NO_UNUSED_FUNCTIONS166/* fast variant (unsafe : won't check if src contains values beyond count[] limit) */167size_t HIST_countFast(unsigned* count, unsigned* maxSymbolValuePtr,168const void* source, size_t sourceSize)169{170unsigned tmpCounters[HIST_WKSP_SIZE_U32];171return HIST_countFast_wksp(count, maxSymbolValuePtr, source, sourceSize, tmpCounters, sizeof(tmpCounters));172}173174size_t HIST_count(unsigned* count, unsigned* maxSymbolValuePtr,175const void* src, size_t srcSize)176{177unsigned tmpCounters[HIST_WKSP_SIZE_U32];178return HIST_count_wksp(count, maxSymbolValuePtr, src, srcSize, tmpCounters, sizeof(tmpCounters));179}180#endif181182183