From: Philip Pronin Date: Sun, 11 Nov 2012 01:56:51 +0000 (-0800) Subject: constexpr-ize folly/Bits.h X-Git-Tag: v0.22.0~1146 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=6aa05bb90edebaa6c507300c306086a9d8b060e4;p=folly.git constexpr-ize folly/Bits.h Summary: Want to be able to call them from other constexpr functions and from within static_assert()s. Test Plan: compiled and ran folly tests Reviewed By: tudorb@fb.com FB internal diff: D627413 --- diff --git a/folly/Bits.h b/folly/Bits.h index 3a05047d..38d35723 100644 --- a/folly/Bits.h +++ b/folly/Bits.h @@ -17,24 +17,24 @@ /** * Various low-level, bit-manipulation routines. * - * findFirstSet(x) + * findFirstSet(x) [constexpr] * find first (least significant) bit set in a value of an integral type, * 1-based (like ffs()). 0 = no bits are set (x == 0) * - * findLastSet(x) + * findLastSet(x) [constexpr] * find last (most significant) bit set in a value of an integral type, * 1-based. 0 = no bits are set (x == 0) * for x != 0, findLastSet(x) == 1 + floor(log2(x)) * - * popcount(x) - * return the number of 1 bits in x - * - * nextPowTwo(x) + * nextPowTwo(x) [constexpr] * Finds the next power of two >= x. * - * isPowTwo(x) + * isPowTwo(x) [constexpr] * return true iff x is a power of two * + * popcount(x) + * return the number of 1 bits in x + * * Endian * convert between native, big, and little endian representation * Endian::big(x) big <-> native @@ -84,6 +84,7 @@ namespace folly { // Generate overloads for findFirstSet as wrappers around // appropriate ffs, ffsl, ffsll gcc builtins template +inline constexpr typename std::enable_if< (std::is_integral::value && std::is_unsigned::value && @@ -94,6 +95,7 @@ typename std::enable_if< } template +inline constexpr typename std::enable_if< (std::is_integral::value && std::is_unsigned::value && @@ -105,6 +107,7 @@ typename std::enable_if< } template +inline constexpr typename std::enable_if< (std::is_integral::value && std::is_unsigned::value && @@ -116,6 +119,7 @@ typename std::enable_if< } template +inline constexpr typename std::enable_if< (std::is_integral::value && std::is_signed::value), unsigned int>::type @@ -129,6 +133,7 @@ typename std::enable_if< // findLastSet: return the 1-based index of the highest bit set // for x > 0, findLastSet(x) == 1 + floor(log2(x)) template +inline constexpr typename std::enable_if< (std::is_integral::value && std::is_unsigned::value && @@ -139,6 +144,7 @@ typename std::enable_if< } template +inline constexpr typename std::enable_if< (std::is_integral::value && std::is_unsigned::value && @@ -150,6 +156,7 @@ typename std::enable_if< } template +inline constexpr typename std::enable_if< (std::is_integral::value && std::is_unsigned::value && @@ -161,6 +168,7 @@ typename std::enable_if< } template +inline constexpr typename std::enable_if< (std::is_integral::value && std::is_signed::value), @@ -170,24 +178,21 @@ typename std::enable_if< } template -inline +inline constexpr typename std::enable_if< std::is_integral::value && std::is_unsigned::value, T>::type nextPowTwo(T v) { - if (UNLIKELY(v == 0)) { - return 1; - } - return 1ul << findLastSet(v - 1); + return v ? (1ul << findLastSet(v - 1)) : 1; } template -inline +inline constexpr typename std::enable_if< std::is_integral::value && std::is_unsigned::value, bool>::type isPowTwo(T v) { - return ((v != 0) && !(v & (v-1))); // yes, this is endian-agnostic + return (v != 0) && !(v & (v - 1)); } /** diff --git a/folly/test/BitsTest.cpp b/folly/test/BitsTest.cpp index 8634246a..25ebdbb7 100644 --- a/folly/test/BitsTest.cpp +++ b/folly/test/BitsTest.cpp @@ -23,6 +23,12 @@ using namespace folly; +// Test constexpr-ness. +static_assert(findFirstSet(2u) == 2, "findFirstSet"); +static_assert(findLastSet(2u) == 2, "findLastSet"); +static_assert(nextPowTwo(2u) == 2, "nextPowTwo"); +static_assert(isPowTwo(2u), "isPowTwo"); + namespace { template