Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-02-14 14:23:21

0001 #include "L1Trigger/L1TMuonEndCap/interface/PhiMemoryImage.h"
0002 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0003 
0004 #include <stdexcept>
0005 #include <iostream>
0006 #include <bitset>
0007 
0008 #define UINT64_BITS 64
0009 
0010 PhiMemoryImage::PhiMemoryImage() { reset(); }
0011 
0012 PhiMemoryImage::~PhiMemoryImage() {}
0013 
0014 PhiMemoryImage::PhiMemoryImage(const PhiMemoryImage& other) {
0015   std::copy(&(other._buffer[0][0]), &(other._buffer[0][0]) + (_layers * _units), &(_buffer[0][0]));
0016 
0017   _straightness = other._straightness;
0018 }
0019 
0020 PhiMemoryImage::PhiMemoryImage(PhiMemoryImage&& other) noexcept : PhiMemoryImage() { swap(other); }
0021 
0022 // Copy-and-swap idiom
0023 PhiMemoryImage& PhiMemoryImage::operator=(PhiMemoryImage other) {
0024   swap(other);
0025   return *this;
0026 }
0027 
0028 void PhiMemoryImage::swap(PhiMemoryImage& other) {
0029   std::swap_ranges(&(other._buffer[0][0]), &(other._buffer[0][0]) + (_layers * _units), &(_buffer[0][0]));
0030 
0031   std::swap(other._straightness, _straightness);
0032 }
0033 
0034 void PhiMemoryImage::reset() {
0035   std::fill(&(_buffer[0][0]), &(_buffer[0][0]) + (_layers * _units), 0);
0036 
0037   _straightness = 0;
0038 }
0039 
0040 void PhiMemoryImage::set_bit(unsigned int layer, unsigned int bit) {
0041   check_input(layer, bit);
0042   value_type unit = bit / UINT64_BITS;
0043   value_type mask = (1ul << (bit % UINT64_BITS));
0044   _buffer[layer][unit] |= mask;
0045 }
0046 
0047 void PhiMemoryImage::clear_bit(unsigned int layer, unsigned int bit) {
0048   check_input(layer, bit);
0049   value_type unit = bit / UINT64_BITS;
0050   value_type mask = (1ul << (bit % UINT64_BITS));
0051   _buffer[layer][unit] &= ~mask;
0052 }
0053 
0054 bool PhiMemoryImage::test_bit(unsigned int layer, unsigned int bit) const {
0055   check_input(layer, bit);
0056   value_type unit = bit / UINT64_BITS;
0057   value_type mask = (1ul << (bit % UINT64_BITS));
0058   return _buffer[layer][unit] & mask;
0059 }
0060 
0061 void PhiMemoryImage::set_word(unsigned int layer, unsigned int unit, value_type value) {
0062   check_input(layer, unit * UINT64_BITS);
0063   _buffer[layer][unit] = value;
0064 }
0065 
0066 PhiMemoryImage::value_type PhiMemoryImage::get_word(unsigned int layer, unsigned int unit) const {
0067   check_input(layer, unit * UINT64_BITS);
0068   return _buffer[layer][unit];
0069 }
0070 
0071 void PhiMemoryImage::check_input(unsigned int layer, unsigned int bit) const {
0072   if (layer >= _layers) {
0073     char what[128];
0074     snprintf(what, sizeof(what), "layer (which is %u) >= _layers (which is %u)", layer, _layers);
0075     throw std::out_of_range(what);
0076   }
0077 
0078   unsigned int unit = bit / UINT64_BITS;
0079   if (unit >= _units) {
0080     char what[128];
0081     snprintf(what, sizeof(what), "unit (which is %u) >= _units (which is %u)", unit, _units);
0082     throw std::out_of_range(what);
0083   }
0084 }
0085 
0086 // See https://en.wikipedia.org/wiki/Circular_shift#Implementing_circular_shifts
0087 // return (val << len) | ((unsigned) val >> (-len & (sizeof(INT) * CHAR_BIT - 1)));
0088 void PhiMemoryImage::rotl(unsigned int n) {
0089   if (n >= _units * UINT64_BITS)
0090     return;
0091 
0092   value_type tmp[_layers][_units];
0093   std::copy(&(_buffer[0][0]), &(_buffer[0][0]) + (_layers * _units), &(tmp[0][0]));
0094 
0095   const unsigned int mask = UINT64_BITS - 1;
0096   const unsigned int n1 = n % UINT64_BITS;
0097   const unsigned int n2 = _units - (n / UINT64_BITS);
0098   const unsigned int n3 = (n1 == 0) ? n2 + 1 : n2;
0099 
0100   unsigned int i = 0, j = 0, j_curr = 0, j_next = 0;
0101   for (i = 0; i < _layers; ++i) {
0102     for (j = 0; j < _units; ++j) {
0103       // if n2 == 0:
0104       //   j_curr = 0, 1, 2
0105       //   j_next = 2, 0, 1
0106       // if n2 == 1:
0107       //   j_curr = 2, 0, 1
0108       //   j_next = 1, 2, 0
0109       j_curr = (n2 + j) % _units;
0110       j_next = (n3 + j + _units - 1) % _units;
0111       _buffer[i][j] = (tmp[i][j_curr] << n1) | (tmp[i][j_next] >> (-n1 & mask));
0112     }
0113   }
0114 }
0115 
0116 void PhiMemoryImage::rotr(unsigned int n) {
0117   if (n >= _units * UINT64_BITS)
0118     return;
0119 
0120   value_type tmp[_layers][_units];
0121   std::copy(&(_buffer[0][0]), &(_buffer[0][0]) + (_layers * _units), &(tmp[0][0]));
0122 
0123   const unsigned int mask = UINT64_BITS - 1;
0124   const unsigned int n1 = n % UINT64_BITS;
0125   const unsigned int n2 = n / UINT64_BITS;
0126   const unsigned int n3 = (n1 == 0) ? n2 + _units - 1 : n2;
0127 
0128   unsigned int i = 0, j = 0, j_curr = 0, j_next = 0;
0129   for (i = 0; i < _layers; ++i) {
0130     for (j = 0; j < _units; ++j) {
0131       // if n2 == 0:
0132       //   j_curr = 0, 1, 2
0133       //   j_next = 1, 2, 0
0134       // if n2 == 1:
0135       //   j_curr = 2, 0, 1
0136       //   j_next = 0, 1, 2
0137       j_curr = (n2 + j) % _units;
0138       j_next = (n3 + j + 1) % _units;
0139       _buffer[i][j] = (tmp[i][j_curr] >> n1) | (tmp[i][j_next] << (-n1 & mask));
0140     }
0141   }
0142 }
0143 
0144 unsigned int PhiMemoryImage::op_and(const PhiMemoryImage& other) const {
0145   static_assert((_layers == 4 && _units == 3), "This function assumes (_layers == 4 && _units == 3)");
0146 
0147   // Unroll
0148   bool b_st1 = (_buffer[0][0] & other._buffer[0][0]) || (_buffer[0][1] & other._buffer[0][1]) ||
0149                (_buffer[0][2] & other._buffer[0][2]);
0150   bool b_st2 = (_buffer[1][0] & other._buffer[1][0]) || (_buffer[1][1] & other._buffer[1][1]) ||
0151                (_buffer[1][2] & other._buffer[1][2]);
0152   bool b_st3 = (_buffer[2][0] & other._buffer[2][0]) || (_buffer[2][1] & other._buffer[2][1]) ||
0153                (_buffer[2][2] & other._buffer[2][2]);
0154   bool b_st4 = (_buffer[3][0] & other._buffer[3][0]) || (_buffer[3][1] & other._buffer[3][1]) ||
0155                (_buffer[3][2] & other._buffer[3][2]);
0156 
0157   //   bit 0: st3 or st4 hit
0158   //   bit 1: st2 hit
0159   //   bit 2: st1 hit
0160   unsigned int ly = (b_st1 << 2) | (b_st2 << 1) | (b_st3 << 0) | (b_st4 << 0);
0161   return ly;
0162 }
0163 
0164 void PhiMemoryImage::print(std::ostream& out) const {
0165   constexpr int N = 160;
0166   out << std::bitset<N - 128>(_buffer[3][2]) << std::bitset<128 - 64>(_buffer[3][1]) << std::bitset<64>(_buffer[3][0])
0167       << std::endl;
0168   out << std::bitset<N - 128>(_buffer[2][2]) << std::bitset<128 - 64>(_buffer[2][1]) << std::bitset<64>(_buffer[2][0])
0169       << std::endl;
0170   out << std::bitset<N - 128>(_buffer[1][2]) << std::bitset<128 - 64>(_buffer[1][1]) << std::bitset<64>(_buffer[1][0])
0171       << std::endl;
0172   out << std::bitset<N - 128>(_buffer[0][2]) << std::bitset<128 - 64>(_buffer[0][1]) << std::bitset<64>(_buffer[0][0]);
0173 }
0174 
0175 // _____________________________________________________________________________
0176 // Output streams
0177 std::ostream& operator<<(std::ostream& o, const PhiMemoryImage& patt) {
0178   patt.print(o);
0179   return o;
0180 }