constexpr_log2_ceil
authorYedidya Feldblum <yfeldblum@fb.com>
Tue, 26 Dec 2017 18:59:25 +0000 (10:59 -0800)
committerFacebook Github Bot <facebook-github-bot@users.noreply.github.com>
Tue, 26 Dec 2017 19:08:22 +0000 (11:08 -0800)
Summary: [Folly] `constexpr_log2_ceil`, like `constexpr_log2` but rounding up.

Reviewed By: Orvid

Differential Revision: D6636433

fbshipit-source-id: a10f031cc9c91cfeba7b74bbf143895a311ca772

folly/ConstexprMath.h
folly/test/ConstexprMathTest.cpp

index 5b0bc51d57d514f713a8b6932fdef62ac012e244..34f7664e2c1cfc4fa21009573e0fe88f4fdd4b3f 100644 (file)
@@ -108,6 +108,11 @@ template <typename T>
 constexpr T constexpr_log2(T a, T e) {
   return e == T(1) ? a : constexpr_log2(a + T(1), e / T(2));
 }
+
+template <typename T>
+constexpr T constexpr_log2_ceil(T l2, T t) {
+  return l2 + T(T(1) << l2 < t ? 1 : 0);
+}
 } // namespace detail
 
 template <typename T>
@@ -115,6 +120,11 @@ constexpr T constexpr_log2(T t) {
   return detail::constexpr_log2(T(0), t);
 }
 
+template <typename T>
+constexpr T constexpr_log2_ceil(T t) {
+  return detail::constexpr_log2_ceil(constexpr_log2(t), t);
+}
+
 template <typename T>
 constexpr T constexpr_ceil(T t, T round) {
   return round == T(0)
index 7b60e8f06e9c064b0c2220587b039b2866a968d0..a0f9b102331c7fa2ccb31d0debb71f0b1d999f20 100644 (file)
@@ -123,6 +123,41 @@ TEST_F(ConstexprMathTest, constexpr_log2_64) {
   EXPECT_TRUE((std::is_same<decltype(v), decltype(a)>::value));
 }
 
+TEST_F(ConstexprMathTest, constexpr_log2_ceil_1) {
+  constexpr auto v = 1ull;
+  constexpr auto a = folly::constexpr_log2_ceil(v);
+  EXPECT_EQ(0ull, a);
+  EXPECT_TRUE((std::is_same<decltype(v), decltype(a)>::value));
+}
+
+TEST_F(ConstexprMathTest, constexpr_log2_ceil_2) {
+  constexpr auto v = 2ull;
+  constexpr auto a = folly::constexpr_log2_ceil(v);
+  EXPECT_EQ(1ull, a);
+  EXPECT_TRUE((std::is_same<decltype(v), decltype(a)>::value));
+}
+
+TEST_F(ConstexprMathTest, constexpr_log2_ceil_3) {
+  constexpr auto v = 3ull;
+  constexpr auto a = folly::constexpr_log2_ceil(v);
+  EXPECT_EQ(2ull, a);
+  EXPECT_TRUE((std::is_same<decltype(v), decltype(a)>::value));
+}
+
+TEST_F(ConstexprMathTest, constexpr_log2_ceil_63) {
+  constexpr auto v = 63ull;
+  constexpr auto a = folly::constexpr_log2_ceil(v);
+  EXPECT_EQ(6ull, a);
+  EXPECT_TRUE((std::is_same<decltype(v), decltype(a)>::value));
+}
+
+TEST_F(ConstexprMathTest, constexpr_log2_ceil_64) {
+  constexpr auto v = 64ull;
+  constexpr auto a = folly::constexpr_log2_ceil(v);
+  EXPECT_EQ(6ull, a);
+  EXPECT_TRUE((std::is_same<decltype(v), decltype(a)>::value));
+}
+
 TEST_F(ConstexprMathTest, constexpr_ceil) {
   {
     constexpr auto roundable = 20ull;