Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-09-02 03:45:50

0001 #ifndef L1GCTUNSIGNEDINT_H
0002 #define L1GCTUNSIGNEDINT_H
0003 
0004 #include <ostream>
0005 
0006 /*!
0007  * \class L1GctUnsignedInt
0008  * \brief Definition of unsigned integer types with overflow
0009  *
0010  * This file defines the template class L1GctUnsignedInt. It is used
0011  * to store energy values that are represented in a given number of bits
0012  * in hardware. The type has a built-in overFlow that is set if the value
0013  * to be represented is outside the allowed range for that number of bits.
0014  * This type represents unsigned integers; signed integers are represented
0015  * by L1GctTwosComplement. Functions are defined to add two values,
0016  * and to copy data into a different number of bits.
0017  *
0018  * this header file contains method definitions because these are template classes
0019  * see http://www.parashift.com/c++-faq-lite/templates.html#faq-35.12
0020  *
0021  * \author Jim Brooke & Greg Heath
0022  * \date May 2006
0023  * 
0024  */
0025 
0026 template <int nBits>
0027 class L1GctUnsignedInt {
0028 public:
0029   /// Construct an unsigned integer with initial value zero
0030   L1GctUnsignedInt();
0031   /// Construct an unsigned integer and check for overFlow
0032   L1GctUnsignedInt(unsigned value);
0033   /// Destructor
0034   ~L1GctUnsignedInt();
0035 
0036   /// Copy contructor to move data between representations with different numbers of bits
0037   template <int mBits>
0038   L1GctUnsignedInt(const L1GctUnsignedInt<mBits>& rhs);
0039 
0040   /// reset value and overflow to zero
0041   void reset() {
0042     m_value = static_cast<unsigned>(0);
0043     m_overFlow = false;
0044   }
0045 
0046   /// Set value from unsigned
0047   void setValue(unsigned value);
0048 
0049   /// set the overflow bit
0050   void setOverFlow(bool oflow) { m_overFlow = oflow; }
0051 
0052   /// access value as unsigned
0053   unsigned value() const { return m_value; }
0054 
0055   /// access overflow
0056   bool overFlow() const { return m_overFlow; }
0057 
0058   /// return number of bits
0059   int size() const { return m_nBits; }
0060 
0061   /// add two numbers
0062   L1GctUnsignedInt operator+(const L1GctUnsignedInt& rhs) const;
0063 
0064   /// overload = operator
0065   L1GctUnsignedInt& operator=(int value);
0066 
0067 protected:
0068   // number of bits
0069   int m_nBits;
0070 
0071   // value
0072   unsigned m_value;
0073 
0074   // overflow
0075   bool m_overFlow;
0076 
0077   static const int MAX_NBITS = 24;
0078 };
0079 
0080 template <int nBits>
0081 std::ostream& operator<<(std::ostream& s, const L1GctUnsignedInt<nBits>& data);
0082 
0083 template <int nBits>
0084 L1GctUnsignedInt<nBits>::L1GctUnsignedInt() {
0085   m_nBits = nBits > 0 && nBits < MAX_NBITS ? nBits : 16;
0086   this->reset();
0087 }
0088 
0089 template <int nBits>
0090 L1GctUnsignedInt<nBits>::L1GctUnsignedInt(unsigned value) {
0091   m_nBits = nBits > 0 && nBits < MAX_NBITS ? nBits : 16;
0092   m_overFlow = false;
0093   this->setValue(value);
0094 }
0095 
0096 template <int nBits>
0097 L1GctUnsignedInt<nBits>::~L1GctUnsignedInt() {}
0098 
0099 // copy contructor to move data between
0100 // representations with different numbers of bits
0101 template <int nBits>
0102 template <int mBits>
0103 L1GctUnsignedInt<nBits>::L1GctUnsignedInt(const L1GctUnsignedInt<mBits>& rhs) {
0104   m_nBits = nBits > 0 && nBits < MAX_NBITS ? nBits : 16;
0105   this->setValue(rhs.value());
0106   this->setOverFlow(this->overFlow() || rhs.overFlow());
0107 }
0108 
0109 // set value, checking for overflow
0110 template <int nBits>
0111 void L1GctUnsignedInt<nBits>::setValue(unsigned value) {
0112   // check for overflow
0113   if (value >= (static_cast<unsigned>(1 << m_nBits))) {
0114     m_overFlow = true;
0115   }
0116 
0117   // set value with bitmask
0118   m_value = value & ((1 << m_nBits) - 1);
0119 }
0120 
0121 // add two unsigneds
0122 template <int nBits>
0123 L1GctUnsignedInt<nBits> L1GctUnsignedInt<nBits>::operator+(const L1GctUnsignedInt<nBits>& rhs) const {
0124   // temporary variable for storing the result (need to set its size)
0125   L1GctUnsignedInt<nBits> temp;
0126 
0127   unsigned sum;
0128   bool ofl;
0129 
0130   // do the addition here
0131   sum = this->value() + rhs.value();
0132   ofl = this->overFlow() || rhs.overFlow();
0133 
0134   //fill the temporary argument
0135   temp.setValue(sum);
0136   temp.setOverFlow(temp.overFlow() || ofl);
0137 
0138   // return the temporary
0139   return temp;
0140 }
0141 
0142 // overload assignment by int
0143 template <int nBits>
0144 L1GctUnsignedInt<nBits>& L1GctUnsignedInt<nBits>::operator=(int value) {
0145   this->setValue(value);
0146   return *this;
0147 }
0148 
0149 // overload ostream<<
0150 template <int nBits>
0151 std::ostream& operator<<(std::ostream& s, const L1GctUnsignedInt<nBits>& data) {
0152   s << "L1GctUnsignedInt value : " << data.value();
0153   if (data.overFlow()) {
0154     s << " Overflow set! ";
0155   }
0156 
0157   return s;
0158 }
0159 
0160 #endif