bitutils.h 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. // Copyright (c) 2015-2016 The Khronos Group Inc.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #ifndef SOURCE_UTIL_BITUTILS_H_
  15. #define SOURCE_UTIL_BITUTILS_H_
  16. #include <cstdint>
  17. #include <cstring>
  18. namespace spvtools {
  19. namespace utils {
  20. // Performs a bitwise copy of source to the destination type Dest.
  21. template <typename Dest, typename Src>
  22. Dest BitwiseCast(Src source) {
  23. Dest dest;
  24. static_assert(sizeof(source) == sizeof(dest),
  25. "BitwiseCast: Source and destination must have the same size");
  26. std::memcpy(&dest, &source, sizeof(dest));
  27. return dest;
  28. }
  29. // SetBits<T, First, Num> returns an integer of type <T> with bits set
  30. // for position <First> through <First + Num - 1>, counting from the least
  31. // significant bit. In particular when Num == 0, no positions are set to 1.
  32. // A static assert will be triggered if First + Num > sizeof(T) * 8, that is,
  33. // a bit that will not fit in the underlying type is set.
  34. template <typename T, size_t First = 0, size_t Num = 0>
  35. struct SetBits {
  36. static_assert(First < sizeof(T) * 8,
  37. "Tried to set a bit that is shifted too far.");
  38. const static T get = (T(1) << First) | SetBits<T, First + 1, Num - 1>::get;
  39. };
  40. template <typename T, size_t Last>
  41. struct SetBits<T, Last, 0> {
  42. const static T get = T(0);
  43. };
  44. // This is all compile-time so we can put our tests right here.
  45. static_assert(SetBits<uint32_t, 0, 0>::get == uint32_t(0x00000000),
  46. "SetBits failed");
  47. static_assert(SetBits<uint32_t, 0, 1>::get == uint32_t(0x00000001),
  48. "SetBits failed");
  49. static_assert(SetBits<uint32_t, 31, 1>::get == uint32_t(0x80000000),
  50. "SetBits failed");
  51. static_assert(SetBits<uint32_t, 1, 2>::get == uint32_t(0x00000006),
  52. "SetBits failed");
  53. static_assert(SetBits<uint32_t, 30, 2>::get == uint32_t(0xc0000000),
  54. "SetBits failed");
  55. static_assert(SetBits<uint32_t, 0, 31>::get == uint32_t(0x7FFFFFFF),
  56. "SetBits failed");
  57. static_assert(SetBits<uint32_t, 0, 32>::get == uint32_t(0xFFFFFFFF),
  58. "SetBits failed");
  59. static_assert(SetBits<uint32_t, 16, 16>::get == uint32_t(0xFFFF0000),
  60. "SetBits failed");
  61. static_assert(SetBits<uint64_t, 0, 1>::get == uint64_t(0x0000000000000001LL),
  62. "SetBits failed");
  63. static_assert(SetBits<uint64_t, 63, 1>::get == uint64_t(0x8000000000000000LL),
  64. "SetBits failed");
  65. static_assert(SetBits<uint64_t, 62, 2>::get == uint64_t(0xc000000000000000LL),
  66. "SetBits failed");
  67. static_assert(SetBits<uint64_t, 31, 1>::get == uint64_t(0x0000000080000000LL),
  68. "SetBits failed");
  69. static_assert(SetBits<uint64_t, 16, 16>::get == uint64_t(0x00000000FFFF0000LL),
  70. "SetBits failed");
  71. // Returns number of '1' bits in a word.
  72. template <typename T>
  73. size_t CountSetBits(T word) {
  74. static_assert(std::is_integral<T>::value,
  75. "CountSetBits requires integer type");
  76. size_t count = 0;
  77. while (word) {
  78. word &= word - 1;
  79. ++count;
  80. }
  81. return count;
  82. }
  83. } // namespace utils
  84. } // namespace spvtools
  85. #endif // SOURCE_UTIL_BITUTILS_H_