benchmark silo added
[c11concurrency-benchmarks.git] / silo / log2.hh
diff --git a/silo/log2.hh b/silo/log2.hh
new file mode 100644 (file)
index 0000000..5264f36
--- /dev/null
@@ -0,0 +1,42 @@
+// taken from xv6
+
+#pragma once
+
+#include <cstddef>
+
+// Return ceil(log2(x)).
+static inline std::size_t
+ceil_log2(std::size_t x)
+{
+  auto bits = sizeof(long long) * 8 - __builtin_clzll(x);
+  if (x == (std::size_t)1 << (bits - 1))
+    return bits - 1;
+  return bits;
+}
+
+// Return ceil(log2(x)).  This is slow, but can be evaluated in a
+// constexpr context.  'exact' is used internally and should not be
+// provided by the caller.
+static inline constexpr std::size_t
+ceil_log2_const(std::size_t x, bool exact = true)
+{
+  return (x == 0) ? (1/x)
+    : (x == 1) ? (exact ? 0 : 1)
+    : 1 + ceil_log2_const(x >> 1, ((x & 1) == 1) ? false : exact);
+}
+
+// Round up to the nearest power of 2
+static inline std::size_t
+round_up_to_pow2(std::size_t x)
+{
+  auto bits = sizeof(long long) * 8 - __builtin_clzll(x);
+  if (x == (std::size_t)1 << (bits - 1))
+    return x;
+  return (std::size_t)1 << bits;
+}
+
+static inline constexpr std::size_t
+round_up_to_pow2_const(std::size_t x)
+{
+  return (std::size_t)1 << ceil_log2_const(x);
+}