}
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...);
+ return b < a ? constexpr_min(b, ts...) : constexpr_min(a, ts...);
+}
+
+template <typename T, typename Less>
+constexpr T const&
+constexpr_clamp(T const& v, T const& lo, T const& hi, Less less) {
+ return less(v, lo) ? lo : less(hi, v) ? hi : v;
+}
+
+template <typename T>
+constexpr T const& constexpr_clamp(T const& v, T const& lo, T const& hi) {
+ struct Less {
+ constexpr bool operator()(T const& a, T const& b) const {
+ return a < b;
+ }
+ };
+ return constexpr_clamp(v, lo, hi, Less{});
}
namespace detail {
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));
+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);
+}
+
+template <typename T>
+constexpr T constexpr_square_(T t) {
+ return t * t;
}
} // namespace detail
template <typename T>
constexpr T constexpr_log2(T t) {
- return detail::constexpr_log2(T(0), 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)
+ ? t
+ : ((t + (t < T(0) ? T(0) : round - T(1))) / round) * round;
+}
+
+template <typename T>
+constexpr T constexpr_pow(T base, std::size_t exp) {
+ return exp == 0
+ ? T(1)
+ : exp == 1 ? base
+ : detail::constexpr_square_(constexpr_pow(base, exp / 2)) *
+ (exp % 2 ? base : T(1));
}
} // namespace folly