Path: blob/main/sys/contrib/zstd/lib/common/bits.h
289229 views
/*1* Copyright (c) Meta Platforms, Inc. and affiliates.2* All rights reserved.3*4* This source code is licensed under both the BSD-style license (found in the5* LICENSE file in the root directory of this source tree) and the GPLv2 (found6* in the COPYING file in the root directory of this source tree).7* You may select, at your option, one of the above-listed licenses.8*/910#ifndef ZSTD_BITS_H11#define ZSTD_BITS_H1213#include "mem.h"1415MEM_STATIC unsigned ZSTD_countTrailingZeros32_fallback(U32 val)16{17assert(val != 0);18{19static const U32 DeBruijnBytePos[32] = {0, 1, 28, 2, 29, 14, 24, 3,2030, 22, 20, 15, 25, 17, 4, 8,2131, 27, 13, 23, 21, 19, 16, 7,2226, 12, 18, 6, 11, 5, 10, 9};23return DeBruijnBytePos[((U32) ((val & -(S32) val) * 0x077CB531U)) >> 27];24}25}2627MEM_STATIC unsigned ZSTD_countTrailingZeros32(U32 val)28{29assert(val != 0);30#if defined(_MSC_VER)31# if STATIC_BMI232return (unsigned)_tzcnt_u32(val);33# else34if (val != 0) {35unsigned long r;36_BitScanForward(&r, val);37return (unsigned)r;38} else {39__assume(0); /* Should not reach this code path */40}41# endif42#elif defined(__GNUC__) && (__GNUC__ >= 4)43return (unsigned)__builtin_ctz(val);44#elif defined(__ICCARM__)45return (unsigned)__builtin_ctz(val);46#else47return ZSTD_countTrailingZeros32_fallback(val);48#endif49}5051MEM_STATIC unsigned ZSTD_countLeadingZeros32_fallback(U32 val)52{53assert(val != 0);54{55static const U32 DeBruijnClz[32] = {0, 9, 1, 10, 13, 21, 2, 29,5611, 14, 16, 18, 22, 25, 3, 30,578, 12, 20, 28, 15, 17, 24, 7,5819, 27, 23, 6, 26, 5, 4, 31};59val |= val >> 1;60val |= val >> 2;61val |= val >> 4;62val |= val >> 8;63val |= val >> 16;64return 31 - DeBruijnClz[(val * 0x07C4ACDDU) >> 27];65}66}6768MEM_STATIC unsigned ZSTD_countLeadingZeros32(U32 val)69{70assert(val != 0);71#if defined(_MSC_VER)72# if STATIC_BMI273return (unsigned)_lzcnt_u32(val);74# else75if (val != 0) {76unsigned long r;77_BitScanReverse(&r, val);78return (unsigned)(31 - r);79} else {80__assume(0); /* Should not reach this code path */81}82# endif83#elif defined(__GNUC__) && (__GNUC__ >= 4)84return (unsigned)__builtin_clz(val);85#elif defined(__ICCARM__)86return (unsigned)__builtin_clz(val);87#else88return ZSTD_countLeadingZeros32_fallback(val);89#endif90}9192MEM_STATIC unsigned ZSTD_countTrailingZeros64(U64 val)93{94assert(val != 0);95#if defined(_MSC_VER) && defined(_WIN64)96# if STATIC_BMI297return (unsigned)_tzcnt_u64(val);98# else99if (val != 0) {100unsigned long r;101_BitScanForward64(&r, val);102return (unsigned)r;103} else {104__assume(0); /* Should not reach this code path */105}106# endif107#elif defined(__GNUC__) && (__GNUC__ >= 4) && defined(__LP64__)108return (unsigned)__builtin_ctzll(val);109#elif defined(__ICCARM__)110return (unsigned)__builtin_ctzll(val);111#else112{113U32 mostSignificantWord = (U32)(val >> 32);114U32 leastSignificantWord = (U32)val;115if (leastSignificantWord == 0) {116return 32 + ZSTD_countTrailingZeros32(mostSignificantWord);117} else {118return ZSTD_countTrailingZeros32(leastSignificantWord);119}120}121#endif122}123124MEM_STATIC unsigned ZSTD_countLeadingZeros64(U64 val)125{126assert(val != 0);127#if defined(_MSC_VER) && defined(_WIN64)128# if STATIC_BMI2129return (unsigned)_lzcnt_u64(val);130# else131if (val != 0) {132unsigned long r;133_BitScanReverse64(&r, val);134return (unsigned)(63 - r);135} else {136__assume(0); /* Should not reach this code path */137}138# endif139#elif defined(__GNUC__) && (__GNUC__ >= 4)140return (unsigned)(__builtin_clzll(val));141#elif defined(__ICCARM__)142return (unsigned)(__builtin_clzll(val));143#else144{145U32 mostSignificantWord = (U32)(val >> 32);146U32 leastSignificantWord = (U32)val;147if (mostSignificantWord == 0) {148return 32 + ZSTD_countLeadingZeros32(leastSignificantWord);149} else {150return ZSTD_countLeadingZeros32(mostSignificantWord);151}152}153#endif154}155156MEM_STATIC unsigned ZSTD_NbCommonBytes(size_t val)157{158if (MEM_isLittleEndian()) {159if (MEM_64bits()) {160return ZSTD_countTrailingZeros64((U64)val) >> 3;161} else {162return ZSTD_countTrailingZeros32((U32)val) >> 3;163}164} else { /* Big Endian CPU */165if (MEM_64bits()) {166return ZSTD_countLeadingZeros64((U64)val) >> 3;167} else {168return ZSTD_countLeadingZeros32((U32)val) >> 3;169}170}171}172173MEM_STATIC unsigned ZSTD_highbit32(U32 val) /* compress, dictBuilder, decodeCorpus */174{175assert(val != 0);176return 31 - ZSTD_countLeadingZeros32(val);177}178179/* ZSTD_rotateRight_*():180* Rotates a bitfield to the right by "count" bits.181* https://en.wikipedia.org/w/index.php?title=Circular_shift&oldid=991635599#Implementing_circular_shifts182*/183MEM_STATIC184U64 ZSTD_rotateRight_U64(U64 const value, U32 count) {185assert(count < 64);186count &= 0x3F; /* for fickle pattern recognition */187return (value >> count) | (U64)(value << ((0U - count) & 0x3F));188}189190MEM_STATIC191U32 ZSTD_rotateRight_U32(U32 const value, U32 count) {192assert(count < 32);193count &= 0x1F; /* for fickle pattern recognition */194return (value >> count) | (U32)(value << ((0U - count) & 0x1F));195}196197MEM_STATIC198U16 ZSTD_rotateRight_U16(U16 const value, U32 count) {199assert(count < 16);200count &= 0x0F; /* for fickle pattern recognition */201return (value >> count) | (U16)(value << ((0U - count) & 0x0F));202}203204#endif /* ZSTD_BITS_H */205206207