xenium
utils.hpp
1 //
2 // Copyright (c) 2018-2020 Manuel Pöter.
3 // Licensed under the MIT License. See LICENSE file in the project root for full license information.
4 //
5 
6 #ifndef XENIUM_UTILS_HPP
7 #define XENIUM_UTILS_HPP
8 
9 #include <cstdint>
10 #ifdef _M_AMD64
11 #include <intrin.h>
12 #endif
13 
14 namespace xenium { namespace utils {
15  template <typename T>
16  constexpr bool is_power_of_two(T val) {
17  return (val & (val - 1)) == 0;
18  }
19 
20  template <typename T>
21  constexpr unsigned find_last_bit_set(T val) {
22  unsigned result = 0;
23  for (; val != 0; val >>= 1)
24  ++result;
25  return result;
26  }
27 
28  template <typename T>
29  constexpr T next_power_of_two(T val)
30  {
31  if (is_power_of_two(val))
32  return val;
33 
34  return static_cast<T>(1) << find_last_bit_set(val);
35  }
36 
37  template <typename T>
38  struct modulo {
39  T operator()(T a, T b) { return a % b; }
40  };
41 
42  // TODO - use intrinsics for rotate operation (if available)
43  template <uintptr_t C>
44  struct rotate {
45  static uintptr_t left(uintptr_t v) {
46  static_assert(C > 0, "should never happen!");
47  return (v >> (64 - C)) | (v << C);
48  }
49 
50  static uintptr_t right(uintptr_t v) {
51  static_assert(C > 0, "should never happen!");
52  return (v >> C) | (v << (64 - C));
53  }
54  };
55 
56  template <>
57  struct rotate<0> {
58  static uintptr_t left(uintptr_t v) { return v; }
59  static uintptr_t right(uintptr_t v) { return v; }
60  };
61 
62 #if defined(__sparc__)
63  static inline std::uint64_t getticks(void) {
64  std::uint64_t ret;
65  __asm__("rd %%tick, %0" : "=r" (ret));
66  return ret;
67  }
68 #elif defined(__x86_64__)
69  static inline std::uint64_t getticks(void) {
70  std::uint32_t hi, lo;
71  __asm__ ("rdtsc" : "=a"(lo), "=d"(hi));
72  return (static_cast<std::uint64_t>(hi) << 32) | static_cast<std::uint64_t>(lo);
73  }
74 #elif defined(_M_AMD64)
75  static inline std::uint64_t getticks(void) {
76  return __rdtsc();
77  }
78 #else
79  // TODO - add support for more compilers!
80  #error "Unsupported compiler"
81 #endif
82 
83  inline std::uint64_t random() {
84  return getticks() >> 4;
85  }
86 }}
87 #endif