Bit counting functions (CountBits, CountBits64) (#232)

* Core: CountBits and CountBits64 functions are added.

* autotest: CountBits test added.

* Core: inline force on CountBits and CountBits64
This commit is contained in:
İsmail Yılmaz 2025-02-14 21:25:25 +03:00 committed by GitHub
parent c4283f3ceb
commit 421eb73ac9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 112 additions and 0 deletions

View file

@ -0,0 +1,33 @@
#include <Core/Core.h>
using namespace Upp;
CONSOLE_APP_MAIN
{
StdLogSetup(LOG_FILE|LOG_COUT);
DUMP(CountBits(0x0001));
DUMP(CountBits(0x000f));
DUMP(CountBits(0x00ff));
DUMP(CountBits(0x0fff));
DUMP(CountBits(0xffff));
DUMP(CountBits(0x000fffff));
DUMP(CountBits(0x00ffffff));
DUMP(CountBits(0x0fffffff));
DUMP(CountBits(0xffffffff));
LOG("====================");
DUMP(CountBits64(0x00000001ffffffff));
DUMP(CountBits64(0x0000000fffffffff));
DUMP(CountBits64(0x000000ffffffffff));
DUMP(CountBits64(0x00000fffffffffff));
DUMP(CountBits64(0x0000ffffffffffff));
DUMP(CountBits64(0x000fffffffffffff));
DUMP(CountBits64(0x00ffffffffffffff));
DUMP(CountBits64(0x0fffffffffffffff));
DUMP(CountBits64(0xffffffffffffffff));
CheckLogEtalon();
}

View file

@ -0,0 +1,10 @@
uses
Core;
file
Etalon.log,
CountBits.cpp;
mainconfig
"" = "";

View file

@ -0,0 +1,21 @@
* /home/maldoror//upp/.cache/upp.out/autotest/CLANG.Debug.Debug_Full.Shared/CountBits 08.02.2025 14:47:07, user: maldoror
CountBits(0x0001) = 1
CountBits(0x000f) = 4
CountBits(0x00ff) = 8
CountBits(0x0fff) = 12
CountBits(0xffff) = 16
CountBits(0x000fffff) = 20
CountBits(0x00ffffff) = 24
CountBits(0x0fffffff) = 28
CountBits(0xffffffff) = 32
====================
CountBits64(0x00000001ffffffff) = 33
CountBits64(0x0000000fffffffff) = 36
CountBits64(0x000000ffffffffff) = 40
CountBits64(0x00000fffffffffff) = 44
CountBits64(0x0000ffffffffffff) = 48
CountBits64(0x000fffffffffffff) = 52
CountBits64(0x00ffffffffffffff) = 56
CountBits64(0x0fffffffffffffff) = 60
CountBits64(0xffffffffffffffff) = 64

View file

@ -202,6 +202,47 @@ inline bool FitsInInt64(double x)
return x >= -9223372036854775808.0 && x < 9223372036854775808.0;
}
force_inline
int CountBits(dword mask)
{
#if defined(__GNUC__) || defined(__clang__)
return __builtin_popcount(mask);
#elif defined(_MSC_VER)
return __popcnt(mask);
#else
// Fallback (unlikely)
mask = mask - ((mask >> 1) & 0x55555555);
mask = (mask & 0x33333333) + ((mask >> 2) & 0x33333333);
mask = (mask + (mask >> 4)) & 0x0F0F0F0F;
mask = mask + (mask >> 8);
mask = mask + (mask >> 16);
return mask & 0x3F;
#endif
}
force_inline
int CountBits64(uint64 mask)
{
#if defined(__GNUC__) || defined(__clang__)
return __builtin_popcountll(mask);
#elif defined(_MSC_VER)
#if defined(_WIN64)
return __popcnt64(mask);
#else
return CountBits(static_cast<dword>(mask)) + CountBits(static_cast<dword>(mask >> 32));
#endif
#else
// Fallback (unlikely)
mask = mask - ((mask >> 1) & 0x5555555555555555ULL);
mask = (mask & 0x3333333333333333ULL) + ((mask >> 2) & 0x3333333333333333ULL);
mask = (mask + (mask >> 4)) & 0x0F0F0F0F0F0F0F0FULL;
mask = mask + (mask >> 8);
mask = mask + (mask >> 16);
mask = mask + (mask >> 32);
return mask & 0x7F;
#endif
}
#if defined(__SIZEOF_INT128__) && (__GNUC__ > 5 || __clang_major__ >= 5)
#ifdef CPU_X86

View file

@ -132,6 +132,13 @@ for binary value 1010, this value is 4. For 0, the value is 0.&]
loosing the precision.&]
[s3;%% &]
[s4; &]
[s5;:Upp`:`:CountBits`(dword`): [@(0.0.255) int] [* CountBits]([_^Upp`:`:dword^ dword]
[*@3 mask])&]
[s5;:Upp`:`:CountBits64`(uint64`): [@(0.0.255) int] [* CountBits64]([_^Upp`:`:uint64^ uint6
4] [*@3 mask])&]
[s2;%% Returns the total number of set bits in a given bit [%-*@3 mask].&]
[s3; &]
[s4; &]
[s5;:Upp`:`:Peek16le`(const void`*`): [@(0.0.255) int]_[* Peek16le]([@(0.0.255) const]_[@(0.0.255) v
oid]_`*[*@3 ptr])&]
[s5;:Upp`:`:Peek32le`(const void`*`): [@(0.0.255) int]_[* Peek32le]([@(0.0.255) const]_[@(0.0.255) v