Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-02-14 12:53:57

0001 #ifndef DataFormats_L1TrackTrigger_TTBV_h
0002 #define DataFormats_L1TrackTrigger_TTBV_h
0003 
0004 #include <bitset>
0005 #include <array>
0006 #include <string>
0007 #include <algorithm>
0008 #include <cmath>
0009 #include <utility>
0010 
0011 /*! 
0012  * \class  TTBV
0013  * \brief  Bit vector used by Track Trigger emulators. Mainly used to convert
0014  *         integers into arbitrary (within margin) sized two's complement string.
0015  * \author Thomas Schuh
0016  * \date   2020, Jan
0017  */
0018 class TTBV {
0019 public:
0020   static constexpr int S = 64;  // Frame width of emp infrastructure f/w, max number of bits a TTBV can handle
0021 
0022 private:
0023   bool twos_;          // Two's complement (true) or binary (false)
0024   int size_;           // number or bits
0025   std::bitset<S> bs_;  // underlying storage
0026 
0027 public:
0028   // constructor: default
0029   TTBV() : twos_(false), size_(S), bs_(std::bitset<S>(0)) {}
0030 
0031   // constructor: double precision (IEEE 754); from most to least significant bit: 1 bit sign + 11 bit binary exponent + 52 bit binary mantisse
0032   TTBV(const double d) : twos_(false), size_(S) {
0033     int index(0);
0034     const char* c = reinterpret_cast<const char*>(&d);
0035     for (int iByte = 0; iByte < (int)sizeof(d); iByte++) {
0036       const std::bitset<std::numeric_limits<unsigned char>::digits> byte(*(c + iByte));
0037       for (int bit = 0; bit < std::numeric_limits<unsigned char>::digits; bit++)
0038         bs_[index++] = byte[bit];
0039     }
0040   }
0041 
0042   // constructor: unsigned int value
0043   TTBV(unsigned long long int value, int size) : twos_(false), size_(size), bs_(std::bitset<S>(value)) {}
0044 
0045   // constructor: int value
0046   TTBV(int value, int size, bool Signed = false)
0047       : twos_(Signed), size_(size), bs_(std::bitset<S>((!Signed || value >= 0) ? value : value + iMax())) {}
0048 
0049   // constructor: double value + precision, biased (floor) representation
0050   TTBV(double value, double base, int size, bool Signed = false) : TTBV((int)std::floor(value / base), size, Signed) {}
0051 
0052   // constructor: string
0053   TTBV(const std::string& str, bool Signed = false) : twos_(Signed), size_(str.size()), bs_(std::bitset<S>(str)) {}
0054 
0055   // constructor: bitset
0056   TTBV(const std::bitset<S>& bs, bool Signed = false) : twos_(Signed), size_(S), bs_(std::bitset<S>(bs)) {}
0057 
0058   // access: data members
0059   bool twos() const { return twos_; }
0060   int size() const { return size_; }
0061   std::bitset<S> bs() const { return bs_; }
0062 
0063   // access: single bit
0064   bool operator[](int pos) const { return bs_[pos]; }
0065   std::bitset<S>::reference operator[](int pos) { return bs_[pos]; }
0066 
0067   // access: most significant bit
0068   bool msb() const { return bs_[size_ - 1]; }
0069   std::bitset<S>::reference msb() { return bs_[size_ - 1]; }
0070 
0071   // access: members of underlying bitset
0072   bool all() const { return bs_.all(); }
0073   bool any() const { return bs_.any(); }
0074   bool none() const { return bs_.none(); }
0075   int count() const { return bs_.count(); }
0076 
0077   // operator: comparisons
0078   bool operator==(const TTBV& rhs) const { return bs_ == rhs.bs_; }
0079   bool operator!=(const TTBV& rhs) const { return bs_ != rhs.bs_; }
0080 
0081   // operator: boolean and, or, xor, not
0082   TTBV& operator&=(const TTBV& rhs) {
0083     const int m(std::max(size_, rhs.size()));
0084     this->resize(m);
0085     TTBV bv(rhs);
0086     bv.resize(m);
0087     bs_ &= bv.bs_;
0088     return *this;
0089   }
0090   TTBV& operator|=(const TTBV& rhs) {
0091     const int m(std::max(size_, rhs.size()));
0092     this->resize(m);
0093     TTBV bv(rhs);
0094     bv.resize(m);
0095     bs_ |= bv.bs_;
0096     return *this;
0097   }
0098   TTBV& operator^=(const TTBV& rhs) {
0099     const int m(std::max(size_, rhs.size()));
0100     this->resize(m);
0101     TTBV bv(rhs);
0102     bv.resize(m);
0103     bs_ ^= bv.bs_;
0104     return *this;
0105   }
0106   TTBV operator~() const {
0107     TTBV bv(*this);
0108     return bv.flip();
0109   }
0110 
0111   // operator: bit shifts
0112   TTBV& operator>>=(int pos) {
0113     bs_ >>= pos;
0114     size_ -= pos;
0115     return *this;
0116   }
0117   TTBV& operator<<=(int pos) {
0118     bs_ <<= S - size_ + pos;
0119     bs_ >>= S - size_ + pos;
0120     size_ -= pos;
0121     return *this;
0122   }
0123   TTBV operator<<(int pos) const {
0124     TTBV bv(*this);
0125     return bv >>= pos;
0126   }
0127   TTBV operator>>(int pos) const {
0128     TTBV bv(*this);
0129     return bv <<= pos;
0130   }
0131 
0132   // operator: concatenation
0133   TTBV& operator+=(const TTBV& rhs) {
0134     bs_ <<= rhs.size();
0135     bs_ |= rhs.bs_;
0136     size_ += rhs.size();
0137     return *this;
0138   }
0139   TTBV operator+(const TTBV& rhs) const {
0140     TTBV lhs(*this);
0141     return lhs += rhs;
0142   }
0143 
0144   // operator: value increment, overflow protected
0145   TTBV& operator++() {
0146     bs_ = std::bitset<S>(bs_.to_ullong() + 1);
0147     this->resize(size_);
0148     return *this;
0149   }
0150 
0151   // manipulation: all bits
0152   TTBV& reset() {
0153     bs_.reset();
0154     return *this;
0155   }
0156   TTBV& set() {
0157     for (int n = 0; n < size_; n++)
0158       bs_.set(n);
0159     return *this;
0160   }
0161   TTBV& flip() {
0162     for (int n = 0; n < size_; n++)
0163       bs_.flip(n);
0164     return *this;
0165   }
0166 
0167   // manipulation: single bit
0168   TTBV& reset(int pos) {
0169     bs_.reset(pos);
0170     return *this;
0171   }
0172   TTBV& set(int pos) {
0173     bs_.set(pos);
0174     return *this;
0175   }
0176   TTBV& flip(int pos) {
0177     bs_.flip(pos);
0178     return *this;
0179   }
0180 
0181   // manipulation: biased absolute value
0182   TTBV& abs() {
0183     if (twos_) {
0184       twos_ = false;
0185       if (this->msb()) {
0186         this->flip();
0187         this->operator++();
0188       }
0189       size_--;
0190     }
0191     return *this;
0192   }
0193 
0194   // manipulation: resize
0195   TTBV& resize(int size) {
0196     bool msb = this->msb();
0197     if (size > size_) {
0198       if (twos_)
0199         for (int n = size_; n < size; n++)
0200           bs_.set(n, msb);
0201       size_ = size;
0202     } else if (size < size_ && size > 0) {
0203       this->operator<<=(size - size_);
0204       if (twos_)
0205         this->msb() = msb;
0206     }
0207     return *this;
0208   }
0209 
0210   // conversion: to string
0211   std::string str() const { return bs_.to_string().substr(S - size_, S); }
0212 
0213   // conversion: range based to string
0214   std::string str(int start, int end = 0) const { return this->str().substr(size_ - start, size_ - end); }
0215 
0216   // conversion: to int
0217   int val() const { return (twos_ && this->msb()) ? (int)bs_.to_ullong() - iMax() : bs_.to_ullong(); }
0218 
0219   // conversion: to int, reinterpret sign
0220   int val(bool Signed) const { return (Signed && this->msb()) ? (int)bs_.to_ullong() - iMax() : bs_.to_ullong(); }
0221 
0222   // conversion: range based to int, reinterpret sign
0223   int val(int start, int end = 0, bool Signed = false) const { return TTBV(this->str(start, end), Signed).val(); }
0224 
0225   // conversion: to double for given precision assuming biased (floor) representation
0226   double val(double base) const { return (this->val() + .5) * base; }
0227 
0228   // range based count of '1's or '0's
0229   int count(int begin, int end, bool b = true) const {
0230     int c(0);
0231     for (int i = begin; i < end; i++)
0232       if (bs_[i] == b)
0233         c++;
0234     return c;
0235   }
0236 
0237   // position of least significant '1' or '0'
0238   int plEncode(bool b = true) const {
0239     for (int e = 0; e < size_; e++)
0240       if (bs_[e] == b)
0241         return e;
0242     return size_;
0243   }
0244 
0245   // position of most significant '1' or '0'
0246   int pmEncode(bool b = true) const {
0247     for (int e = size_ - 1; e > -1; e--)
0248       if (bs_[e] == b)
0249         return e;
0250     return size_;
0251   }
0252 
0253 private:
0254   // look up table initializer for powers of 2
0255   constexpr std::array<unsigned long long int, S> powersOfTwo() const {
0256     std::array<unsigned long long int, S> lut = {};
0257     for (int i = 0; i < S; i++)
0258       lut[i] = std::pow(2, i);
0259     return lut;
0260   }
0261 
0262   // returns 2 ** size_
0263   unsigned long long int iMax() const {
0264     static const std::array<unsigned long long int, S> lut = powersOfTwo();
0265     return lut[size_];
0266   }
0267 };
0268 
0269 #endif