PackedVector.h 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===- llvm/ADT/PackedVector.h - Packed values vector -----------*- C++ -*-===//
  7. //
  8. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  9. // See https://llvm.org/LICENSE.txt for license information.
  10. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  11. //
  12. //===----------------------------------------------------------------------===//
  13. ///
  14. /// \file
  15. /// This file implements the PackedVector class.
  16. ///
  17. //===----------------------------------------------------------------------===//
  18. #ifndef LLVM_ADT_PACKEDVECTOR_H
  19. #define LLVM_ADT_PACKEDVECTOR_H
  20. #include "llvm/ADT/BitVector.h"
  21. #include <cassert>
  22. #include <limits>
  23. namespace llvm {
  24. template <typename T, unsigned BitNum, typename BitVectorTy, bool isSigned>
  25. class PackedVectorBase;
  26. // This won't be necessary if we can specialize members without specializing
  27. // the parent template.
  28. template <typename T, unsigned BitNum, typename BitVectorTy>
  29. class PackedVectorBase<T, BitNum, BitVectorTy, false> {
  30. protected:
  31. static T getValue(const BitVectorTy &Bits, unsigned Idx) {
  32. T val = T();
  33. for (unsigned i = 0; i != BitNum; ++i)
  34. val = T(val | ((Bits[(Idx << (BitNum-1)) + i] ? 1UL : 0UL) << i));
  35. return val;
  36. }
  37. static void setValue(BitVectorTy &Bits, unsigned Idx, T val) {
  38. assert((val >> BitNum) == 0 && "value is too big");
  39. for (unsigned i = 0; i != BitNum; ++i)
  40. Bits[(Idx << (BitNum-1)) + i] = val & (T(1) << i);
  41. }
  42. };
  43. template <typename T, unsigned BitNum, typename BitVectorTy>
  44. class PackedVectorBase<T, BitNum, BitVectorTy, true> {
  45. protected:
  46. static T getValue(const BitVectorTy &Bits, unsigned Idx) {
  47. T val = T();
  48. for (unsigned i = 0; i != BitNum-1; ++i)
  49. val = T(val | ((Bits[(Idx << (BitNum-1)) + i] ? 1UL : 0UL) << i));
  50. if (Bits[(Idx << (BitNum-1)) + BitNum-1])
  51. val = ~val;
  52. return val;
  53. }
  54. static void setValue(BitVectorTy &Bits, unsigned Idx, T val) {
  55. if (val < 0) {
  56. val = ~val;
  57. Bits.set((Idx << (BitNum-1)) + BitNum-1);
  58. }
  59. assert((val >> (BitNum-1)) == 0 && "value is too big");
  60. for (unsigned i = 0; i != BitNum-1; ++i)
  61. Bits[(Idx << (BitNum-1)) + i] = val & (T(1) << i);
  62. }
  63. };
  64. /// Store a vector of values using a specific number of bits for each
  65. /// value. Both signed and unsigned types can be used, e.g
  66. /// @code
  67. /// PackedVector<signed, 2> vec;
  68. /// @endcode
  69. /// will create a vector accepting values -2, -1, 0, 1. Any other value will hit
  70. /// an assertion.
  71. template <typename T, unsigned BitNum, typename BitVectorTy = BitVector>
  72. class PackedVector : public PackedVectorBase<T, BitNum, BitVectorTy,
  73. std::numeric_limits<T>::is_signed> {
  74. BitVectorTy Bits;
  75. using base = PackedVectorBase<T, BitNum, BitVectorTy,
  76. std::numeric_limits<T>::is_signed>;
  77. public:
  78. class reference {
  79. PackedVector &Vec;
  80. const unsigned Idx;
  81. public:
  82. reference() = delete;
  83. reference(PackedVector &vec, unsigned idx) : Vec(vec), Idx(idx) {}
  84. reference &operator=(T val) {
  85. Vec.setValue(Vec.Bits, Idx, val);
  86. return *this;
  87. }
  88. operator T() const {
  89. return Vec.getValue(Vec.Bits, Idx);
  90. }
  91. };
  92. PackedVector() = default;
  93. explicit PackedVector(unsigned size) : Bits(size << (BitNum-1)) {}
  94. bool empty() const { return Bits.empty(); }
  95. unsigned size() const { return Bits.size() >> (BitNum - 1); }
  96. void clear() { Bits.clear(); }
  97. void resize(unsigned N) { Bits.resize(N << (BitNum - 1)); }
  98. void reserve(unsigned N) { Bits.reserve(N << (BitNum-1)); }
  99. PackedVector &reset() {
  100. Bits.reset();
  101. return *this;
  102. }
  103. void push_back(T val) {
  104. resize(size()+1);
  105. (*this)[size()-1] = val;
  106. }
  107. reference operator[](unsigned Idx) {
  108. return reference(*this, Idx);
  109. }
  110. T operator[](unsigned Idx) const {
  111. return base::getValue(Bits, Idx);
  112. }
  113. bool operator==(const PackedVector &RHS) const {
  114. return Bits == RHS.Bits;
  115. }
  116. bool operator!=(const PackedVector &RHS) const {
  117. return Bits != RHS.Bits;
  118. }
  119. PackedVector &operator|=(const PackedVector &RHS) {
  120. Bits |= RHS.Bits;
  121. return *this;
  122. }
  123. };
  124. // Leave BitNum=0 undefined.
  125. template <typename T> class PackedVector<T, 0>;
  126. } // end namespace llvm
  127. #endif // LLVM_ADT_PACKEDVECTOR_H
  128. #ifdef __GNUC__
  129. #pragma GCC diagnostic pop
  130. #endif