PackedVector.h 4.3 KB

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