ATLAS Offline Software
LWHistBitUtils.icc
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 //____________________________________________________________________
6 inline uint32_t LWHistBitUtils::posMSB( uint32_t x)
7 {
8  assert(x!=0);
9  //Code snippet posted on http://www.southwindsgames.com by Juan Pablo:
10  uint32_t l=0;
11  if(x >= 1<<16) { x>>=16; l|=16; }
12  if(x >= 1<<8) { x>>=8; l|=8; }
13  if(x >= 1<<4) { x>>=4; l|=4; }
14  if(x >= 1<<2) { x>>=2; l|=2; }
15  if(x >= 1<<1) l|=1;
16  return ++l;
17 }
18 
19 //____________________________________________________________________
20 inline uint8_t LWHistBitUtils::posMSB( uint8_t x)
21 {
22  assert(x!=0);
23  //Code snippet posted on http://www.southwindsgames.com by Juan Pablo:
24  uint8_t l=0;
25  if(x >= 1<<4) { x>>=4; l|=4; }
26  if(x >= 1<<2) { x>>=2; l|=2; }
27  if(x >= 1<<1) l|=1;
28  return ++l;
29 }
30 
31 //____________________________________________________________________
32 inline uint32_t LWHistBitUtils::posLSB(uint32_t x)
33 {
34  assert(x!=0);
35  return ffs(x);
36 }
37 
38 //____________________________________________________________________
39 inline uint8_t LWHistBitUtils::posLSB(uint8_t x)
40 {
41  assert(x!=0);
42  return ffs(x);
43 }
44 
45 
46 //____________________________________________________________________
47 template <class T>
48 inline T LWHistBitUtils::countSetBits(T data)
49 {
50 #ifndef NDEBUG
51  //Direct method:
52  T nDirect(0);
53  for(T i=0;i<T(sizeof(T)*8);++i)
54  if (bitIsSet(data,i))
55  ++nDirect;
56 #endif
57  // "Brian Kernighan's" method (needs number of steps equal to number of set bits):
58  T c(0); // c accumulates the total bits set in v
59  for (; data; ++c)
60  data &= data - 1; // clear the least significant bit set
61  assert(c==nDirect);
62  return c;
63 }
64 
65 //____________________________________________________________________
66 template <class T>
67 inline T LWHistBitUtils::countSetBitsBefore(T data, T ibit)
68 {
69  const T result(countSetBits(T(data<<(sizeof(T)*8-ibit))));
70 #ifndef NDEBUG
71  T nDirect(0);
72  for(T i=0;i<ibit;++i)
73  if (bitIsSet(data,i))
74  ++nDirect;
75  assert(nDirect==result);
76 #endif
77  return result;
78 }
79 
80 
81 //____________________________________________________________________
82 template<uint8_t sizeofT>
83 uint8_t LWHistBitUtils::stageOffset8Bits(uint32_t stagepattern)
84 {
85 #define C1 sizeof(uint8_t)
86 #define C2 sizeof(uint16_t)
87 #define C3 sizeofT
88 
89  //Assume only the 8 rightmost bits are set:
90  assert(!(0xFFFFFF00&stagepattern));
91 
92  if (!(stagepattern&0xAAAAAAAA)) {
93  //All stagepatterns are either 0x0 or 0x1, thus:
94  return stagepattern ? LWHistBitUtils::countSetBits<uint32_t>(stagepattern) * C1 : 0;
95  }
96 
97  //Use lookup table:
98  static const uint8_t lookup[16]
99  = { 0, //0000
100  C1, //0001
101  C2, //0010
102  C3, //0011
103  C1, //0100
104  2*C1, //0101
105  C1+C2, //0110
106  C1+C3, //0111
107  C2, //1000
108  C2+C1, //1001
109  2*C2, //1010
110  C2+C3, //1011
111  C3, //1100
112  C3+C1, //1101
113  C3+C2, //1110
114  2*C3 //1111
115  };
116 #undef C1
117 #undef C2
118 #undef C3
119  return lookup[ uint8_t(stagepattern & 0xF) ] + lookup[ uint8_t((stagepattern>>4)&0xF) ];
120 }
121 
122 //____________________________________________________________________
123 template<uint8_t sizeofT>
124 inline uint8_t LWHistBitUtils::totalSummedOffsetInStages(uint32_t stagepattern )
125 {
126 #ifndef NDEBUG
127  uint32_t tmpstagepattern(stagepattern);
128  unsigned char expectedresult(0);
129  for (uint8_t ibin = 0; ibin<sizeof(uint32_t)*4;++ibin) {
130  switch((tmpstagepattern & 0x3)) {
131  case 0x1: expectedresult += sizeof(unsigned char); break;
132  case 0x2: expectedresult += sizeof(unsigned short); break;
133  case 0x3: expectedresult += sizeofT; break;
134  default:
135  //empty stage
136  break;
137  }
138  tmpstagepattern = (tmpstagepattern >> 2);
139  }
140 #endif
141 
142  if (!(stagepattern&0xAAAAAAAA)) {
143  //All stagepatterns are either 0x0 or 0x1, thus:
144  assert(expectedresult==LWHistBitUtils::countSetBits<uint32_t>(stagepattern) * sizeof(uint8_t));
145  return LWHistBitUtils::countSetBits<uint32_t>(stagepattern) * sizeof(uint8_t);
146  }
147  //FIXME: Use LSB/MSB trick???
148  const uint8_t result = stageOffset8Bits<sizeofT>(stagepattern & 0xFF)
149  + stageOffset8Bits<sizeofT>((stagepattern>>8) & 0xFF)
150  + stageOffset8Bits<sizeofT>((stagepattern>>16) & 0xFF)
151  + stageOffset8Bits<sizeofT>((stagepattern>>24) & 0xFF);
152  assert(expectedresult==result);
153  return result;
154 }