From: Kefu Chai Date: Tue, 27 Jul 2021 05:54:26 +0000 (+0800) Subject: include/intarith: add popcount() X-Git-Tag: v17.1.0~1273^2~3 X-Git-Url: http://git.apps.os.sepia.ceph.com/?a=commitdiff_plain;h=197368cfb01176a996d3e885118ef57f7db1917e;p=ceph-ci.git include/intarith: add popcount() for counting "1" in an integer. Signed-off-by: Kefu Chai --- diff --git a/src/include/intarith.h b/src/include/intarith.h index e912cbe7b3c..d3eaff15635 100644 --- a/src/include/intarith.h +++ b/src/include/intarith.h @@ -190,4 +190,16 @@ template return (sizeof(v) * 8) - __builtin_clzll(v); } +// count the bits set to 1, a.k.a. population count +template +unsigned popcount(T v) { + static_assert(sizeof(T) <= sizeof(unsigned long long), "type too large"); + if constexpr (sizeof(T) <= sizeof(unsigned int)) { + return __builtin_popcount(v); + } else if constexpr (sizeof(T) <= sizeof(unsigned long)) { + return __builtin_popcountl(v); + } else { + return __builtin_popcountll(v); + } +} #endif diff --git a/src/test/test_intarith.cc b/src/test/test_intarith.cc index 0a225d40e09..c7dae7a7dcd 100644 --- a/src/test/test_intarith.cc +++ b/src/test/test_intarith.cc @@ -1,9 +1,8 @@ // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- // vim: ts=8 sw=2 smarttab -#include +#include #include - #include "include/intarith.h" TEST(intarith, cbits) { @@ -80,3 +79,22 @@ TEST(intarith, p2family) { ASSERT_EQ(0x1300, p2roundup(0x1234, 0x100)); ASSERT_EQ(0x5600, p2roundup(0x5600, 0x100)); } + +TEST(intarith, popcount) { + // char, unsigned char + EXPECT_EQ(0, popcount((char)(0))); + EXPECT_EQ(1, popcount((unsigned char)(1))); + // short, unsigned short + EXPECT_EQ(1, popcount((short)0b10)); + EXPECT_EQ(2, popcount((unsigned char)(0b11U))); + // int, unsigned int + EXPECT_EQ(sizeof(int) * CHAR_BIT, popcount(-1)); + EXPECT_EQ(0, popcount(0)); + EXPECT_EQ(1, popcount(0b10U)); + // long, unsigned long + EXPECT_EQ(1, popcount(0b1000'0000'0000'0000L)); + EXPECT_EQ(3, popcount(0b1100'1000'0000'0000UL)); + // long long, unsigned long long + EXPECT_EQ(4, popcount(0x1111'0000LL)); + EXPECT_EQ(1, popcount(0x1000'0000ULL)); +}