--- /dev/null
+/*
+ * Copyright 2017 Facebook, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <type_traits>
+
+namespace folly {
+
+// TLDR: Prefer using operator< for ordering. And when
+// a and b are equivalent objects, we return b to make
+// sorting stable.
+// See http://stepanovpapers.com/notes.pdf for details.
+template <typename T>
+constexpr T constexpr_max(T a) {
+ return a;
+}
+template <typename T, typename... Ts>
+constexpr T constexpr_max(T a, T b, Ts... ts) {
+ return b < a ? constexpr_max(a, ts...) : constexpr_max(b, ts...);
+}
+
+// When a and b are equivalent objects, we return a to
+// make sorting stable.
+template <typename T>
+constexpr T constexpr_min(T a) {
+ return a;
+}
+template <typename T, typename... Ts>
+constexpr T constexpr_min(T a, T b, Ts... ts) {
+ return b < a ? constexpr_max(b, ts...) : constexpr_max(a, ts...);
+}
+
+namespace detail {
+
+template <typename T, typename = void>
+struct constexpr_abs_helper {};
+
+template <typename T>
+struct constexpr_abs_helper<
+ T,
+ typename std::enable_if<std::is_floating_point<T>::value>::type> {
+ static constexpr T go(T t) {
+ return t < static_cast<T>(0) ? -t : t;
+ }
+};
+
+template <typename T>
+struct constexpr_abs_helper<
+ T,
+ typename std::enable_if<
+ std::is_integral<T>::value && !std::is_same<T, bool>::value &&
+ std::is_unsigned<T>::value>::type> {
+ static constexpr T go(T t) {
+ return t;
+ }
+};
+
+template <typename T>
+struct constexpr_abs_helper<
+ T,
+ typename std::enable_if<
+ std::is_integral<T>::value && !std::is_same<T, bool>::value &&
+ std::is_signed<T>::value>::type> {
+ static constexpr typename std::make_unsigned<T>::type go(T t) {
+ return typename std::make_unsigned<T>::type(t < static_cast<T>(0) ? -t : t);
+ }
+};
+} // namespace detail
+
+template <typename T>
+constexpr auto constexpr_abs(T t)
+ -> decltype(detail::constexpr_abs_helper<T>::go(t)) {
+ return detail::constexpr_abs_helper<T>::go(t);
+}
+
+namespace detail {
+template <typename T>
+constexpr T constexpr_log2(T a, T e) {
+ return e == T(1) ? a : constexpr_log2(a + T(1), e / T(2));
+}
+} // namespace detail
+
+template <typename T>
+constexpr T constexpr_log2(T t) {
+ return detail::constexpr_log2(T(0), t);
+}
+
+} // namespace folly
#include <type_traits>
#include <utility>
+#include <folly/ConstexprMath.h>
#include <folly/Portability.h>
#include <folly/Range.h>
#include <folly/Utility.h>
b = std::move(tmp);
}
-// FUTURE: use const_log2 to fold instantiations of BasicFixedString together.
-// All BasicFixedString<C, N> instantiations could share the implementation
-// of BasicFixedString<C, M>, where M is the next highest power of 2 after N.
-//
-// Also, because of alignment of the data_ and size_ members, N should never be
-// smaller than `(alignof(std::size_t)/sizeof(C))-1` (-1 because of the null
-// terminator). OR, create a specialization for BasicFixedString<C, 0u> that
-// does not have a size_ member, since it is unnecessary.
-constexpr std::size_t const_log2(std::size_t N, std::size_t log2 = 0u) {
- return N / 2u == 0u ? log2 : const_log2(N / 2u, log2 + 1u);
-}
-
// For constexpr reverse iteration over a BasicFixedString
template <class T>
struct ReverseIterator {
friend class BasicFixedString;
friend struct detail::fixedstring::Helper;
+ // FUTURE: use constexpr_log2 to fold instantiations of BasicFixedString
+ // together. All BasicFixedString<C, N> instantiations could share the
+ // implementation of BasicFixedString<C, M>, where M is the next highest power
+ // of 2 after N.
+ //
+ // Also, because of alignment of the data_ and size_ members, N should never
+ // be smaller than `(alignof(std::size_t)/sizeof(C))-1` (-1 because of the
+ // null terminator). OR, create a specialization for BasicFixedString<C, 0u>
+ // that does not have a size_ member, since it is unnecessary.
Char data_[N + 1u]; // +1 for the null terminator
std::size_t size_; // Nbr of chars, not incl. null terminator. size_ <= N.
#include <folly/Format.h>
+#include <folly/ConstexprMath.h>
#include <folly/CppAttributes.h>
-#include <folly/portability/Constexpr.h>
#include <double-conversion/double-conversion.h>
concurrency/ConcurrentHashMap.h \
concurrency/CoreCachedSharedPtr.h \
concurrency/detail/ConcurrentHashMap-detail.h \
+ ConstexprMath.h \
detail/AtomicHashUtils.h \
detail/AtomicUnorderedMapUtils.h \
detail/AtomicUtils.h \
#include <folly/fibers/Fiber.h>
#include <folly/fibers/LoopController.h>
+#include <folly/ConstexprMath.h>
#include <folly/SingletonThreadLocal.h>
#include <folly/portability/SysSyscall.h>
#include <folly/portability/Unistd.h>
namespace folly {
-// TLDR: Prefer using operator< for ordering. And when
-// a and b are equivalent objects, we return b to make
-// sorting stable.
-// See http://stepanovpapers.com/notes.pdf for details.
-template <typename T>
-constexpr T constexpr_max(T a, T b) {
- return b < a ? a : b;
-}
-
-// When a and b are equivalent objects, we return a to
-// make sorting stable.
-template <typename T>
-constexpr T constexpr_min(T a, T b) {
- return b < a ? b : a;
-}
-
-namespace detail {
-
-template <typename T, typename = void>
-struct constexpr_abs_helper {};
-
-template <typename T>
-struct constexpr_abs_helper<
- T,
- typename std::enable_if<std::is_floating_point<T>::value>::type> {
- static constexpr T go(T t) {
- return t < static_cast<T>(0) ? -t : t;
- }
-};
-
-template <typename T>
-struct constexpr_abs_helper<
- T,
- typename std::enable_if<
- std::is_integral<T>::value && !std::is_same<T, bool>::value &&
- std::is_unsigned<T>::value>::type> {
- static constexpr T go(T t) {
- return t;
- }
-};
-
-template <typename T>
-struct constexpr_abs_helper<
- T,
- typename std::enable_if<
- std::is_integral<T>::value && !std::is_same<T, bool>::value &&
- std::is_signed<T>::value>::type> {
- static constexpr typename std::make_unsigned<T>::type go(T t) {
- return typename std::make_unsigned<T>::type(t < static_cast<T>(0) ? -t : t);
- }
-};
-} // namespace detail
-
-template <typename T>
-constexpr auto constexpr_abs(T t)
- -> decltype(detail::constexpr_abs_helper<T>::go(t)) {
- return detail::constexpr_abs_helper<T>::go(t);
-}
-
-template <typename T>
-constexpr T constexpr_log2(T t) {
- return t == T(1) ? T(0) : T(1) + constexpr_log2(t / T(2));
-}
-
namespace detail {
template <typename Char>
class ConstexprTest : public testing::Test {};
}
-TEST_F(ConstexprTest, constexpr_abs_unsigned) {
- constexpr auto v = uint32_t(17);
- constexpr auto a = folly::constexpr_abs(v);
- EXPECT_EQ(17, a);
- EXPECT_TRUE((std::is_same<const uint32_t, decltype(a)>::value));
-}
-
-TEST_F(ConstexprTest, constexpr_abs_signed_positive) {
- constexpr auto v = int32_t(17);
- constexpr auto a = folly::constexpr_abs(v);
- EXPECT_EQ(17, a);
- EXPECT_TRUE((std::is_same<const uint32_t, decltype(a)>::value));
-}
-
-TEST_F(ConstexprTest, constexpr_abs_signed_negative) {
- constexpr auto v = int32_t(-17);
- constexpr auto a = folly::constexpr_abs(v);
- EXPECT_EQ(17, a);
- EXPECT_TRUE((std::is_same<const uint32_t, decltype(a)>::value));
-}
-
-TEST_F(ConstexprTest, constexpr_abs_float_positive) {
- constexpr auto v = 17.5f;
- constexpr auto a = folly::constexpr_abs(v);
- EXPECT_EQ(17.5, a);
- EXPECT_TRUE((std::is_same<const float, decltype(a)>::value));
-}
-
-TEST_F(ConstexprTest, constexpr_abs_float_negative) {
- constexpr auto v = -17.5f;
- constexpr auto a = folly::constexpr_abs(v);
- EXPECT_EQ(17.5, a);
- EXPECT_TRUE((std::is_same<const float, decltype(a)>::value));
-}
-
-TEST_F(ConstexprTest, constexpr_abs_double_positive) {
- constexpr auto v = 17.5;
- constexpr auto a = folly::constexpr_abs(v);
- EXPECT_EQ(17.5, a);
- EXPECT_TRUE((std::is_same<const double, decltype(a)>::value));
-}
-
-TEST_F(ConstexprTest, constexpr_abs_double_negative) {
- constexpr auto v = -17.5;
- constexpr auto a = folly::constexpr_abs(v);
- EXPECT_EQ(17.5, a);
- EXPECT_TRUE((std::is_same<const double, decltype(a)>::value));
-}
-
-TEST_F(ConstexprTest, constexpr_log2_1) {
- constexpr auto v = 1ull;
- constexpr auto a = folly::constexpr_log2(v);
- EXPECT_EQ(0ull, a);
- EXPECT_TRUE((std::is_same<decltype(v), decltype(a)>::value));
-}
-
-TEST_F(ConstexprTest, constexpr_log2_2) {
- constexpr auto v = 2ull;
- constexpr auto a = folly::constexpr_log2(v);
- EXPECT_EQ(1ull, a);
- EXPECT_TRUE((std::is_same<decltype(v), decltype(a)>::value));
-}
-
-TEST_F(ConstexprTest, constexpr_log2_64) {
- constexpr auto v = 64ull;
- constexpr auto a = folly::constexpr_log2(v);
- EXPECT_EQ(6ull, a);
- EXPECT_TRUE((std::is_same<decltype(v), decltype(a)>::value));
+TEST_F(ConstexprTest, constexpr_strlen_cstr) {
+ constexpr auto v = "hello";
+ constexpr auto a = folly::constexpr_strlen(v);
+ EXPECT_EQ(5, a);
+ EXPECT_TRUE((std::is_same<const size_t, decltype(a)>::value));
+}
+
+TEST_F(ConstexprTest, constexpr_strlen_ints) {
+ constexpr int v[] = {5, 3, 4, 0, 7};
+ constexpr auto a = folly::constexpr_strlen(v);
+ EXPECT_EQ(3, a);
+ EXPECT_TRUE((std::is_same<const size_t, decltype(a)>::value));
}
#include <boost/type_traits.hpp>
#include <folly/Assume.h>
+#include <folly/ConstexprMath.h>
#include <folly/FormatTraits.h>
#include <folly/Malloc.h>
#include <folly/Portability.h>
#include <folly/SmallLocks.h>
#include <folly/Traits.h>
#include <folly/portability/BitsFunctexcept.h>
-#include <folly/portability/Constexpr.h>
#include <folly/portability/Malloc.h>
#include <folly/portability/TypeTraits.h>
--- /dev/null
+/*
+ * Copyright 2017 Facebook, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <folly/ConstexprMath.h>
+
+#include <folly/portability/GTest.h>
+
+namespace {
+
+class ConstexprMathTest : public testing::Test {};
+}
+
+TEST_F(ConstexprMathTest, constexpr_abs_unsigned) {
+ constexpr auto v = uint32_t(17);
+ constexpr auto a = folly::constexpr_abs(v);
+ EXPECT_EQ(17, a);
+ EXPECT_TRUE((std::is_same<const uint32_t, decltype(a)>::value));
+}
+
+TEST_F(ConstexprMathTest, constexpr_abs_signed_positive) {
+ constexpr auto v = int32_t(17);
+ constexpr auto a = folly::constexpr_abs(v);
+ EXPECT_EQ(17, a);
+ EXPECT_TRUE((std::is_same<const uint32_t, decltype(a)>::value));
+}
+
+TEST_F(ConstexprMathTest, constexpr_abs_signed_negative) {
+ constexpr auto v = int32_t(-17);
+ constexpr auto a = folly::constexpr_abs(v);
+ EXPECT_EQ(17, a);
+ EXPECT_TRUE((std::is_same<const uint32_t, decltype(a)>::value));
+}
+
+TEST_F(ConstexprMathTest, constexpr_abs_float_positive) {
+ constexpr auto v = 17.5f;
+ constexpr auto a = folly::constexpr_abs(v);
+ EXPECT_EQ(17.5, a);
+ EXPECT_TRUE((std::is_same<const float, decltype(a)>::value));
+}
+
+TEST_F(ConstexprMathTest, constexpr_abs_float_negative) {
+ constexpr auto v = -17.5f;
+ constexpr auto a = folly::constexpr_abs(v);
+ EXPECT_EQ(17.5, a);
+ EXPECT_TRUE((std::is_same<const float, decltype(a)>::value));
+}
+
+TEST_F(ConstexprMathTest, constexpr_abs_double_positive) {
+ constexpr auto v = 17.5;
+ constexpr auto a = folly::constexpr_abs(v);
+ EXPECT_EQ(17.5, a);
+ EXPECT_TRUE((std::is_same<const double, decltype(a)>::value));
+}
+
+TEST_F(ConstexprMathTest, constexpr_abs_double_negative) {
+ constexpr auto v = -17.5;
+ constexpr auto a = folly::constexpr_abs(v);
+ EXPECT_EQ(17.5, a);
+ EXPECT_TRUE((std::is_same<const double, decltype(a)>::value));
+}
+
+TEST_F(ConstexprMathTest, constexpr_log2_1) {
+ constexpr auto v = 1ull;
+ constexpr auto a = folly::constexpr_log2(v);
+ EXPECT_EQ(0ull, a);
+ EXPECT_TRUE((std::is_same<decltype(v), decltype(a)>::value));
+}
+
+TEST_F(ConstexprMathTest, constexpr_log2_2) {
+ constexpr auto v = 2ull;
+ constexpr auto a = folly::constexpr_log2(v);
+ EXPECT_EQ(1ull, a);
+ EXPECT_TRUE((std::is_same<decltype(v), decltype(a)>::value));
+}
+
+TEST_F(ConstexprMathTest, constexpr_log2_64) {
+ constexpr auto v = 64ull;
+ constexpr auto a = folly::constexpr_log2(v);
+ EXPECT_EQ(6ull, a);
+ EXPECT_TRUE((std::is_same<decltype(v), decltype(a)>::value));
+}
array_test_LDADD = libfollytestmain.la
TESTS += array_test
+constexpr_math_test_SOURCES = ConstexprMathTest.cpp
+constexpr_math_test_LDADD = libfollytestmain.la
+TESTS += constexpr_math_test
+
if RUN_ARCH_SPECIFIC_TESTS
small_locks_test_SOURCES = SmallLocksTest.cpp
small_locks_test_LDADD = libfollytestmain.la