LLVM API Documentation

PackedVector.h
Go to the documentation of this file.
00001 //===- llvm/ADT/PackedVector.h - Packed values vector -----------*- C++ -*-===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // This file implements the PackedVector class.
00011 //
00012 //===----------------------------------------------------------------------===//
00013 
00014 #ifndef LLVM_ADT_PACKEDVECTOR_H
00015 #define LLVM_ADT_PACKEDVECTOR_H
00016 
00017 #include "llvm/ADT/BitVector.h"
00018 #include <limits>
00019 
00020 namespace llvm {
00021 
00022 template <typename T, unsigned BitNum, typename BitVectorTy, bool isSigned>
00023 class PackedVectorBase;
00024 
00025 // This won't be necessary if we can specialize members without specializing
00026 // the parent template.
00027 template <typename T, unsigned BitNum, typename BitVectorTy>
00028 class PackedVectorBase<T, BitNum, BitVectorTy, false> {
00029 protected:
00030   static T getValue(const BitVectorTy &Bits, unsigned Idx) {
00031     T val = T();
00032     for (unsigned i = 0; i != BitNum; ++i)
00033       val = T(val | ((Bits[(Idx << (BitNum-1)) + i] ? 1UL : 0UL) << i));
00034     return val;
00035   }
00036 
00037   static void setValue(BitVectorTy &Bits, unsigned Idx, T val) {
00038     assert((val >> BitNum) == 0 && "value is too big");
00039     for (unsigned i = 0; i != BitNum; ++i)
00040       Bits[(Idx << (BitNum-1)) + i] = val & (T(1) << i);
00041   }
00042 };
00043 
00044 template <typename T, unsigned BitNum, typename BitVectorTy>
00045 class PackedVectorBase<T, BitNum, BitVectorTy, true> {
00046 protected:
00047   static T getValue(const BitVectorTy &Bits, unsigned Idx) {
00048     T val = T();
00049     for (unsigned i = 0; i != BitNum-1; ++i)
00050       val = T(val | ((Bits[(Idx << (BitNum-1)) + i] ? 1UL : 0UL) << i));
00051     if (Bits[(Idx << (BitNum-1)) + BitNum-1])
00052       val = ~val;
00053     return val;
00054   }
00055 
00056   static void setValue(BitVectorTy &Bits, unsigned Idx, T val) {
00057     if (val < 0) {
00058       val = ~val;
00059       Bits.set((Idx << (BitNum-1)) + BitNum-1);
00060     }
00061     assert((val >> (BitNum-1)) == 0 && "value is too big");
00062     for (unsigned i = 0; i != BitNum-1; ++i)
00063       Bits[(Idx << (BitNum-1)) + i] = val & (T(1) << i);
00064   }
00065 };
00066 
00067 /// \brief Store a vector of values using a specific number of bits for each
00068 /// value. Both signed and unsigned types can be used, e.g
00069 /// @code
00070 ///   PackedVector<signed, 2> vec;
00071 /// @endcode
00072 /// will create a vector accepting values -2, -1, 0, 1. Any other value will hit
00073 /// an assertion.
00074 template <typename T, unsigned BitNum, typename BitVectorTy = BitVector>
00075 class PackedVector : public PackedVectorBase<T, BitNum, BitVectorTy,
00076                                             std::numeric_limits<T>::is_signed> {
00077   BitVectorTy Bits;
00078   typedef PackedVectorBase<T, BitNum, BitVectorTy,
00079                            std::numeric_limits<T>::is_signed> base;
00080 
00081 public:
00082   class reference {
00083     PackedVector &Vec;
00084     const unsigned Idx;
00085 
00086     reference();  // Undefined    
00087   public:
00088     reference(PackedVector &vec, unsigned idx) : Vec(vec), Idx(idx) { }    
00089 
00090     reference &operator=(T val) {
00091       Vec.setValue(Vec.Bits, Idx, val);
00092       return *this;
00093     }
00094     operator T() const {
00095       return Vec.getValue(Vec.Bits, Idx);
00096     }
00097   };
00098 
00099   PackedVector() { }
00100   explicit PackedVector(unsigned size) : Bits(size << (BitNum-1)) { }
00101 
00102   bool empty() const { return Bits.empty(); }
00103 
00104   unsigned size() const { return Bits.size() >> (BitNum-1); }
00105   
00106   void clear() { Bits.clear(); }
00107   
00108   void resize(unsigned N) { Bits.resize(N << (BitNum-1)); }
00109 
00110   void reserve(unsigned N) { Bits.reserve(N << (BitNum-1)); }
00111 
00112   PackedVector &reset() {
00113     Bits.reset();
00114     return *this;
00115   }
00116 
00117   void push_back(T val) {
00118     resize(size()+1);
00119     (*this)[size()-1] = val;
00120   }
00121 
00122   reference operator[](unsigned Idx) {
00123     return reference(*this, Idx);
00124   }
00125 
00126   T operator[](unsigned Idx) const {
00127     return base::getValue(Bits, Idx);
00128   }
00129 
00130   bool operator==(const PackedVector &RHS) const {
00131     return Bits == RHS.Bits;
00132   }
00133 
00134   bool operator!=(const PackedVector &RHS) const {
00135     return Bits != RHS.Bits;
00136   }
00137 
00138   const PackedVector &operator=(const PackedVector &RHS) {
00139     Bits = RHS.Bits;
00140     return *this;
00141   }
00142 
00143   PackedVector &operator|=(const PackedVector &RHS) {
00144     Bits |= RHS.Bits;
00145     return *this;
00146   }
00147 
00148   void swap(PackedVector &RHS) {
00149     Bits.swap(RHS.Bits);
00150   }
00151 };
00152 
00153 // Leave BitNum=0 undefined. 
00154 template <typename T>
00155 class PackedVector<T, 0>;
00156 
00157 } // end llvm namespace
00158 
00159 #endif