File indexing completed on 2025-06-11 02:59:55
0001 #ifndef DataFormats_L1TrackTrigger_TTBV_h
0002 #define DataFormats_L1TrackTrigger_TTBV_h
0003
0004 #include "FWCore/Utilities/interface/Exception.h"
0005
0006 #include <bitset>
0007 #include <array>
0008 #include <string>
0009 #include <algorithm>
0010 #include <cmath>
0011 #include <utility>
0012 #include <vector>
0013 #include <iostream>
0014
0015
0016
0017
0018
0019
0020
0021
0022 class TTBV {
0023 public:
0024 static constexpr int S_ = 64;
0025 private:
0026 bool twos_;
0027 int size_;
0028 std::bitset<S_> bs_;
0029 public:
0030
0031 TTBV() : twos_(false), size_(0), bs_() {}
0032
0033 TTBV(const double d) : twos_(false), size_(S_) {
0034 int index(0);
0035 const char* c = reinterpret_cast<const char*>(&d);
0036 for (int iByte = 0; iByte < (int)sizeof(d); iByte++) {
0037 const std::bitset<std::numeric_limits<unsigned char>::digits> byte(*(c + iByte));
0038 for (int bit = 0; bit < std::numeric_limits<unsigned char>::digits; bit++)
0039 bs_[index++] = byte[bit];
0040 }
0041 }
0042
0043
0044 TTBV(unsigned long long int value, int size) : twos_(false), size_(size), bs_(value) { checkU(value); }
0045
0046
0047 TTBV(int value, int size, bool twos = false)
0048 : twos_(twos), size_(size), bs_((!twos || value >= 0) ? value : value + iMax()) {
0049 checkI(value);
0050 }
0051
0052
0053 TTBV(double value, double base, int size, bool twos = false)
0054 : TTBV((int)std::floor(value / base + 1.e-12), size, twos) {}
0055
0056
0057 TTBV(const std::string& str, bool twos = false) : twos_(twos), size_(str.size()), bs_(str) {}
0058
0059
0060 TTBV(const std::bitset<S_>& bs, bool twos = false) : twos_(twos), size_(S_), bs_(bs) {}
0061
0062
0063 TTBV(const TTBV& ttBV, int begin, int end = 0, bool twos = false) : twos_(twos), size_(begin - end), bs_(ttBV.bs_) {
0064 bs_ <<= S_ - begin;
0065 bs_ >>= S_ - begin + end;
0066 }
0067
0068
0069 bool twos() const { return twos_; }
0070
0071 int size() const { return size_; }
0072
0073 const std::bitset<S_>& bs() const { return bs_; }
0074
0075
0076 bool operator[](int pos) const { return bs_[pos]; }
0077
0078
0079 std::bitset<S_>::reference operator[](int pos) { return bs_[pos]; }
0080
0081
0082 bool test(int pos) const { return bs_.test(pos); }
0083
0084
0085 bool msb() const { return bs_[size_ - 1]; }
0086
0087
0088 std::bitset<S_>::reference msb() { return bs_[size_ - 1]; }
0089
0090
0091
0092 bool all() const { return bs_.all(); }
0093 bool any() const { return bs_.any(); }
0094 bool none() const { return bs_.none(); }
0095 int count() const { return bs_.count(); }
0096
0097
0098 bool operator==(const TTBV& rhs) const { return bs_ == rhs.bs_; }
0099
0100
0101 bool operator!=(const TTBV& rhs) const { return bs_ != rhs.bs_; }
0102
0103
0104 TTBV& operator&=(const TTBV& rhs) {
0105 bs_ &= rhs.bs_;
0106 return *this;
0107 }
0108
0109
0110 TTBV operator&&(const TTBV& rhs) {
0111 TTBV copy(*this);
0112 return copy &= rhs;
0113 }
0114
0115
0116 TTBV& operator|=(const TTBV& rhs) {
0117 bs_ |= rhs.bs_;
0118 return *this;
0119 }
0120
0121
0122 TTBV operator||(const TTBV& rhs) {
0123 TTBV copy(*this);
0124 return copy |= rhs;
0125 }
0126
0127
0128 TTBV& operator^=(const TTBV& rhs) {
0129 bs_ ^= rhs.bs_;
0130 return *this;
0131 }
0132
0133
0134 TTBV operator~() const {
0135 TTBV bv(*this);
0136 return bv.flip();
0137 }
0138
0139
0140 TTBV& operator>>=(int pos) {
0141 bs_ >>= pos;
0142 size_ -= pos;
0143 return *this;
0144 }
0145
0146
0147 TTBV& operator<<=(int pos) {
0148 bs_ <<= S_ - size_ + pos;
0149 bs_ >>= S_ - size_ + pos;
0150 size_ -= pos;
0151 return *this;
0152 }
0153
0154
0155 TTBV operator<<(int pos) const {
0156 TTBV bv(*this);
0157 return bv <<= pos;
0158 }
0159
0160
0161 TTBV operator>>(int pos) const {
0162 TTBV bv(*this);
0163 return bv >>= pos;
0164 }
0165
0166
0167 TTBV& operator+=(const TTBV& rhs) {
0168 bs_ <<= rhs.size();
0169 bs_ |= rhs.bs_;
0170 size_ += rhs.size();
0171 return *this;
0172 }
0173
0174
0175 TTBV operator+(const TTBV& rhs) const {
0176 TTBV lhs(*this);
0177 return lhs += rhs;
0178 }
0179
0180
0181 TTBV& operator++() {
0182 bs_ = std::bitset<S_>(bs_.to_ullong() + 1);
0183 this->resize(size_);
0184 return *this;
0185 }
0186
0187
0188 TTBV& reset() {
0189 bs_.reset();
0190 return *this;
0191 }
0192
0193
0194 TTBV& set() {
0195 for (int n = 0; n < size_; n++)
0196 bs_.set(n);
0197 return *this;
0198 }
0199
0200
0201 TTBV& flip() {
0202 for (int n = 0; n < size_; n++)
0203 bs_.flip(n);
0204 return *this;
0205 }
0206
0207
0208 TTBV& reset(int pos) {
0209 bs_.reset(pos);
0210 return *this;
0211 }
0212
0213
0214 TTBV& set(int pos) {
0215 bs_.set(pos);
0216 return *this;
0217 }
0218
0219
0220 TTBV& set(std::vector<int> vpos) {
0221 for (int pos : vpos)
0222 bs_.set(pos);
0223 return *this;
0224 }
0225
0226
0227 TTBV& flip(int pos) {
0228 bs_.flip(pos);
0229 return *this;
0230 }
0231
0232
0233 TTBV& abs() {
0234 if (twos_) {
0235 twos_ = false;
0236 if (this->msb())
0237 this->flip();
0238 size_--;
0239 }
0240 return *this;
0241 }
0242
0243
0244 TTBV& resize(int size) {
0245 bool msb = this->msb();
0246 if (size > size_) {
0247 if (twos_)
0248 for (int n = size_; n < size; n++)
0249 bs_.set(n, msb);
0250 size_ = size;
0251 } else if (size < size_ && size > 0) {
0252 this->operator<<=(size_ - size);
0253 if (twos_)
0254 this->msb() = msb;
0255 }
0256 return *this;
0257 }
0258
0259
0260 std::string str() const { return bs_.to_string().substr(S_ - size_, S_); }
0261
0262
0263 std::string str(int start, int end = 0) const { return this->str().substr(size_ - start, size_ - end); }
0264
0265
0266 int val() const { return (twos_ && this->msb()) ? (int)bs_.to_ullong() - iMax() : bs_.to_ullong(); }
0267
0268
0269 int val(bool twos) const { return (twos && this->msb()) ? (int)bs_.to_ullong() - iMax() : bs_.to_ullong(); }
0270
0271
0272 int val(int start, int end = 0, bool twos = false) const { return TTBV(*this, start, end).val(twos); }
0273
0274
0275 double val(double base) const { return (this->val() + .5) * base; }
0276
0277
0278 double val(double base, int start, int end = 0, bool twos = false) const {
0279 return (this->val(start, end, twos) + .5) * base;
0280 }
0281
0282
0283 double extract(double base, int size, bool twos = false) {
0284 double val = this->val(base, size, 0, twos);
0285 this->operator>>=(size);
0286 return val;
0287 }
0288
0289
0290 int extract(int size, bool twos = false) {
0291 int val = this->val(size, 0, twos);
0292 this->operator>>=(size);
0293 return val;
0294 }
0295
0296
0297 bool extract() {
0298 bool val = bs_[0];
0299 this->operator>>=(1);
0300 return val;
0301 }
0302
0303
0304 TTBV slice(int size, bool twos = false) {
0305 TTBV ttBV(*this, size, 0, twos);
0306 this->operator>>=(size);
0307 return ttBV;
0308 }
0309
0310
0311 int count(int begin, int end, bool b = true) const {
0312 int c(0);
0313 for (int i = begin; i < end; i++)
0314 if (bs_[i] == b)
0315 c++;
0316 return c;
0317 }
0318
0319
0320 int plEncode(bool b = true) const {
0321 for (int e = 0; e < size_; e++)
0322 if (bs_[e] == b)
0323 return e;
0324 return size_;
0325 }
0326
0327
0328 int plEncode(int begin, int end, bool b = true) const {
0329 for (int e = begin; e < end; e++)
0330 if (bs_.test(e) == b)
0331 return e;
0332 return size_;
0333 }
0334
0335
0336 int pmEncode(bool b = true) const {
0337 for (int e = size_ - 1; e > -1; e--)
0338 if (bs_[e] == b)
0339 return e;
0340 return size_;
0341 }
0342
0343
0344 int pmEncode(int begin, int end, bool b = true) const {
0345 for (int e = end - 1; e >= begin; e--)
0346 if (bs_.test(e) == b)
0347 return e;
0348 return end;
0349 }
0350
0351
0352 int encode(int n, bool b = true) const {
0353 int sum(0);
0354 for (int e = 0; e < size_; e++) {
0355 if (bs_[e] == b) {
0356 sum++;
0357 if (sum == n)
0358 return e;
0359 }
0360 }
0361 return size_;
0362 }
0363
0364 std::vector<int> ids(bool b = true, bool singed = false) const {
0365 std::vector<int> v;
0366 v.reserve(bs_.count());
0367 for (int i = 0; i < size_; i++)
0368 if (bs_[i] == b)
0369 v.push_back(singed ? i + size_ / 2 : i);
0370 return v;
0371 }
0372
0373 friend std::ostream& operator<<(std::ostream& os, const TTBV& ttBV) { return os << ttBV.str(); }
0374
0375 private:
0376
0377 constexpr std::array<double, S_ + 1> powersOfTwo() const {
0378 std::array<double, S_ + 1> lut = {};
0379 for (int i = 0; i <= S_; i++)
0380 lut[i] = std::pow(2, i);
0381 return lut;
0382 }
0383
0384
0385 double iMax() const {
0386 static const std::array<double, S_ + 1> lut = powersOfTwo();
0387 return std::round(lut[size_]);
0388 }
0389
0390
0391 void checkU(unsigned long long int value) {
0392 if (size_ <= 0 || size_ > S_)
0393 throwSize();
0394 if (value < iMax())
0395 return;
0396 cms::Exception exception("RunTimeError.");
0397 exception << "Value " << value << " does not fit into a " << size_ << "b binary.";
0398 exception.addContext("TTBV::checkU");
0399 throw exception;
0400 }
0401
0402
0403 void checkT(int value) {
0404 static const std::array<double, S_ + 1> lut = powersOfTwo();
0405 auto abs = [](int val) { return val < 0 ? std::abs(val) - 1 : val; };
0406 if (abs(value) < std::round(lut[size_ - 1]))
0407 return;
0408 cms::Exception exception("RunTimeError.");
0409 exception << "Value " << value << " does not fit into a " << size_ << "b two's complement.";
0410 exception.addContext("TTBV::checkT");
0411 throw exception;
0412 }
0413
0414
0415 void checkI(int value) {
0416 if (size_ <= 0 || size_ > S_)
0417 throwSize();
0418 if (twos_)
0419 checkT(value);
0420 else if (value < 0) {
0421 cms::Exception exception("RunTimeError.");
0422 exception << size_ << "b Binary TTBV constructor called with negative value (" << value << ").";
0423 exception.addContext("TTBV::checkI");
0424 throw exception;
0425 } else
0426 checkU(value);
0427 }
0428
0429
0430 void throwSize() const {
0431 cms::Exception exception("RunTimeError.");
0432 exception << "TTBV constructor called with bad bit width (" << size_ << ").";
0433 throw exception;
0434 }
0435 };
0436
0437 #endif