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