]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
include/intarith: add popcount()
authorKefu Chai <kchai@redhat.com>
Tue, 27 Jul 2021 05:54:26 +0000 (13:54 +0800)
committerKefu Chai <kchai@redhat.com>
Tue, 27 Jul 2021 12:03:32 +0000 (20:03 +0800)
for counting "1" in an integer.

Signed-off-by: Kefu Chai <kchai@redhat.com>
src/include/intarith.h
src/test/test_intarith.cc

index e912cbe7b3c44f242921f298dcd8dd0b4dc11e16..d3eaff15635f773bdb35314cbea09c35fb2773fb 100644 (file)
@@ -190,4 +190,16 @@ template<class T>
   return (sizeof(v) * 8) - __builtin_clzll(v);
 }
 
+// count the bits set to 1, a.k.a. population count
+template<class T>
+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
index 0a225d40e09b0a42c5993699fd4a76490897f6aa..c7dae7a7dcd6c1eb75d4d05d70c133d4c4441b99 100644 (file)
@@ -1,9 +1,8 @@
 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
 // vim: ts=8 sw=2 smarttab
 
-#include <iostream>
+#include <climits>
 #include <gtest/gtest.h>
-
 #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));
+}