ATLAS Offline Software
L1TopoDataTypes.h
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3 */
4 /*********************************
5  * L1TopoDataTypes.h
6  * author : Ignacio Aracena <ignacio.aracena@cern.ch>
7  * Created May 2015
8  *
9  * @brief Tools for handling fixed point Qm.n numbers
10 **********************************/
11 #ifndef L1TopoSimulationUtils_L1TOPODATATYPES_H
12 #define L1TopoSimulationUtils_L1TOPODATATYPES_H
13 #include <string>
14 #include <iostream>
15 #include <stdint.h>
16 
17 /* Setting maximal number of bits to 32. */
18 #ifndef MAXBITS
19 #define MAXBITS 64
20 #endif
21 
22 
24 template <class T>
25 inline
26 T ones (unsigned int n)
27 {
28  if (n >= sizeof(T) * 8)
29  return ~static_cast<T>(0);
30  return (static_cast<T>(1) << n) - 1ull;
31 }
32 
33 namespace TSU {
34 
35  typedef unsigned long long T;
36  T convert(const unsigned long long& v, const unsigned& in_p, const unsigned int& in_f,
37  const unsigned int& out_p, const unsigned int& out_f);
38 
39 /*********************************
40  * Template class implements Qm.n number format
41  * PREC : Total number of bits
42  * F : fractional bits
43  * PREC - F - 1 : integer bits (one bit used for sign)
44  *
45  * Usage TSU::L1TopoDataTypes<10,7> a("0010100011")
46  * or
47  * Usage TSU::L1TopoDataTypes<10,7> a(163)
48  * with PREC = 10 and F=7 163 (or 0010100011) corresponds to 1.27344
49 *********************************/
50 
51  template <unsigned PREC, unsigned F> class L1TopoDataTypes {
52  public:
53  L1TopoDataTypes(T v) : m_tvalue(v) { }
54  // c'tor using binary pattern as input
55  L1TopoDataTypes(const std::string& b="") : m_tvalue(0) {
56  unsigned int idx = 0;
57  for(auto in = b.rbegin(); in!=b.rend(); ++in){
58  if(*in=='1') m_tvalue += (1ull << idx);
59  ++idx;
60  }
61  }
62 
63  L1TopoDataTypes(double d) : m_tvalue(d) {
64  m_tvalue = d*(1ull<<F);
65  }
66 
67  L1TopoDataTypes(int i) : m_tvalue(i) {
68  m_tvalue = i*(1ull<<F);
69  }
70 
71  L1TopoDataTypes(unsigned i) : m_tvalue(i) {
72  m_tvalue = i*(1ull<<F);
73  }
74 
75  // converts number from one set of template parameters to another
76  template<unsigned P1, unsigned F1> operator L1TopoDataTypes<P1,F1>(){
77  return L1TopoDataTypes<P1,F1>(convert(m_tvalue,PREC,F,P1,F1));
78  }
79 
80  operator float(){
81  return this->to_float();
82  }
83 
84  operator int(){
85  return ones<T>(PREC-F)&((m_tvalue>>F));
86  }
87 
88  operator unsigned(){
89  return ones<T>(PREC-F)&((m_tvalue>>F));
90  }
91 
92  operator int64_t(){
93  return ones<T>(PREC-F)&((m_tvalue>>F));
94  }
95 
96  operator unsigned long long(){
97  return ones<T>(PREC-F)&((m_tvalue>>F));
98  }
99 
100  T value() const {
101  return m_tvalue;
102  }
103 
104  T abs() const {
105  T mask = m_tvalue >> (PREC-1ull);
106  T res = ((mask ^ m_tvalue) - mask) & ones<T>(PREC);
107  return res;
108  }
109 
110  // returns two's complement of a value (i.e. the negative)
111  T complement() const {
112  T res=0;
113  T v = m_tvalue;
114  for(unsigned j=0;j<PREC;++j){
115  res += v & (1ull << j) ? 0 : (1ull << j);
116  }
117  res += 1;
118  return res;
119  }
120 
121  // increments value
123  m_tvalue += value;
124  return *this;
125  }
126 
127  // flips sign
129  m_tvalue = this->complement();
130  return *this;
131  }
132 
133  // scale value with an integer
134  L1TopoDataTypes& operator*=(const int& factor){
135  short int neg = (m_tvalue >> (PREC-1ull)) ? 1 : 0;
136  if(neg && factor<0){
137  neg = 0;
138  m_tvalue = this->complement() * ::abs(factor);
139  } else if(factor<0){
140  m_tvalue = (m_tvalue * ::abs(factor));
141  m_tvalue = this->complement();
142  } else {
143  m_tvalue = m_tvalue * factor;
144  }
145  return *this;
146  }
147 
148  // multiplication with an integer
149  template<unsigned P,unsigned FF> friend L1TopoDataTypes<P,FF> operator*(const int& factor, L1TopoDataTypes<P,FF> d);
150  template<unsigned P,unsigned FF> friend L1TopoDataTypes<P,FF> operator*(L1TopoDataTypes<P,FF> d,const int& factor);
151 
152  // add two numbers with different representation
153  template<unsigned P1, unsigned F1, unsigned P2, unsigned F2> friend L1TopoDataTypes<((P1-F1) > (P2-F2) ? (P1-F1) : (P2-F2)) + ((F1 > F2) ? F1 : F2), (F1 > F2) ? F1 : F2> operator+(const L1TopoDataTypes<P1,F1>& lhs, const L1TopoDataTypes<P2,F2>& rhs);
154 
155  // subtract two numbers with different representation
156  template<unsigned P1, unsigned F1, unsigned P2, unsigned F2> friend L1TopoDataTypes<((P1-F1) > (P2-F2) ? (P1-F1) : (P2-F2)) + ((F1 > F2) ? F1 : F2), (F1 > F2) ? F1 : F2> operator-(const L1TopoDataTypes<P1,F1> lhs, const L1TopoDataTypes<P2,F2> rhs);
157 
158  // subtract L1TopoDataTypes from double
159  template<unsigned P1, unsigned F1> L1TopoDataTypes<P1+1,F1> friend operator-(const double& lhs, const L1TopoDataTypes<P1,F1>& rhs);
160 
161  template<unsigned P1, unsigned F1> L1TopoDataTypes<P1+1,F1> friend operator-(const L1TopoDataTypes<P1,F1>& lhs, const double& rhs);
162 
163  // subtract L1TopoDataTypes from int
164  template<unsigned P1, unsigned F1> L1TopoDataTypes<P1+1,F1> friend operator-(const int& lhs, const L1TopoDataTypes<P1,F1>& rhs);
165 
166  template<unsigned P1, unsigned F1> L1TopoDataTypes<P1+1,F1> friend operator-(const L1TopoDataTypes<P1,F1>& lhs, const int& rhs);
167  // product of two numbers with different representation
168  template<unsigned P1, unsigned F1, unsigned P2, unsigned F2> friend L1TopoDataTypes<(P1+P2-1 > MAXBITS) ? MAXBITS : P1+P2-1, (P1+P2-1 > MAXBITS) ? (F2>F1 ? F2 - ((P1+P2-1) - MAXBITS) : F1 - ((P1+P2-1) - MAXBITS)) : ((F1 > F2) ? F1 : F2)> operator*(const L1TopoDataTypes<P1,F1> lhs, const L1TopoDataTypes<P2,F2> rhs);
169 
170  // add L1TopoDataTypes to double
171  template<unsigned P1, unsigned F1> L1TopoDataTypes<P1+1,F1> friend operator+(const double& lhs, const L1TopoDataTypes<P1,F1>& rhs);
172 
173  template<unsigned P1, unsigned F1> L1TopoDataTypes<P1+1,F1> friend operator+(const L1TopoDataTypes<P1,F1>& lhs, const double& rhs);
174 
175  // add L1TopoDataTypes to int
176  template<unsigned P1, unsigned F1> L1TopoDataTypes<P1+1,F1> friend operator+(const int& lhs, const L1TopoDataTypes<P1,F1>& rhs);
177 
178  template<unsigned P1, unsigned F1> L1TopoDataTypes<P1+1,F1> friend operator+(const L1TopoDataTypes<P1,F1>& lhs, const int& rhs);
179  // product of two numbers with different representation
180  template<unsigned P1, unsigned F1, unsigned P2, unsigned F2> friend L1TopoDataTypes<(P1+P2-1 > MAXBITS) ? MAXBITS : P1+P2-1, (P1+P2-1 > MAXBITS) ? (F2>F1 ? F2 - ((P1+P2-1) - MAXBITS) : F1 - ((P1+P2-1) - MAXBITS)) : ((F1 > F2) ? F1 : F2)> operator*(const L1TopoDataTypes<P1,F1> lhs, const L1TopoDataTypes<P2,F2> rhs);
181 
182  // overloaded operator<<
183  friend std::ostream& operator<<(std::ostream& os, const L1TopoDataTypes& d){
184  std::string out;
185  for(int j=PREC-1;j>=0;--j){
186  out += ((d.m_tvalue>>j)&1ull) ? "1" : "0";
187  }
188  os << "integer value " << d.m_tvalue << " binary " << out << " float " << d.to_float();
189  return os;
190  }
191 
192  // return float representation
193  float to_float() const {
194  // Find sign
195  float res = ((m_tvalue>>(PREC-1ull))&1ull) ? -(1ll<<(PREC-F)) : 0.;
196  // Get integer part
197  res += (m_tvalue>>F)&((1ull<<(PREC-F))-1ull) ? float((m_tvalue>>F)&((1ull<<(PREC-F))-1ull)) : 0;
198  // Do the fractional part
199  if (F > 0) {
200  unsigned frac = m_tvalue & ( (1ull<<F)-1ull );
201  res += static_cast<float>(frac) / (2ull<<(F-1ull));
202  }
203  return res;
204  }
205 
206  unsigned int prec() const { return PREC; }
207  unsigned int frac() const { return F; }
208 
209  private:
210  T m_tvalue{};
211  };
212 
213  // get the 2's complement of bitset with p bits
214  T complement(const T& v, const unsigned int& p);
215 
216  // masks from Qm.n to a Qm1.n1, where in_p and in_f = total number of bits and of fraction part of input
217  //T convert(const unsigned int& v, const unsigned& in_p, const unsigned int& in_f,
218  // const unsigned int& out_p, const unsigned int& out_f);
219 
220  // represent T value with p bits as binary
221  std::string to_binary(T value, const unsigned int& p);
222 
223  // represent Qm.n number as float with p = total number of bits, f = number of fractional bits
224  float to_float(const T& va, const unsigned int& p, const unsigned int& f);
225 
226  // operator+ for L1TopoDataTypes
227  template<unsigned P1, unsigned F1, unsigned P2, unsigned F2> L1TopoDataTypes<((P1-F1) > (P2-F2) ? (P1-F1) : (P2-F2)) + ((F1 > F2) ? F1 : F2), (F1 > F2) ? F1 : F2> operator+(const L1TopoDataTypes<P1,F1>& lhs, const L1TopoDataTypes<P2,F2>& rhs){
228  const unsigned int frac = (F1 > F2) ? F1 : F2;
229  const unsigned int digit = ((P1-F1) > (P2-F2)) ? (P1-F1) - 1 : (P2-F2) - 1;
230  const unsigned int prec = frac + digit + 1;
231  T lhsconvert = convert(lhs.m_tvalue,P1,F1,prec,frac);
232  T rhsconvert = convert(rhs.m_tvalue,P2,F2,prec,frac);
233  L1TopoDataTypes<prec,frac> res(lhsconvert+rhsconvert);
234 
235  return res;
236  }
237 
238  // operator- for L1TopoDataTypes
239  template<unsigned P1, unsigned F1, unsigned P2, unsigned F2> L1TopoDataTypes<((P1-F1) > (P2-F2) ? (P1-F1) : (P2-F2)) + ((F1 > F2) ? F1 : F2), (F1 > F2) ? F1 : F2> operator-(const L1TopoDataTypes<P1,F1> lhs, const L1TopoDataTypes<P2,F2> rhs){
240  const unsigned int frac = (F1 > F2) ? F1 : F2;
241  const unsigned int digit = ((P1-F1) > (P2-F2)) ? (P1-F1) - 1 : (P2-F2) - 1;
242  const unsigned int prec = frac + digit + 1;
243  T lhsconvert = convert(lhs.m_tvalue,P1,F1,prec,frac);
244  T rhsconvert = convert(rhs.m_tvalue,P2,F2,prec,frac);
245  L1TopoDataTypes<prec,frac> res(lhsconvert+complement(rhsconvert,prec));
246 
247  return res;
248  }
249 
250  template<unsigned P1, unsigned F1> L1TopoDataTypes<P1+1,F1> operator-(const double& lhs, const L1TopoDataTypes<P1,F1>& rhs){
251  return L1TopoDataTypes<P1+1,F1>(lhs - rhs.to_float());
252  }
253 
254  template<unsigned P1, unsigned F1> L1TopoDataTypes<P1+1,F1> operator-(const L1TopoDataTypes<P1,F1>& lhs, const double& rhs){
255  return L1TopoDataTypes<P1+1,F1>(lhs.to_float() - rhs);
256  }
257 
258  template<unsigned P1, unsigned F1> L1TopoDataTypes<P1+1,F1> operator-(const int& lhs, const L1TopoDataTypes<P1,F1>& rhs){
259  return L1TopoDataTypes<P1+1,F1>(lhs - rhs.to_float());
260  }
261 
262  template<unsigned P1, unsigned F1> L1TopoDataTypes<P1+1,F1> operator-(const L1TopoDataTypes<P1,F1>& lhs, const int& rhs){
263  return L1TopoDataTypes<P1+1,F1>(lhs.to_float() - rhs);
264  }
265 
266  template<unsigned P1, unsigned F1> L1TopoDataTypes<P1+1,F1> operator+(const double& lhs, const L1TopoDataTypes<P1,F1>& rhs){
267  return L1TopoDataTypes<P1+1,F1>(lhs + rhs.to_float());
268  }
269 
270  template<unsigned P1, unsigned F1> L1TopoDataTypes<P1+1,F1> operator+(const L1TopoDataTypes<P1,F1>& lhs, const double& rhs){
271  return L1TopoDataTypes<P1+1,F1>(lhs.to_float() + rhs);
272  }
273 
274  template<unsigned P1, unsigned F1> L1TopoDataTypes<P1+1,F1> operator+(const int& lhs, const L1TopoDataTypes<P1,F1>& rhs){
275  return L1TopoDataTypes<P1+1,F1>(lhs + rhs.to_float());
276  }
277 
278  template<unsigned P1, unsigned F1> L1TopoDataTypes<P1+1,F1> operator+(const L1TopoDataTypes<P1,F1>& lhs, const int& rhs){
279  return L1TopoDataTypes<P1+1,F1>(lhs.to_float() + rhs);
280  }
281 
282 
283  // operator* for L1TopoDataTypes
284  template<unsigned P1, unsigned F1, unsigned P2, unsigned F2> L1TopoDataTypes<(P1+P2-1 > MAXBITS) ? MAXBITS : P1+P2-1, (P1+P2-1 > MAXBITS) ? (F2>F1 ? F2 - ((P1+P2-1) - MAXBITS) : F1 - ((P1+P2-1) - MAXBITS)) : ((F1 > F2) ? F1 : F2)> operator*(const L1TopoDataTypes<P1,F1> lhs, const L1TopoDataTypes<P2,F2> rhs){
285  const unsigned int frac = (P1+P2-1 > MAXBITS) ? (F2>F1 ? F2 - ((P1+P2-1) - MAXBITS) : F1 - ((P1+P2-1) - MAXBITS)) : ((F1 > F2) ? F1 : F2);
286  const unsigned int digit = ((P1+P2-1 > MAXBITS) ? (MAXBITS - frac) : (P1+P2-1 - frac)) - 1;
287  const unsigned int prec = frac + digit + 1;
288  T lhsconvert = lhs.m_tvalue;
289  T rhsconvert = rhs.m_tvalue;
290  // check if either value is negative and work with the absolute value
291  if((lhs.m_tvalue >> (P1-1ull)) & 1ull){
292  lhsconvert = complement(lhsconvert,P1);
293  }
294  if((rhs.m_tvalue >> (P2-1ull)) & 1ull){
295  rhsconvert = complement(rhsconvert,P2);
296  }
297  // map numbers into Q1+digit.frac
298  T lhsconvint = convert(lhsconvert,P1,F1,P1-F1,0);
299  T rhsconvint = convert(rhsconvert,P2,F2,P2-F2,0);
300  T lhsconvfrac = convert(lhsconvert,P1,F1,F1+1,F1);
301  T rhsconvfrac = convert(rhsconvert,P2,F2,F2+1,F2);
302  T prod_int = lhsconvint*rhsconvint; // PREC = P1-F1+P2-F2-1, F = 0
303  T prod_frac = lhsconvfrac*rhsconvfrac; // PREC = F1 + F2 + 1, F = F1 + F2
304  T prod_mix1 = lhsconvint*rhsconvfrac; // PREC = P1 - F1 + F2, F = F2
305  T prod_mix2 = lhsconvfrac*rhsconvint; // PREC = P2 - F2 + F1, F = F1
307  result += (prod_frac>>(F1+F2-frac));
308  result += (prod_mix1>>((F2>frac ? F2 - frac : 0)));
309  result += (prod_mix2>>((F1>frac ? F1 - frac : 0)));
310  if(!(((lhs.m_tvalue >> (P1-1ull)) & 1ull) ^ ((rhs.m_tvalue >> (P2-1ull)) & 1ull))){
311  return result;
312  } else
313  return -result;
314  }
315 
316  template<unsigned P, unsigned FF> TSU::L1TopoDataTypes<P,FF> operator*(const int& factor, TSU::L1TopoDataTypes<P,FF> d){
317  return d*=factor;
318  }
319 
320  template<unsigned P, unsigned FF> TSU::L1TopoDataTypes<P,FF> operator*(TSU::L1TopoDataTypes<P,FF> d, const int& factor){
321  return d*=factor;
322  }
323 
324 } // namespace
325 #endif
TSU::operator*
L1TopoDataTypes<(P1+P2-1 > MAXBITS) ? MAXBITS :P1+P2-1,(P1+P2-1 > MAXBITS) ?(F2 >F1 ? F2 -((P1+P2-1) - MAXBITS) :F1 -((P1+P2-1) - MAXBITS)) :((F1 > F2) ? F1 :F2)> operator*(const L1TopoDataTypes< P1, F1 > lhs, const L1TopoDataTypes< P2, F2 > rhs)
Definition: L1TopoDataTypes.h:284
TSU::L1TopoDataTypes::operator+=
L1TopoDataTypes & operator+=(const T &value)
Definition: L1TopoDataTypes.h:132
TSU::operator+
L1TopoDataTypes<((P1-F1) >P2-F2) ?(P1-F1) :(P2-F2))+((F1 > F2) ? F1 :F2),(F1 > F2) ? F1 :F2 > operator+(const L1TopoDataTypes< P1, F1 > &lhs, const L1TopoDataTypes< P2, F2 > &rhs)
Definition: L1TopoDataTypes.h:227
get_generator_info.result
result
Definition: get_generator_info.py:21
detail::ll
long long ll
Definition: PrimitiveHelpers.h:46
CaloCellPos2Ntuple.int
int
Definition: CaloCellPos2Ntuple.py:24
hist_file_dump.d
d
Definition: hist_file_dump.py:137
TSU::L1TopoDataTypes::prec
unsigned int prec() const
Definition: L1TopoDataTypes.h:216
TSU::L1TopoDataTypes::operator*=
L1TopoDataTypes & operator*=(const int &factor)
Definition: L1TopoDataTypes.h:144
python.AthDsoLogger.out
out
Definition: AthDsoLogger.py:71
athena.value
value
Definition: athena.py:124
TSU
Definition: Conversions.h:11
checkRpcDigits.digit
digit
Definition: checkRpcDigits.py:186
const
bool const RAWDATA *ch2 const
Definition: LArRodBlockPhysicsV0.cxx:560
xAOD::unsigned
unsigned
Definition: RingSetConf_v1.cxx:662
python.utils.AtlRunQueryLookup.mask
string mask
Definition: AtlRunQueryLookup.py:460
TSU::L1TopoDataTypes
Definition: L1TopoDataTypes.h:51
TSU::to_binary
std::string to_binary(T value, const unsigned int &p)
Definition: L1TopoDataTypes.cxx:42
TSU::L1TopoDataTypes::L1TopoDataTypes
L1TopoDataTypes(T v)
Definition: L1TopoDataTypes.h:63
MAXBITS
#define MAXBITS
Definition: L1TopoDataTypes.h:19
TSU::L1TopoDataTypes::operator<<
friend std::ostream & operator<<(std::ostream &os, const L1TopoDataTypes &d)
Definition: L1TopoDataTypes.h:193
TSU::L1TopoDataTypes::operator+
friend L1TopoDataTypes<((P1-F1) >P2-F2) ?(P1-F1) :(P2-F2))+((F1 > F2) ? F1 :F2),(F1 > F2) ? F1 :F2 > operator+(const L1TopoDataTypes< P1, F1 > &lhs, const L1TopoDataTypes< P2, F2 > &rhs)
Definition: L1TopoDataTypes.h:227
python.utils.AtlRunQueryDQUtils.p
p
Definition: AtlRunQueryDQUtils.py:210
TSU::L1TopoDataTypes::m_tvalue
T m_tvalue
Definition: L1TopoDataTypes.h:220
lumiFormat.i
int i
Definition: lumiFormat.py:85
TSU::L1TopoDataTypes::abs
T abs() const
Definition: L1TopoDataTypes.h:114
beamspotman.n
n
Definition: beamspotman.py:731
checkxAOD.frac
frac
Definition: Tools/PyUtils/bin/checkxAOD.py:259
res
std::pair< std::vector< unsigned int >, bool > res
Definition: JetGroupProductTest.cxx:14
TSU::L1TopoDataTypes::complement
T complement() const
Definition: L1TopoDataTypes.h:121
hist_file_dump.f
f
Definition: hist_file_dump.py:135
ReadFromCoolCompare.os
os
Definition: ReadFromCoolCompare.py:231
TSU::L1TopoDataTypes::value
T value() const
Definition: L1TopoDataTypes.h:110
plotBeamSpotMon.b
b
Definition: plotBeamSpotMon.py:77
python.PyAthena.v
v
Definition: PyAthena.py:154
TSU::to_float
float to_float(const T &va, const unsigned int &p, const unsigned int &f)
Definition: L1TopoDataTypes.cxx:53
TSU::L1TopoDataTypes::operator*
friend L1TopoDataTypes< P, FF > operator*(const int &factor, L1TopoDataTypes< P, FF > d)
Definition: L1TopoDataTypes.h:316
TSU::operator-
L1TopoDataTypes<((P1-F1) >P2-F2) ?(P1-F1) :(P2-F2))+((F1 > F2) ? F1 :F2),(F1 > F2) ? F1 :F2 > operator-(const L1TopoDataTypes< P1, F1 > lhs, const L1TopoDataTypes< P2, F2 > rhs)
Definition: L1TopoDataTypes.h:239
ones
T ones(unsigned int n)
Return a bit mask with the lower n bits set.
Definition: L1TopoDataTypes.h:26
TSU::convert
T convert(const unsigned long long &v, const unsigned &in_p, const unsigned int &in_f, const unsigned int &out_p, const unsigned int &out_f)
TSU::L1TopoDataTypes::frac
unsigned int frac() const
Definition: L1TopoDataTypes.h:217
F
#define F(x, y, z)
Definition: MD5.cxx:112
LArNewCalib_DelayDump_OFC_Cali.idx
idx
Definition: LArNewCalib_DelayDump_OFC_Cali.py:69
TSU::complement
T complement(const T &v, const unsigned int &p)
Definition: L1TopoDataTypes.cxx:18
jobOptions.prec
prec
Definition: jobOptions.Superchic_UPC_yyMuMu.py:20
TSU::L1TopoDataTypes::to_float
float to_float() const
Definition: L1TopoDataTypes.h:203
readCCLHist.float
float
Definition: readCCLHist.py:83
TSU::L1TopoDataTypes::operator-
L1TopoDataTypes & operator-()
Definition: L1TopoDataTypes.h:138
TSU::T
unsigned long long T
Definition: L1TopoDataTypes.h:35
detail::ull
unsigned long long ull
Definition: PrimitiveHelpers.h:44