bit_vector.h 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. // Copyright (c) 2018 Google LLC
  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_BIT_VECTOR_H_
  15. #define SOURCE_UTIL_BIT_VECTOR_H_
  16. #include <cstdint>
  17. #include <iosfwd>
  18. #include <vector>
  19. namespace spvtools {
  20. namespace utils {
  21. // Implements a bit vector class.
  22. //
  23. // All bits default to zero, and the upper bound is 2^32-1.
  24. class BitVector {
  25. private:
  26. using BitContainer = uint64_t;
  27. enum { kBitContainerSize = 64 };
  28. enum { kInitialNumBits = 1024 };
  29. public:
  30. // Creates a bit vector contianing 0s.
  31. BitVector(uint32_t reserved_size = kInitialNumBits)
  32. : bits_((reserved_size - 1) / kBitContainerSize + 1, 0) {}
  33. // Sets the |i|th bit to 1. Returns the |i|th bit before it was set.
  34. bool Set(uint32_t i) {
  35. uint32_t element_index = i / kBitContainerSize;
  36. uint32_t bit_in_element = i % kBitContainerSize;
  37. if (element_index >= bits_.size()) {
  38. bits_.resize(element_index + 1, 0);
  39. }
  40. BitContainer original = bits_[element_index];
  41. BitContainer ith_bit = static_cast<BitContainer>(1) << bit_in_element;
  42. if ((original & ith_bit) != 0) {
  43. return true;
  44. } else {
  45. bits_[element_index] = original | ith_bit;
  46. return false;
  47. }
  48. }
  49. // Sets the |i|th bit to 0. Return the |i|th bit before it was cleared.
  50. bool Clear(uint32_t i) {
  51. uint32_t element_index = i / kBitContainerSize;
  52. uint32_t bit_in_element = i % kBitContainerSize;
  53. if (element_index >= bits_.size()) {
  54. return false;
  55. }
  56. BitContainer original = bits_[element_index];
  57. BitContainer ith_bit = static_cast<BitContainer>(1) << bit_in_element;
  58. if ((original & ith_bit) == 0) {
  59. return false;
  60. } else {
  61. bits_[element_index] = original & (~ith_bit);
  62. return true;
  63. }
  64. }
  65. // Returns the |i|th bit.
  66. bool Get(uint32_t i) const {
  67. uint32_t element_index = i / kBitContainerSize;
  68. uint32_t bit_in_element = i % kBitContainerSize;
  69. if (element_index >= bits_.size()) {
  70. return false;
  71. }
  72. return (bits_[element_index] &
  73. (static_cast<BitContainer>(1) << bit_in_element)) != 0;
  74. }
  75. // Returns true if every bit is 0.
  76. bool Empty() const {
  77. for (BitContainer b : bits_) {
  78. if (b != 0) {
  79. return false;
  80. }
  81. }
  82. return true;
  83. }
  84. // Print a report on the densicy of the bit vector, number of 1 bits, number
  85. // of bytes, and average bytes for 1 bit, to |out|.
  86. void ReportDensity(std::ostream& out);
  87. friend std::ostream& operator<<(std::ostream&, const BitVector&);
  88. // Performs a bitwise-or operation on |this| and |that|, storing the result in
  89. // |this|. Return true if |this| changed.
  90. bool Or(const BitVector& that);
  91. private:
  92. std::vector<BitContainer> bits_;
  93. };
  94. } // namespace utils
  95. } // namespace spvtools
  96. #endif // SOURCE_UTIL_BIT_VECTOR_H_