ATLAS Offline Software
Loading...
Searching...
No Matches
L1TopoDataTypes.h
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 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 */
18#ifndef MAXBITS
19#define MAXBITS 64
20#endif
21
22
24template <class T>
25consteval
26T 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
33namespace 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:
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
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() const {
81 return this->to_float();
82 }
83
84 operator int() const {
85 return ones<T>(PREC-F)&((m_tvalue>>F));
86 }
87
88 operator unsigned() const {
89 return ones<T>(PREC-F)&((m_tvalue>>F));
90 }
91
92 operator int64_t() const {
93 return ones<T>(PREC-F)&((m_tvalue>>F));
94 }
95
96 operator unsigned long long() const {
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 // product of two numbers with different representation
159 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);
160
161 // product of two numbers with different representation
162 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);
163
164 // overloaded operator<<
165 friend std::ostream& operator<<(std::ostream& os, const L1TopoDataTypes& d){
166 std::string out;
167 for(int j=PREC-1;j>=0;--j){
168 out += ((d.m_tvalue>>j)&1ull) ? "1" : "0";
169 }
170 os << "integer value " << d.m_tvalue << " binary " << out << " float " << d.to_float();
171 return os;
172 }
173
174 // return float representation
175 float to_float() const {
176 // Find sign
177 float res = ((m_tvalue>>(PREC-1ull))&1ull) ? -(1ll<<(PREC-F)) : 0.;
178 // Get integer part
179 res += (m_tvalue>>F)&((1ull<<(PREC-F))-1ull) ? float((m_tvalue>>F)&((1ull<<(PREC-F))-1ull)) : 0;
180 // Do the fractional part
181 if (F > 0) {
182 unsigned frac = m_tvalue & ( (1ull<<F)-1ull );
183 res += static_cast<float>(frac) / (2ull<<(F-1ull));
184 }
185 return res;
186 }
187
188 constexpr unsigned int prec() const { return PREC; }
189 constexpr unsigned int frac() const { return F; }
190
191 private:
193 };
194
195 // get the 2's complement of bitset with p bits
196 T complement(const T& v, const unsigned int& p);
197
198 // masks from Qm.n to a Qm1.n1, where in_p and in_f = total number of bits and of fraction part of input
199 //T convert(const unsigned int& v, const unsigned& in_p, const unsigned int& in_f,
200 // const unsigned int& out_p, const unsigned int& out_f);
201
202 // represent T value with p bits as binary
203 std::string to_binary(T value, const unsigned int& p);
204
205 // represent Qm.n number as float with p = total number of bits, f = number of fractional bits
206 float to_float(const T& va, const unsigned int& p, const unsigned int& f);
207
208 // operator+ for L1TopoDataTypes
209 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){
210 constexpr unsigned int frac = (F1 > F2) ? F1 : F2;
211 constexpr unsigned int digit = ((P1-F1) > (P2-F2)) ? (P1-F1) - 1 : (P2-F2) - 1;
212 constexpr unsigned int prec = frac + digit + 1;
213 T lhsconvert = convert(lhs.m_tvalue,P1,F1,prec,frac);
214 T rhsconvert = convert(rhs.m_tvalue,P2,F2,prec,frac);
215 L1TopoDataTypes<prec,frac> res(lhsconvert+rhsconvert);
216
217 return res;
218 }
219
220 // operator- for L1TopoDataTypes
221 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){
222 constexpr unsigned int frac = (F1 > F2) ? F1 : F2;
223 constexpr unsigned int digit = ((P1-F1) > (P2-F2)) ? (P1-F1) - 1 : (P2-F2) - 1;
224 constexpr unsigned int prec = frac + digit + 1;
225 T lhsconvert = convert(lhs.m_tvalue,P1,F1,prec,frac);
226 T rhsconvert = convert(rhs.m_tvalue,P2,F2,prec,frac);
227 L1TopoDataTypes<prec,frac> res(lhsconvert+complement(rhsconvert,prec));
228
229 return res;
230 }
231
232 template<unsigned P1, unsigned F1> L1TopoDataTypes<P1+1,F1> operator-(const double& lhs, const L1TopoDataTypes<P1,F1>& rhs){
233 return L1TopoDataTypes<P1+1,F1>(lhs - static_cast<float>(rhs));
234 }
235
236 template<unsigned P1, unsigned F1> L1TopoDataTypes<P1+1,F1> operator-(const L1TopoDataTypes<P1,F1>& lhs, const double& rhs){
237 return L1TopoDataTypes<P1+1,F1>(static_cast<float>(lhs) - rhs);
238 }
239
240 template<unsigned P1, unsigned F1> L1TopoDataTypes<P1+1,F1> operator-(const int& lhs, const L1TopoDataTypes<P1,F1>& rhs){
241 return L1TopoDataTypes<P1+1,F1>(lhs - static_cast<float>(rhs));
242 }
243
244 template<unsigned P1, unsigned F1> L1TopoDataTypes<P1+1,F1> operator-(const L1TopoDataTypes<P1,F1>& lhs, const int& rhs){
245 return L1TopoDataTypes<P1+1,F1>(static_cast<float>(lhs) - rhs);
246 }
247
248 template<unsigned P1, unsigned F1> L1TopoDataTypes<P1+1,F1> operator+(const double& lhs, const L1TopoDataTypes<P1,F1>& rhs){
249 return L1TopoDataTypes<P1+1,F1>(lhs + static_cast<float>(rhs));
250 }
251
252 template<unsigned P1, unsigned F1> L1TopoDataTypes<P1+1,F1> operator+(const L1TopoDataTypes<P1,F1>& lhs, const double& rhs){
253 return L1TopoDataTypes<P1+1,F1>(static_cast<float>(lhs) + rhs);
254 }
255
256 template<unsigned P1, unsigned F1> L1TopoDataTypes<P1+1,F1> operator+(const int& lhs, const L1TopoDataTypes<P1,F1>& rhs){
257 return L1TopoDataTypes<P1+1,F1>(lhs + static_cast<float>(rhs));
258 }
259
260 template<unsigned P1, unsigned F1> L1TopoDataTypes<P1+1,F1> operator+(const L1TopoDataTypes<P1,F1>& lhs, const int& rhs){
261 return L1TopoDataTypes<P1+1,F1>(static_cast<float>(lhs) + rhs);
262 }
263
264
265 // operator* for L1TopoDataTypes
266 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){
267 constexpr unsigned int frac = (P1+P2-1 > MAXBITS) ? (F2>F1 ? F2 - ((P1+P2-1) - MAXBITS) : F1 - ((P1+P2-1) - MAXBITS)) : ((F1 > F2) ? F1 : F2);
268 constexpr unsigned int digit = ((P1+P2-1 > MAXBITS) ? (MAXBITS - frac) : (P1+P2-1 - frac)) - 1;
269 constexpr unsigned int prec = frac + digit + 1;
270 T lhsconvert = lhs.m_tvalue;
271 T rhsconvert = rhs.m_tvalue;
272 // check if either value is negative and work with the absolute value
273 if((lhs.m_tvalue >> (P1-1ull)) & 1ull){
274 lhsconvert = complement(lhsconvert,P1);
275 }
276 if((rhs.m_tvalue >> (P2-1ull)) & 1ull){
277 rhsconvert = complement(rhsconvert,P2);
278 }
279 // map numbers into Q1+digit.frac
280 T lhsconvint = convert(lhsconvert,P1,F1,P1-F1,0);
281 T rhsconvint = convert(rhsconvert,P2,F2,P2-F2,0);
282 T lhsconvfrac = convert(lhsconvert,P1,F1,F1+1,F1);
283 T rhsconvfrac = convert(rhsconvert,P2,F2,F2+1,F2);
284 T prod_int = lhsconvint*rhsconvint; // PREC = P1-F1+P2-F2-1, F = 0
285 T prod_frac = lhsconvfrac*rhsconvfrac; // PREC = F1 + F2 + 1, F = F1 + F2
286 T prod_mix1 = lhsconvint*rhsconvfrac; // PREC = P1 - F1 + F2, F = F2
287 T prod_mix2 = lhsconvfrac*rhsconvint; // PREC = P2 - F2 + F1, F = F1
289 result += (prod_frac>>(F1+F2-frac));
290 result += (prod_mix1>>((F2>frac ? F2 - frac : 0)));
291 result += (prod_mix2>>((F1>frac ? F1 - frac : 0)));
292 if(!(((lhs.m_tvalue >> (P1-1ull)) & 1ull) ^ ((rhs.m_tvalue >> (P2-1ull)) & 1ull))){
293 return result;
294 } else
295 return -result;
296 }
297
298 template<unsigned P, unsigned FF> TSU::L1TopoDataTypes<P,FF> operator*(const int& factor, TSU::L1TopoDataTypes<P,FF> d){
299 return d*=factor;
300 }
301
302 template<unsigned P, unsigned FF> TSU::L1TopoDataTypes<P,FF> operator*(TSU::L1TopoDataTypes<P,FF> d, const int& factor){
303 return d*=factor;
304 }
305
306} // namespace
307#endif
std::pair< std::vector< unsigned int >, bool > res
#define MAXBITS
consteval T ones(unsigned int n)
Return a bit mask with the lower n bits set.
#define F(x, y, z)
Definition MD5.cxx:112
constexpr unsigned int frac() const
L1TopoDataTypes & operator-()
friend std::ostream & operator<<(std::ostream &os, const L1TopoDataTypes &d)
L1TopoDataTypes & operator*=(const int &factor)
friend L1TopoDataTypes< P, FF > operator*(const int &factor, L1TopoDataTypes< P, FF > d)
L1TopoDataTypes(unsigned i)
constexpr unsigned int prec() const
L1TopoDataTypes(const std::string &b="")
L1TopoDataTypes & operator+=(const T &value)
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)
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)
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)
float to_float(const T &va, const unsigned int &p, const unsigned int &f)
std::string to_binary(T value, const unsigned int &p)
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)
unsigned long long T
T complement(const T &v, const unsigned int &p)