xref: /aosp_15_r20/external/llvm/include/llvm/ADT/PackedVector.h (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker //===- llvm/ADT/PackedVector.h - Packed values vector -----------*- C++ -*-===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker //                     The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker // This file implements the PackedVector class.
11*9880d681SAndroid Build Coastguard Worker //
12*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
13*9880d681SAndroid Build Coastguard Worker 
14*9880d681SAndroid Build Coastguard Worker #ifndef LLVM_ADT_PACKEDVECTOR_H
15*9880d681SAndroid Build Coastguard Worker #define LLVM_ADT_PACKEDVECTOR_H
16*9880d681SAndroid Build Coastguard Worker 
17*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/BitVector.h"
18*9880d681SAndroid Build Coastguard Worker #include <limits>
19*9880d681SAndroid Build Coastguard Worker 
20*9880d681SAndroid Build Coastguard Worker namespace llvm {
21*9880d681SAndroid Build Coastguard Worker 
22*9880d681SAndroid Build Coastguard Worker template <typename T, unsigned BitNum, typename BitVectorTy, bool isSigned>
23*9880d681SAndroid Build Coastguard Worker class PackedVectorBase;
24*9880d681SAndroid Build Coastguard Worker 
25*9880d681SAndroid Build Coastguard Worker // This won't be necessary if we can specialize members without specializing
26*9880d681SAndroid Build Coastguard Worker // the parent template.
27*9880d681SAndroid Build Coastguard Worker template <typename T, unsigned BitNum, typename BitVectorTy>
28*9880d681SAndroid Build Coastguard Worker class PackedVectorBase<T, BitNum, BitVectorTy, false> {
29*9880d681SAndroid Build Coastguard Worker protected:
getValue(const BitVectorTy & Bits,unsigned Idx)30*9880d681SAndroid Build Coastguard Worker   static T getValue(const BitVectorTy &Bits, unsigned Idx) {
31*9880d681SAndroid Build Coastguard Worker     T val = T();
32*9880d681SAndroid Build Coastguard Worker     for (unsigned i = 0; i != BitNum; ++i)
33*9880d681SAndroid Build Coastguard Worker       val = T(val | ((Bits[(Idx << (BitNum-1)) + i] ? 1UL : 0UL) << i));
34*9880d681SAndroid Build Coastguard Worker     return val;
35*9880d681SAndroid Build Coastguard Worker   }
36*9880d681SAndroid Build Coastguard Worker 
setValue(BitVectorTy & Bits,unsigned Idx,T val)37*9880d681SAndroid Build Coastguard Worker   static void setValue(BitVectorTy &Bits, unsigned Idx, T val) {
38*9880d681SAndroid Build Coastguard Worker     assert((val >> BitNum) == 0 && "value is too big");
39*9880d681SAndroid Build Coastguard Worker     for (unsigned i = 0; i != BitNum; ++i)
40*9880d681SAndroid Build Coastguard Worker       Bits[(Idx << (BitNum-1)) + i] = val & (T(1) << i);
41*9880d681SAndroid Build Coastguard Worker   }
42*9880d681SAndroid Build Coastguard Worker };
43*9880d681SAndroid Build Coastguard Worker 
44*9880d681SAndroid Build Coastguard Worker template <typename T, unsigned BitNum, typename BitVectorTy>
45*9880d681SAndroid Build Coastguard Worker class PackedVectorBase<T, BitNum, BitVectorTy, true> {
46*9880d681SAndroid Build Coastguard Worker protected:
getValue(const BitVectorTy & Bits,unsigned Idx)47*9880d681SAndroid Build Coastguard Worker   static T getValue(const BitVectorTy &Bits, unsigned Idx) {
48*9880d681SAndroid Build Coastguard Worker     T val = T();
49*9880d681SAndroid Build Coastguard Worker     for (unsigned i = 0; i != BitNum-1; ++i)
50*9880d681SAndroid Build Coastguard Worker       val = T(val | ((Bits[(Idx << (BitNum-1)) + i] ? 1UL : 0UL) << i));
51*9880d681SAndroid Build Coastguard Worker     if (Bits[(Idx << (BitNum-1)) + BitNum-1])
52*9880d681SAndroid Build Coastguard Worker       val = ~val;
53*9880d681SAndroid Build Coastguard Worker     return val;
54*9880d681SAndroid Build Coastguard Worker   }
55*9880d681SAndroid Build Coastguard Worker 
setValue(BitVectorTy & Bits,unsigned Idx,T val)56*9880d681SAndroid Build Coastguard Worker   static void setValue(BitVectorTy &Bits, unsigned Idx, T val) {
57*9880d681SAndroid Build Coastguard Worker     if (val < 0) {
58*9880d681SAndroid Build Coastguard Worker       val = ~val;
59*9880d681SAndroid Build Coastguard Worker       Bits.set((Idx << (BitNum-1)) + BitNum-1);
60*9880d681SAndroid Build Coastguard Worker     }
61*9880d681SAndroid Build Coastguard Worker     assert((val >> (BitNum-1)) == 0 && "value is too big");
62*9880d681SAndroid Build Coastguard Worker     for (unsigned i = 0; i != BitNum-1; ++i)
63*9880d681SAndroid Build Coastguard Worker       Bits[(Idx << (BitNum-1)) + i] = val & (T(1) << i);
64*9880d681SAndroid Build Coastguard Worker   }
65*9880d681SAndroid Build Coastguard Worker };
66*9880d681SAndroid Build Coastguard Worker 
67*9880d681SAndroid Build Coastguard Worker /// \brief Store a vector of values using a specific number of bits for each
68*9880d681SAndroid Build Coastguard Worker /// value. Both signed and unsigned types can be used, e.g
69*9880d681SAndroid Build Coastguard Worker /// @code
70*9880d681SAndroid Build Coastguard Worker ///   PackedVector<signed, 2> vec;
71*9880d681SAndroid Build Coastguard Worker /// @endcode
72*9880d681SAndroid Build Coastguard Worker /// will create a vector accepting values -2, -1, 0, 1. Any other value will hit
73*9880d681SAndroid Build Coastguard Worker /// an assertion.
74*9880d681SAndroid Build Coastguard Worker template <typename T, unsigned BitNum, typename BitVectorTy = BitVector>
75*9880d681SAndroid Build Coastguard Worker class PackedVector : public PackedVectorBase<T, BitNum, BitVectorTy,
76*9880d681SAndroid Build Coastguard Worker                                             std::numeric_limits<T>::is_signed> {
77*9880d681SAndroid Build Coastguard Worker   BitVectorTy Bits;
78*9880d681SAndroid Build Coastguard Worker   typedef PackedVectorBase<T, BitNum, BitVectorTy,
79*9880d681SAndroid Build Coastguard Worker                            std::numeric_limits<T>::is_signed> base;
80*9880d681SAndroid Build Coastguard Worker 
81*9880d681SAndroid Build Coastguard Worker public:
82*9880d681SAndroid Build Coastguard Worker   class reference {
83*9880d681SAndroid Build Coastguard Worker     PackedVector &Vec;
84*9880d681SAndroid Build Coastguard Worker     const unsigned Idx;
85*9880d681SAndroid Build Coastguard Worker 
86*9880d681SAndroid Build Coastguard Worker     reference(); // Undefined
87*9880d681SAndroid Build Coastguard Worker   public:
reference(PackedVector & vec,unsigned idx)88*9880d681SAndroid Build Coastguard Worker     reference(PackedVector &vec, unsigned idx) : Vec(vec), Idx(idx) {}
89*9880d681SAndroid Build Coastguard Worker 
90*9880d681SAndroid Build Coastguard Worker     reference &operator=(T val) {
91*9880d681SAndroid Build Coastguard Worker       Vec.setValue(Vec.Bits, Idx, val);
92*9880d681SAndroid Build Coastguard Worker       return *this;
93*9880d681SAndroid Build Coastguard Worker     }
T()94*9880d681SAndroid Build Coastguard Worker     operator T() const {
95*9880d681SAndroid Build Coastguard Worker       return Vec.getValue(Vec.Bits, Idx);
96*9880d681SAndroid Build Coastguard Worker     }
97*9880d681SAndroid Build Coastguard Worker   };
98*9880d681SAndroid Build Coastguard Worker 
99*9880d681SAndroid Build Coastguard Worker   PackedVector() = default;
PackedVector(unsigned size)100*9880d681SAndroid Build Coastguard Worker   explicit PackedVector(unsigned size) : Bits(size << (BitNum-1)) { }
101*9880d681SAndroid Build Coastguard Worker 
empty()102*9880d681SAndroid Build Coastguard Worker   bool empty() const { return Bits.empty(); }
103*9880d681SAndroid Build Coastguard Worker 
size()104*9880d681SAndroid Build Coastguard Worker   unsigned size() const { return Bits.size() >> (BitNum - 1); }
105*9880d681SAndroid Build Coastguard Worker 
clear()106*9880d681SAndroid Build Coastguard Worker   void clear() { Bits.clear(); }
107*9880d681SAndroid Build Coastguard Worker 
resize(unsigned N)108*9880d681SAndroid Build Coastguard Worker   void resize(unsigned N) { Bits.resize(N << (BitNum - 1)); }
109*9880d681SAndroid Build Coastguard Worker 
reserve(unsigned N)110*9880d681SAndroid Build Coastguard Worker   void reserve(unsigned N) { Bits.reserve(N << (BitNum-1)); }
111*9880d681SAndroid Build Coastguard Worker 
reset()112*9880d681SAndroid Build Coastguard Worker   PackedVector &reset() {
113*9880d681SAndroid Build Coastguard Worker     Bits.reset();
114*9880d681SAndroid Build Coastguard Worker     return *this;
115*9880d681SAndroid Build Coastguard Worker   }
116*9880d681SAndroid Build Coastguard Worker 
push_back(T val)117*9880d681SAndroid Build Coastguard Worker   void push_back(T val) {
118*9880d681SAndroid Build Coastguard Worker     resize(size()+1);
119*9880d681SAndroid Build Coastguard Worker     (*this)[size()-1] = val;
120*9880d681SAndroid Build Coastguard Worker   }
121*9880d681SAndroid Build Coastguard Worker 
122*9880d681SAndroid Build Coastguard Worker   reference operator[](unsigned Idx) {
123*9880d681SAndroid Build Coastguard Worker     return reference(*this, Idx);
124*9880d681SAndroid Build Coastguard Worker   }
125*9880d681SAndroid Build Coastguard Worker 
126*9880d681SAndroid Build Coastguard Worker   T operator[](unsigned Idx) const {
127*9880d681SAndroid Build Coastguard Worker     return base::getValue(Bits, Idx);
128*9880d681SAndroid Build Coastguard Worker   }
129*9880d681SAndroid Build Coastguard Worker 
130*9880d681SAndroid Build Coastguard Worker   bool operator==(const PackedVector &RHS) const {
131*9880d681SAndroid Build Coastguard Worker     return Bits == RHS.Bits;
132*9880d681SAndroid Build Coastguard Worker   }
133*9880d681SAndroid Build Coastguard Worker 
134*9880d681SAndroid Build Coastguard Worker   bool operator!=(const PackedVector &RHS) const {
135*9880d681SAndroid Build Coastguard Worker     return Bits != RHS.Bits;
136*9880d681SAndroid Build Coastguard Worker   }
137*9880d681SAndroid Build Coastguard Worker 
138*9880d681SAndroid Build Coastguard Worker   PackedVector &operator|=(const PackedVector &RHS) {
139*9880d681SAndroid Build Coastguard Worker     Bits |= RHS.Bits;
140*9880d681SAndroid Build Coastguard Worker     return *this;
141*9880d681SAndroid Build Coastguard Worker   }
142*9880d681SAndroid Build Coastguard Worker };
143*9880d681SAndroid Build Coastguard Worker 
144*9880d681SAndroid Build Coastguard Worker // Leave BitNum=0 undefined.
145*9880d681SAndroid Build Coastguard Worker template <typename T> class PackedVector<T, 0>;
146*9880d681SAndroid Build Coastguard Worker 
147*9880d681SAndroid Build Coastguard Worker } // end llvm namespace
148*9880d681SAndroid Build Coastguard Worker 
149*9880d681SAndroid Build Coastguard Worker #endif
150