11#ifndef DataFormats_L1TrackTrigger_TTBV_h
22#define DataFormats_L1TrackTrigger_TTBV_h
33
4+ #include " FWCore/Utilities/interface/Exception.h"
5+
46#include < bitset>
57#include < array>
68#include < string>
2022class TTBV {
2123public:
2224 static constexpr int S_ = 64 ; // Frame width of emp infrastructure f/w, max number of bits a TTBV can handle
23-
2425private:
2526 bool twos_; // Two's complement (true) or binary (false)
2627 int size_; // number or bits
2728 std::bitset<S_> bs_; // underlying storage
28-
2929public:
3030 // constructor: default
3131 TTBV () : twos_(false ), size_(0 ), bs_() {}
32-
3332 // constructor: double precision (IEEE 754); from most to least significant bit: 1 bit sign + 11 bit binary exponent + 52 bit binary mantisse
3433 TTBV (const double d) : twos_(false ), size_(S_) {
3534 int index (0 );
@@ -42,14 +41,17 @@ class TTBV {
4241 }
4342
4443 // constructor: unsigned int value
45- TTBV (unsigned long long int value, int size) : twos_(false ), size_(size), bs_(value) {}
44+ TTBV (unsigned long long int value, int size) : twos_(false ), size_(size), bs_(value) { checkU (value); }
4645
4746 // constructor: int value
4847 TTBV (int value, int size, bool twos = false )
49- : twos_(twos), size_(size), bs_((!twos || value >= 0 ) ? value : value + iMax()) {}
48+ : twos_(twos), size_(size), bs_((!twos || value >= 0 ) ? value : value + iMax()) {
49+ checkI (value);
50+ }
5051
5152 // constructor: double value + precision, biased (floor) representation
52- TTBV (double value, double base, int size, bool twos = false ) : TTBV((int )std::floor(value / base), size, twos) {}
53+ TTBV (double value, double base, int size, bool twos = false )
54+ : TTBV((int )std::floor(value / base + 1 .e-12 ), size, twos) {}
5355
5456 // constructor: string
5557 TTBV (const std::string& str, bool twos = false ) : twos_(twos), size_(str.size()), bs_(str) {}
@@ -70,10 +72,15 @@ class TTBV {
7072 // underlying storage
7173 const std::bitset<S_>& bs () const { return bs_; }
7274
73- // access: single bit
75+ // access: single bit value
7476 bool operator [](int pos) const { return bs_[pos]; }
77+
78+ // access: single bit reference
7579 std::bitset<S_>::reference operator [](int pos) { return bs_[pos]; }
7680
81+ // access: single bit value with bounds check
82+ bool test (int pos) const { return bs_.test (pos); }
83+
7784 // access: most significant bit copy
7885 bool msb () const { return bs_[size_ - 1 ]; }
7986
@@ -95,31 +102,31 @@ class TTBV {
95102
96103 // operator: boolean and
97104 TTBV& operator &=(const TTBV& rhs) {
98- const int m (std::max (size_, rhs.size ()));
99- this ->resize (m);
100- TTBV bv (rhs);
101- bv.resize (m);
102- bs_ &= bv.bs_ ;
105+ bs_ &= rhs.bs_ ;
103106 return *this ;
104107 }
105108
109+ // operator: boolean and
110+ TTBV operator &&(const TTBV& rhs) {
111+ TTBV copy (*this );
112+ return copy &= rhs;
113+ }
114+
106115 // operator: boolean or
107116 TTBV& operator |=(const TTBV& rhs) {
108- const int m (std::max (size_, rhs.size ()));
109- this ->resize (m);
110- TTBV bv (rhs);
111- bv.resize (m);
112- bs_ |= bv.bs_ ;
117+ bs_ |= rhs.bs_ ;
113118 return *this ;
114119 }
115120
121+ // operator: boolean or
122+ TTBV operator ||(const TTBV& rhs) {
123+ TTBV copy (*this );
124+ return copy |= rhs;
125+ }
126+
116127 // operator: boolean xor
117128 TTBV& operator ^=(const TTBV& rhs) {
118- const int m (std::max (size_, rhs.size ()));
119- this ->resize (m);
120- TTBV bv (rhs);
121- bv.resize (m);
122- bs_ ^= bv.bs_ ;
129+ bs_ ^= rhs.bs_ ;
123130 return *this ;
124131 }
125132
@@ -242,7 +249,7 @@ class TTBV {
242249 bs_.set (n, msb);
243250 size_ = size;
244251 } else if (size < size_ && size > 0 ) {
245- this ->operator <<=(size - size_ );
252+ this ->operator <<=(size_ - size );
246253 if (twos_)
247254 this ->msb () = msb;
248255 }
@@ -281,11 +288,18 @@ class TTBV {
281288
282289 // maniplulation and conversion: extracts range based to int reinterpret sign and removes these bits
283290 int extract (int size, bool twos = false ) {
284- double val = this ->val (size, 0 , twos);
291+ int val = this ->val (size, 0 , twos);
285292 this ->operator >>=(size);
286293 return val;
287294 }
288295
296+ // maniplulation and conversion: extracts bool and removes this bit
297+ bool extract () {
298+ bool val = bs_[0 ];
299+ this ->operator >>=(1 );
300+ return val;
301+ }
302+
289303 // manipulation: extracts slice and removes these bits
290304 TTBV slice (int size, bool twos = false ) {
291305 TTBV ttBV (*this , size, 0 , twos);
@@ -310,6 +324,14 @@ class TTBV {
310324 return size_;
311325 }
312326
327+ // position of least significant '1' or '0' in range [begin, end)
328+ int plEncode (int begin, int end, bool b = true ) const {
329+ for (int e = begin; e < end; e++)
330+ if (bs_.test (e) == b)
331+ return e;
332+ return size_;
333+ }
334+
313335 // position of most significant '1' or '0'
314336 int pmEncode (bool b = true ) const {
315337 for (int e = size_ - 1 ; e > -1 ; e--)
@@ -318,6 +340,14 @@ class TTBV {
318340 return size_;
319341 }
320342
343+ // position of most significant '1' or '0' in range [begin, end)
344+ int pmEncode (int begin, int end, bool b = true ) const {
345+ for (int e = end - 1 ; e >= begin; e--)
346+ if (bs_.test (e) == b)
347+ return e;
348+ return end;
349+ }
350+
321351 // position for n'th '1' or '0' counted from least to most significant bit
322352 int encode (int n, bool b = true ) const {
323353 int sum (0 );
@@ -344,17 +374,58 @@ class TTBV {
344374
345375private:
346376 // look up table initializer for powers of 2
347- constexpr std::array<unsigned long long int , S_> powersOfTwo () const {
348- std::array<unsigned long long int , S_> lut = {};
349- for (int i = 0 ; i < S_; i++)
377+ constexpr std::array<double , S_ + 1 > powersOfTwo () const {
378+ std::array<double , S_ + 1 > lut = {};
379+ for (int i = 0 ; i <= S_; i++)
350380 lut[i] = std::pow (2 , i);
351381 return lut;
352382 }
353383
354384 // returns 2 ** size_
355- unsigned long long int iMax () const {
356- static const std::array<unsigned long long int , S_> lut = powersOfTwo ();
357- return lut[size_];
385+ double iMax () const {
386+ static const std::array<double , S_ + 1 > lut = powersOfTwo ();
387+ return std::round (lut[size_]);
388+ }
389+
390+ // check if value fits into binary BV
391+ void checkU (unsigned long long int value) {
392+ if (size_ == 0 )
393+ return ;
394+ if (value < iMax ())
395+ return ;
396+ cms::Exception exception (" RunTimeError." );
397+ exception << " Value " << value << " does not fit into a " << size_ << " b binary." ;
398+ exception.addContext (" TTBV::checkU" );
399+ throw exception;
400+ }
401+
402+ // check if value fits into twos's complement BV
403+ void checkT (int value) {
404+ if (size_ == 0 )
405+ return ;
406+ static const std::array<double , S_ + 1 > lut = powersOfTwo ();
407+ auto abs = [](int val) { return val < 0 ? std::abs (val) - 1 : val; };
408+ if (abs (value) < std::round (lut[size_ - 1 ]))
409+ return ;
410+ cms::Exception exception (" RunTimeError." );
411+ exception << " Value " << value << " does not fit into a " << size_ << " b two's complement." ;
412+ exception.addContext (" TTBV::checkT" );
413+ throw exception;
414+ }
415+
416+ // check if value fits into twos complement / binary BV
417+ void checkI (int value) {
418+ if (size_ == 0 )
419+ return ;
420+ if (twos_)
421+ checkT (value);
422+ else if (value < 0 ) {
423+ cms::Exception exception (" RunTimeError." );
424+ exception << size_ << " b Binary TTBV constructor called with negative value (" << value << " )." ;
425+ exception.addContext (" TTBV::checkI" );
426+ throw exception;
427+ } else
428+ checkU (value);
358429 }
359430};
360431
0 commit comments