DESY Hbb Analysis Framework
Utilities.h
Go to the documentation of this file.
1 #ifndef Analysis_Tools_Utilities_h
2 #define Analysis_Tools_Utilities_h
3 
4 // Original code: CMSSW_10_2_22 - CondFormats/JetMETObjects/interface/Utilities.h
5 
6 #include <stdexcept>
7 #include <cstdlib>
8 #include <sstream>
9 #include <string>
10 #include <vector>
11 #include <tuple>
12 #include <cmath>
13 #include <utility>
14 
15 namespace std
16 {
17  //These functions print a tuple using a provided std::ostream
18  template<typename Type, unsigned N, unsigned Last>
19  struct tuple_printer {
20 
21  static void print(std::ostream& out, const Type& value) {
22  out << std::get<N>(value) << ", ";
24  }
25  };
26  template<typename Type, unsigned N>
27  struct tuple_printer<Type, N, N> {
28 
29  static void print(std::ostream& out, const Type& value) {
30  out << std::get<N>(value);
31  }
32 
33  };
34  template<typename... Types>
35  std::ostream& operator<<(std::ostream& out, const std::tuple<Types...>& value) {
36  out << "(";
37  tuple_printer<std::tuple<Types...>, 0, sizeof...(Types) - 1>::print(out, value);
38  out << ")";
39  return out;
40  }
41  //----------------------------------------------------------------------
42  //Returns a list of type indices
43  template <size_t... n>
45  template <size_t m>
46  struct push_back
47  {
48  typedef ct_integers_list<n..., m> type;
49  };
50  };
51  template <size_t max>
52  struct ct_iota_1
53  {
54  typedef typename ct_iota_1<max-1>::type::template push_back<max>::type type;
55  };
56  template <>
57  struct ct_iota_1<0>
58  {
60  };
61  //----------------------------------------------------------------------
62  //Return a tuple which is a subset of the original tuple
63  //This function pops an entry off the font of the tuple
64  template <size_t... indices, typename Tuple>
66  -> decltype(std::make_tuple(std::get<indices>(tpl)...))
67  {
68  return std::make_tuple(std::get<indices>(tpl)...);
69  // this means:
70  // make_tuple(get<indices[0]>(tpl), get<indices[1]>(tpl), ...)
71  }
72  template <typename Head, typename... Tail>
73  std::tuple<Tail...> tuple_tail(const std::tuple<Head, Tail...>& tpl)
74  {
75  return tuple_subset(tpl, typename ct_iota_1<sizeof...(Tail)>::type());
76  // this means:
77  // tuple_subset<1, 2, 3, ..., sizeof...(Tail)-1>(tpl, ..)
78  }
79  //----------------------------------------------------------------------
80  //Recursive hashing function for tuples
81  template<typename Head, typename... ndims> struct hash_specialization
82  {
83  typedef std::tuple<Head,ndims...> argument_type;
84  typedef std::size_t result_type;
85  result_type operator()(const argument_type& t) const
86  {
87  const uint32_t& b = reinterpret_cast<const uint32_t&>(std::get<0>(t));
88  //const uint32_t& more = (*this)(tuple_tail(t));
89  const uint32_t& more = hash_specialization<ndims...>()(tuple_tail(t));
90  return b^more;
91  }
92  };
93  //Base case
94  template<> struct hash_specialization<float>
95  {
96  typedef std::tuple<float> argument_type;
97  typedef std::size_t result_type;
98  result_type operator()(const argument_type& t) const
99  {
100  const uint32_t& b = reinterpret_cast<const uint32_t&>(std::get<0>(t));
101  return static_cast<result_type>(b);
102  }
103  };
104  //Overloaded verions of std::hash for tuples
105  template<typename Head, typename... ndims> struct hash<std::tuple<Head, ndims...> >
106  {
107  typedef std::tuple<Head,ndims...> argument_type;
108  typedef std::size_t result_type;
109  result_type operator()(const argument_type& t) const
110  {
111  return hash_specialization<Head,ndims...>()(t);
112  }
113  };
114  template<> struct hash<std::tuple<> >
115  {
116  typedef std::tuple<> argument_type;
117  typedef std::size_t result_type;
118  result_type operator()(const argument_type& t) const
119  {
120  return -1;
121  }
122  };
123 }
124 
125 namespace
126 {
127  void handleError(const std::string& fClass, const std::string& fMessage)
128  {
129  std::stringstream sserr;
130  sserr<<fClass<<" ERROR: "<<fMessage;
131  throw std::runtime_error(sserr.str());
132  }
133  //----------------------------------------------------------------------
134  inline float getFloat(const std::string& token)
135  {
136  char* endptr;
137  float result = strtod (token.c_str(), &endptr);
138  if (endptr == token.c_str())
139  {
140  std::stringstream sserr;
141  sserr<<"can't convert token "<<token<<" to float value";
142  handleError("getFloat",sserr.str());
143  }
144  return result;
145  }
146  //----------------------------------------------------------------------
147  inline unsigned getUnsigned(const std::string& token)
148  {
149  char* endptr;
150  unsigned result = strtoul (token.c_str(), &endptr, 0);
151  if (endptr == token.c_str())
152  {
153  std::stringstream sserr;
154  sserr<<"can't convert token "<<token<<" to unsigned value";
155  handleError("getUnsigned",sserr.str());
156  }
157  return result;
158  }
159  inline long int getSigned(const std::string& token)
160  {
161  char* endptr;
162  unsigned result = strtol (token.c_str(), &endptr, 0);
163  if (endptr == token.c_str())
164  {
165  std::stringstream sserr;
166  sserr<<"can't convert token "<<token<<" to signed value";
167  handleError("getSigned",sserr.str());
168  }
169  return result;
170  }
171  //----------------------------------------------------------------------
172  inline std::string getSection(const std::string& token)
173  {
174  size_t iFirst = token.find ('[');
175  size_t iLast = token.find (']');
176  if (iFirst != std::string::npos && iLast != std::string::npos && iFirst < iLast)
177  return std::string (token, iFirst+1, iLast-iFirst-1);
178  return "";
179  }
180  //----------------------------------------------------------------------
181  inline std::vector<std::string> getTokens(const std::string& fLine)
182  {
183  std::vector<std::string> tokens;
184  std::string currentToken;
185  for (unsigned ipos = 0; ipos < fLine.length (); ++ipos)
186  {
187  char c = fLine[ipos];
188  if (c == '#') break; // ignore comments
189  else if (c == ' ')
190  { // flush current token if any
191  if (!currentToken.empty())
192  {
193  tokens.push_back(currentToken);
194  currentToken.clear();
195  }
196  }
197  else
198  currentToken += c;
199  }
200  if (!currentToken.empty()) tokens.push_back(currentToken); // flush end
201  return tokens;
202  }
203  //----------------------------------------------------------------------
204  inline std::string getDefinitions(const std::string& token)
205  {
206  size_t iFirst = token.find ('{');
207  size_t iLast = token.find ('}');
208  if (iFirst != std::string::npos && iLast != std::string::npos && iFirst < iLast)
209  return std::string (token, iFirst+1, iLast-iFirst-1);
210  return "";
211  }
212  //------------------------------------------------------------------------
213  inline float quadraticInterpolation(float fZ, const float fX[3], const float fY[3])
214  {
215  // Quadratic interpolation through the points (x[i],y[i]). First find the parabola that
216  // is defined by the points and then calculate the y(z).
217  float D[4],a[3];
218  D[0] = fX[0]*fX[1]*(fX[0]-fX[1])+fX[1]*fX[2]*(fX[1]-fX[2])+fX[2]*fX[0]*(fX[2]-fX[0]);
219  D[3] = fY[0]*(fX[1]-fX[2])+fY[1]*(fX[2]-fX[0])+fY[2]*(fX[0]-fX[1]);
220  D[2] = fY[0]*(pow(fX[2],2)-pow(fX[1],2))+fY[1]*(pow(fX[0],2)-pow(fX[2],2))+fY[2]*(pow(fX[1],2)-pow(fX[0],2));
221  D[1] = fY[0]*fX[1]*fX[2]*(fX[1]-fX[2])+fY[1]*fX[0]*fX[2]*(fX[2]-fX[0])+fY[2]*fX[0]*fX[1]*(fX[0]-fX[1]);
222  if (D[0] != 0)
223  {
224  a[0] = D[1]/D[0];
225  a[1] = D[2]/D[0];
226  a[2] = D[3]/D[0];
227  }
228  else
229  {
230  a[0] = 0.0;
231  a[1] = 0.0;
232  a[2] = 0.0;
233  }
234  float r = a[0]+fZ*(a[1]+fZ*a[2]);
235  return r;
236  }
237  //------------------------------------------------------------------------
238  //Generates a std::tuple type based on a stored type and the number of
239  // objects in the tuple.
240  //Note: All of the objects will be of the same type
241  template<typename /*LEFT_TUPLE*/, typename /*RIGHT_TUPLE*/>
242  struct join_tuples
243  {
244  };
245  template<typename... LEFT, typename... RIGHT>
246  struct join_tuples<std::tuple<LEFT...>, std::tuple<RIGHT...>>
247  {
248  typedef std::tuple<LEFT..., RIGHT...> type;
249  };
250  template<typename T, unsigned N>
251  struct generate_tuple_type
252  {
253  typedef typename generate_tuple_type<T, N/2>::type left;
254  typedef typename generate_tuple_type<T, N/2 + N%2>::type right;
255  typedef typename join_tuples<left, right>::type type;
256  };
257  template<typename T>
258  struct generate_tuple_type<T, 1>
259  {
260  typedef std::tuple<T> type;
261  };
262  template<typename T>
263  struct generate_tuple_type<T, 0>
264  {
265  typedef std::tuple<> type;
266  };
267  //------------------------------------------------------------------------
268  //C++11 implementation of make_index_sequence, which is a C++14 function
269  // using aliases for cleaner syntax
270  template<class T> using Invoke = typename T::type;
271 
272  template<unsigned...> struct seq{ using type = seq; };
273 
274  template<class S1, class S2> struct concat;
275 
276  template<unsigned... I1, unsigned... I2>
277  struct concat<seq<I1...>, seq<I2...>>
278  : seq<I1..., (sizeof...(I1)+I2)...>{};
279 
280  template<class S1, class S2>
281  using Concat = Invoke<concat<S1, S2>>;
282 
283  template<unsigned N> struct gen_seq;
284  template<unsigned N> using GenSeq = Invoke<gen_seq<N>>;
285 
286  template<unsigned N>
287  struct gen_seq : Concat<GenSeq<N/2>, GenSeq<N - N/2>>{};
288 
289  template<> struct gen_seq<0> : seq<>{};
290  template<> struct gen_seq<1> : seq<0>{};
291  //------------------------------------------------------------------------
292  //Generates a tuple based on a given function (i.e. lambda expression)
293  template <typename F, unsigned... Is>
294  auto gen_tuple_impl(F func, seq<Is...> )
295  -> decltype(std::make_tuple(func(Is)...))
296  {
297  return std::make_tuple(func(Is)...);
298  }
299  template <unsigned N, typename F>
300  auto gen_tuple(F func)
301  -> decltype(gen_tuple_impl(func, GenSeq<N>() ))
302  {
303  return gen_tuple_impl(func, GenSeq<N>() );
304  }
305 }
306 #endif
std::tuple< Head, ndims... > argument_type
Definition: Utilities.h:83
std::tuple< Tail... > tuple_tail(const std::tuple< Head, Tail... > &tpl)
Definition: Utilities.h:73
auto tuple_subset(const Tuple &tpl, ct_integers_list< indices... >) -> decltype(std::make_tuple(std::get< indices >(tpl)...))
Definition: Utilities.h:65
ct_iota_1< max-1 >::type::template push_back< max >::type type
Definition: Utilities.h:54
result_type operator()(const argument_type &t) const
Definition: Utilities.h:98
result_type operator()(const argument_type &t) const
Definition: Utilities.h:109
static void print(std::ostream &out, const Type &value)
Definition: Utilities.h:29
std::tuple< Head, ndims... > argument_type
Definition: Utilities.h:107
std::ostream & operator<<(std::ostream &out, const std::tuple< Types... > &value)
Definition: Utilities.h:35
float T
Definition: PlotsCompare.cc:18
std::tuple< float > argument_type
Definition: Utilities.h:96
std::size_t result_type
Definition: Utilities.h:84
ct_integers_list type
Definition: Utilities.h:59
result_type operator()(const argument_type &t) const
Definition: Utilities.h:85
static void print(std::ostream &out, const Type &value)
Definition: Utilities.h:21
result_type operator()(const argument_type &t) const
Definition: Utilities.h:118
ct_integers_list< n..., m > type
Definition: Utilities.h:48