| // Copyright (c) 2018 Google LLC |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| #ifndef SOURCE_UTIL_BIT_VECTOR_H_ |
| #define SOURCE_UTIL_BIT_VECTOR_H_ |
| |
| #include <cstdint> |
| #include <iosfwd> |
| #include <vector> |
| |
| namespace spvtools { |
| namespace utils { |
| |
| // Implements a bit vector class. |
| // |
| // All bits default to zero, and the upper bound is 2^32-1. |
| class BitVector { |
| private: |
| using BitContainer = uint64_t; |
| enum { kBitContainerSize = 64 }; |
| enum { kInitialNumBits = 1024 }; |
| |
| public: |
| // Creates a bit vector contianing 0s. |
| BitVector(uint32_t reserved_size = kInitialNumBits) |
| : bits_((reserved_size - 1) / kBitContainerSize + 1, 0) {} |
| |
| // Sets the |i|th bit to 1. Returns the |i|th bit before it was set. |
| bool Set(uint32_t i) { |
| uint32_t element_index = i / kBitContainerSize; |
| uint32_t bit_in_element = i % kBitContainerSize; |
| |
| if (element_index >= bits_.size()) { |
| bits_.resize(element_index + 1, 0); |
| } |
| |
| BitContainer original = bits_[element_index]; |
| BitContainer ith_bit = static_cast<BitContainer>(1) << bit_in_element; |
| |
| if ((original & ith_bit) != 0) { |
| return true; |
| } else { |
| bits_[element_index] = original | ith_bit; |
| return false; |
| } |
| } |
| |
| // Sets the |i|th bit to 0. Return the |i|th bit before it was cleared. |
| bool Clear(uint32_t i) { |
| uint32_t element_index = i / kBitContainerSize; |
| uint32_t bit_in_element = i % kBitContainerSize; |
| |
| if (element_index >= bits_.size()) { |
| return false; |
| } |
| |
| BitContainer original = bits_[element_index]; |
| BitContainer ith_bit = static_cast<BitContainer>(1) << bit_in_element; |
| |
| if ((original & ith_bit) == 0) { |
| return false; |
| } else { |
| bits_[element_index] = original & (~ith_bit); |
| return true; |
| } |
| } |
| |
| // Returns the |i|th bit. |
| bool Get(uint32_t i) const { |
| uint32_t element_index = i / kBitContainerSize; |
| uint32_t bit_in_element = i % kBitContainerSize; |
| |
| if (element_index >= bits_.size()) { |
| return false; |
| } |
| |
| return (bits_[element_index] & |
| (static_cast<BitContainer>(1) << bit_in_element)) != 0; |
| } |
| |
| // Returns true if every bit is 0. |
| bool Empty() const { |
| for (BitContainer b : bits_) { |
| if (b != 0) { |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| // Print a report on the densicy of the bit vector, number of 1 bits, number |
| // of bytes, and average bytes for 1 bit, to |out|. |
| void ReportDensity(std::ostream& out); |
| |
| friend std::ostream& operator<<(std::ostream&, const BitVector&); |
| |
| // Performs a bitwise-or operation on |this| and |that|, storing the result in |
| // |this|. Return true if |this| changed. |
| bool Or(const BitVector& that); |
| |
| private: |
| std::vector<BitContainer> bits_; |
| }; |
| |
| } // namespace utils |
| } // namespace spvtools |
| |
| #endif // SOURCE_UTIL_BIT_VECTOR_H_ |