rivet is hosted by Hepforge, IPPP Durham
Rivet  2.7.0
Utils.hh
1 // -*- C++ -*-
2 #ifndef RIVET_Utils_HH
3 #define RIVET_Utils_HH
4 
5 #include "Rivet/Tools/RivetSTL.hh"
6 #include "Rivet/Tools/PrettyPrint.hh"
7 #include <ostream>
8 #include <iostream>
9 #include <cctype>
10 #include <cerrno>
11 #include <stdexcept>
12 #include <numeric>
13 #include <limits>
14 #include <climits>
15 #include <cfloat>
16 #include <cmath>
17 
18 
19 // // Macro to help with overzealous compiler warnings
20 // /// @note It's easier and better to just not give an arg name to args which won't be used, when possible.
21 // #ifdef UNUSED
22 // #elif defined(__GNUC__)
23 // # define UNUSED(x) UNUSED_ ## x __attribute__((unused))
24 // #elif defined(__LCLINT__)
25 // # define UNUSED(x) /*@unused@*/ x
26 // #else
27 // # define UNUSED(x) x
28 // #endif
29 
30 
32 #ifndef DEPRECATED
33 #if __GNUC__ && __cplusplus && RIVET_NO_DEPRECATION_WARNINGS == 0
34 #define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
35 #if GCC_VERSION >= 40500
36  #if __cplusplus > 201103L
37  #define DEPRECATED(x) [[deprecated(x)]]
38  #else
39  #define DEPRECATED(x) __attribute__((deprecated(x)))
40  #endif
41 #else
42  #define DEPRECATED(x) __attribute__((deprecated))
43 #endif
44 #else
45  #define DEPRECATED(x)
46 #endif
47 #endif
48 
49 
50 namespace Rivet {
51 
52 
54  static constexpr double DBL_NAN = std::numeric_limits<double>::quiet_NaN();
55 
56 
58 
59 
60  struct bad_lexical_cast : public std::runtime_error {
61  bad_lexical_cast(const std::string& what) : std::runtime_error(what) {}
62  };
63 
65  template<typename T, typename U>
66  T lexical_cast(const U& in) {
67  try {
68  std::stringstream ss;
69  ss << in;
70  T out;
71  ss >> out;
72  return out;
73  } catch (const std::exception& e) {
74  throw bad_lexical_cast(e.what());
75  }
76  }
77 
81  template <typename T>
82  inline string to_str(const T& x) {
83  return lexical_cast<string>(x);
84  }
85 
89  template <typename T>
90  inline string toString(const T& x) {
91  return to_str(x);
92  }
93 
95  inline string& replace_first(string& str, const string& patt, const string& repl) {
96  if (!contains(str, patt)) return str; //< contains from RivetSTL
97  str.replace(str.find(patt), patt.size(), repl);
98  return str;
99  }
100 
106  inline string& replace_all(string& str, const string& patt, const string& repl) {
107  if (!contains(str, patt)) return str; //< contains from RivetSTL
108  while (true) {
109  string::size_type it = str.find(patt);
110  if (it == string::npos) break;
111  str.replace(it, patt.size(), repl);
112  }
113  return str;
114  }
115 
116 
118  inline int nocase_cmp(const string& s1, const string& s2) {
119  string::const_iterator it1 = s1.begin();
120  string::const_iterator it2 = s2.begin();
121  while ( (it1 != s1.end()) && (it2 != s2.end()) ) {
122  if(::toupper(*it1) != ::toupper(*it2)) { // < Letters differ?
123  // Return -1 to indicate smaller than, 1 otherwise
124  return (::toupper(*it1) < ::toupper(*it2)) ? -1 : 1;
125  }
126  // Proceed to the next character in each string
127  ++it1;
128  ++it2;
129  }
130  size_t size1 = s1.size(), size2 = s2.size(); // Cache lengths
131  // Return -1,0 or 1 according to strings' lengths
132  if (size1 == size2) return 0;
133  return (size1 < size2) ? -1 : 1;
134  }
135 
136 
138  inline bool nocase_equals(const string& s1, const string& s2) {
139  return nocase_cmp(s1, s2) == 0;
140  }
141 
142 
144  inline string toLower(const string& s) {
145  string out = s;
146  std::transform(out.begin(), out.end(), out.begin(), (int(*)(int)) std::tolower);
147  return out;
148  }
149 
150 
152  inline string toUpper(const string& s) {
153  string out = s;
154  std::transform(out.begin(), out.end(), out.begin(), (int(*)(int)) std::toupper);
155  return out;
156  }
157 
158 
160  inline bool startsWith(const string& s, const string& start) {
161  if (s.length() < start.length()) return false;
162  return s.substr(0, start.length()) == start;
163  }
164 
165 
167  inline bool endsWith(const string& s, const string& end) {
168  if (s.length() < end.length()) return false;
169  return s.substr(s.length() - end.length()) == end;
170  }
171 
172 
174  template <typename T>
175  inline string join(const vector<T>& v, const string& sep=" ") {
176  string rtn;
177  for (size_t i = 0; i < v.size(); ++i) {
178  if (i != 0) rtn += sep;
179  rtn += to_str(v[i]);
180  }
181  return rtn;
182  }
183 
185  template <typename T>
186  inline string join(const set<T>& s, const string& sep=" ") {
187  string rtn;
188  for (const T& x : s) {
189  if (rtn.size() > 0) rtn += sep;
190  rtn += to_str(x);
191  }
192  return rtn;
193  }
194 
196  inline vector<string> split(const string& s, const string& sep) {
197  vector<string> dirs;
198  string tmp = s;
199  while (true) {
200  const size_t delim_pos = tmp.find(sep);
201  if (delim_pos == string::npos) break;
202  const string dir = tmp.substr(0, delim_pos);
203  if (dir.length()) dirs.push_back(dir); // Don't insert "empties"
204  tmp.replace(0, delim_pos+1, "");
205  }
206  if (tmp.length()) dirs.push_back(tmp); // Don't forget the trailing component!
207  return dirs;
208  }
209 
211 
212 
214 
215 
219  inline vector<string> pathsplit(const string& path) {
220  return split(path, ":");
221  }
222 
223 
228  inline string pathjoin(const vector<string>& paths) {
229  return join(paths, ":");
230  }
231 
233  inline string operator / (const string& a, const string& b) {
234  // Ensure that a doesn't end with a slash, and b doesn't start with one, to avoid "//"
235  const string anorm = (a.find("/") != string::npos) ? a.substr(0, a.find_last_not_of("/")+1) : a;
236  const string bnorm = (b.find("/") != string::npos) ? b.substr(b.find_first_not_of("/")) : b;
237  return anorm + "/" + bnorm;
238  }
239 
241  inline string basename(const string& p) {
242  if (!contains(p, "/")) return p;
243  return p.substr(p.rfind("/")+1);
244  }
245 
247  inline string dirname(const string& p) {
248  if (!contains(p, "/")) return "";
249  return p.substr(0, p.rfind("/"));
250  }
251 
253  inline string file_stem(const string& f) {
254  if (!contains(f, ".")) return f;
255  return f.substr(0, f.rfind("."));
256  }
257 
259  inline string file_extn(const string& f) {
260  if (!contains(f, ".")) return "";
261  return f.substr(f.rfind(".")+1);
262  }
263 
265 
266 
268 
269 
271  template <typename CONTAINER>
272  inline unsigned int count(const CONTAINER& c) {
273  // return std::count_if(std::begin(c), std::end(c), [](const typename CONTAINER::value_type& x){return bool(x);});
274  unsigned int rtn = 0;
275  for (const auto& x : c) if (bool(x)) rtn += 1;
276  return rtn;
277  }
278 
280  template <typename CONTAINER, typename FN>
281  inline unsigned int count(const CONTAINER& c, const FN& f) {
282  return std::count_if(std::begin(c), std::end(c), f);
283  }
284 
286  template <typename CONTAINER>
287  inline bool any(const CONTAINER& c) {
288  // return std::any_of(std::begin(c), std::end(c), [](const auto& x){return bool(x);});
289  for (const auto& x : c) if (bool(x)) return true;
290  return false;
291  }
292 
294  template <typename CONTAINER, typename FN>
295  inline bool any(const CONTAINER& c, const FN& f) {
296  return std::any_of(std::begin(c), std::end(c), f);
297  }
298 
300  template <typename CONTAINER>
301  inline bool all(const CONTAINER& c) {
302  // return std::all_of(std::begin(c), std::end(c), [](const auto& x){return bool(x);});
303  for (const auto& x : c) if (!bool(x)) return false;
304  return true;
305  }
306 
308  template <typename CONTAINER, typename FN>
309  inline bool all(const CONTAINER& c, const FN& f) {
310  return std::all_of(std::begin(c), std::end(c), f);
311  }
312 
314  template <typename CONTAINER>
315  inline bool none(const CONTAINER& c) {
316  // return std::none_of(std::begin(c), std::end(c), [](){});
317  for (const auto& x : c) if (bool(x)) return false;
318  return true;
319  }
320 
322  template <typename CONTAINER, typename FN>
323  inline bool none(const CONTAINER& c, const FN& f) {
324  return std::none_of(std::begin(c), std::end(c), f);
325  }
326 
327 
329  template <typename C1, typename C2, typename FN>
330  inline const C2& transform(const C1& in, C2& out, const FN& f) {
331  out.clear(); out.resize(in.size());
332  std::transform(in.begin(), in.end(), out.begin(), f);
333  return out;
334  }
335 
337  template <typename C1, typename T, typename FN>
338  inline T accumulate(const C1& in, const T& init, const FN& f) {
339  const T rtn = std::accumulate(in.begin(), in.end(), init, f);
340  return rtn;
341  }
342 
344  template <typename CONTAINER, typename T>
345  inline T sum(const CONTAINER& c, const T& start=T()) {
346  T rtn = start;
347  for (const auto& x : c) rtn += x;
348  return rtn;
349  }
350 
352  template <typename CONTAINER, typename FN, typename T>
353  inline T sum(const CONTAINER& c, const FN& f, const T& start=T()) {
354  T rtn = start;
355  for (const auto& x : c) rtn += f(x);
356  return rtn;
357  }
358 
359 
361  template <typename CONTAINER, typename FN>
362  inline CONTAINER& ifilter_discard(CONTAINER& c, const FN& f) {
363  const auto newend = std::remove_if(std::begin(c), std::end(c), f);
364  c.erase(newend, c.end());
365  return c;
366  }
367 
369  template <typename CONTAINER, typename FN>
370  inline CONTAINER filter_discard(const CONTAINER& c, const FN& f) {
371  CONTAINER rtn = c;
372  return ifilter_discard(rtn, f);
373  }
374 
377  template <typename CONTAINER, typename FN>
378  inline CONTAINER& filter_discard(const CONTAINER& c, const FN& f, CONTAINER& out) {
379  out = filter_discard(c, f);
380  return out;
381  }
382 
383 
385  template <typename CONTAINER, typename FN>
386  inline CONTAINER& ifilter_select(CONTAINER& c, const FN& f) {
387  //using value_type = typename std::remove_reference<decltype(*std::begin(std::declval<typename std::add_lvalue_reference<CONTAINER>::type>()))>::type;
388  auto invf = [&](const typename CONTAINER::value_type& x){ return !f(x); };
389  return ifilter_discard(c, invf);
390  }
391 
393  template <typename CONTAINER, typename FN>
394  inline CONTAINER filter_select(const CONTAINER& c, const FN& f) {
395  CONTAINER rtn = c;
396  return ifilter_select(rtn, f);
397  }
398 
401  template <typename CONTAINER, typename FN>
402  inline CONTAINER& filter_select(const CONTAINER& c, const FN& f, CONTAINER& out) {
403  out = filter_select(c, f);
404  return out;
405  }
406 
407 
412  template <typename CONTAINER>
413  inline CONTAINER slice(const CONTAINER& c, int i, int j) {
414  CONTAINER rtn;
415  const size_t off1 = (i >= 0) ? i : c.size() + i;
416  const size_t off2 = (j >= 0) ? j : c.size() + j;
417  if (off1 > c.size() || off2 > c.size()) throw RangeError("Attempting to slice beyond requested offsets");
418  if (off2 < off1) throw RangeError("Requested offsets in invalid order");
419  rtn.resize(off2 - off1);
420  std::copy(c.begin()+off1, c.begin()+off2, rtn.begin());
421  return rtn;
422  }
423 
427  template <typename CONTAINER>
428  inline CONTAINER slice(const CONTAINER& c, int i) {
429  return slice(c, i, c.size());
430  }
431 
435  template <typename CONTAINER>
436  inline CONTAINER head(const CONTAINER& c, int n) {
437  // if (n > c.size()) throw RangeError("Requested head longer than container");
438  if (n < 0) n = std::max(0, (int)c.size()+n);
439  n = std::min(n, (int)c.size());
440  return slice(c, 0, n);
441  }
442 
446  template <typename CONTAINER>
447  inline CONTAINER tail(const CONTAINER& c, int n) {
448  // if (n > c.size()) throw RangeError("Requested tail longer than container");
449  if (n < 0) n = std::max(0, (int)c.size()+n);
450  n = std::min(n, (int)c.size());
451  return slice(c, c.size()-n);
452  }
453 
454 
455  using std::min;
456  using std::max;
457 
459  inline double min(const vector<double>& in, double errval=DBL_NAN) {
460  const auto e = std::min_element(in.begin(), in.end());
461  return e != in.end() ? *e : errval;
462  }
463 
465  inline double max(const vector<double>& in, double errval=DBL_NAN) {
466  const auto e = std::max_element(in.begin(), in.end());
467  return e != in.end() ? *e : errval;
468  }
469 
471  inline pair<double,double> minmax(const vector<double>& in, double errval=DBL_NAN) {
472  const auto e = std::minmax_element(in.begin(), in.end());
473  const double rtnmin = e.first != in.end() ? *e.first : errval;
474  const double rtnmax = e.second != in.end() ? *e.first : errval;
475  return std::make_pair(rtnmin, rtnmax);
476  }
477 
478 
480  inline int min(const vector<int>& in, int errval=-1) {
481  const auto e = std::min_element(in.begin(), in.end());
482  return e != in.end() ? *e : errval;
483  }
484 
486  inline int max(const vector<int>& in, int errval=-1) {
487  const auto e = std::max_element(in.begin(), in.end());
488  return e != in.end() ? *e : errval;
489  }
490 
492  inline pair<int,int> minmax(const vector<int>& in, int errval=-1) {
493  const auto e = std::minmax_element(in.begin(), in.end());
494  const double rtnmin = e.first != in.end() ? *e.first : errval;
495  const double rtnmax = e.second != in.end() ? *e.first : errval;
496  return std::make_pair(rtnmin, rtnmax);
497  }
498 
500 
501 
505  template <typename T>
506  T getEnvParam(const std::string name, const T& fallback) {
507  char* env = getenv(name.c_str());
508  return env ? lexical_cast<T>(env) : fallback;
509  }
510 
511 
512 }
513 
514 #endif
Definition: ALICE_2010_I880049.cc:13
T lexical_cast(const U &in)
Convert between any types via stringstream.
Definition: Utils.hh:66
string dirname(const string &p)
Get the dirname (i.e. path to the penultimate directory) from a path p.
Definition: Utils.hh:247
CONTAINER head(const CONTAINER &c, int n)
Head slice of the n first container elements.
Definition: Utils.hh:436
string toLower(const string &s)
Convert a string to lower-case.
Definition: Utils.hh:144
string pathjoin(const vector< string > &paths)
Join several filesystem paths together with the standard &#39;:&#39; delimiter.
Definition: Utils.hh:228
bool any(const CONTAINER &c)
Return true if x is true for any x in container c, otherwise false.
Definition: Utils.hh:287
bool startsWith(const string &s, const string &start)
Check whether a string start is found at the start of s.
Definition: Utils.hh:160
Definition: Utils.hh:60
bool none(const CONTAINER &c)
Return true if x is false for all x in container c, otherwise false.
Definition: Utils.hh:315
static constexpr double DBL_NAN
Convenient const for getting the double NaN value.
Definition: Utils.hh:54
Jets & ifilter_discard(Jets &jets, const Cut &c)
Filter a jet collection in-place to the subset that fails the supplied Cut.
Definition: JetUtils.cc:14
CONTAINER tail(const CONTAINER &c, int n)
Tail slice of the n last container elements.
Definition: Utils.hh:447
Jets filter_discard(const Jets &jets, const Cut &c)
Filter a jet collection in-place to the subset that fails the supplied Cut.
Definition: JetUtils.hh:165
bool nocase_equals(const string &s1, const string &s2)
Case-insensitive string equality function.
Definition: Utils.hh:138
string & replace_first(string &str, const string &patt, const string &repl)
Replace the first instance of patt with repl.
Definition: Utils.hh:95
string & replace_all(string &str, const string &patt, const string &repl)
Replace all instances of patt with repl.
Definition: Utils.hh:106
Jets filter_select(const Jets &jets, const Cut &c)
Filter a jet collection in-place to the subset that passes the supplied Cut.
Definition: JetUtils.hh:143
int nocase_cmp(const string &s1, const string &s2)
Case-insensitive string comparison function.
Definition: Utils.hh:118
pair< double, double > minmax(const vector< double > &in, double errval=DBL_NAN)
Find the minimum and maximum values in the vector.
Definition: Utils.hh:471
T accumulate(const C1 &in, const T &init, const FN &f)
A single-container-arg version of std::accumulate, aka reduce.
Definition: Utils.hh:338
string file_stem(const string &f)
Get the stem (i.e. part without a file extension) from a filename f.
Definition: Utils.hh:253
CONTAINER slice(const CONTAINER &c, int i, int j)
Slice of the container elements cf. Python&#39;s [i:j] syntax.
Definition: Utils.hh:413
vector< string > split(const string &s, const string &sep)
Split a string on a specified separator string.
Definition: Utils.hh:196
T sum(const CONTAINER &c, const T &start=T())
Generic sum function, adding x for all x in container c, starting with start.
Definition: Utils.hh:345
string toUpper(const string &s)
Convert a string to upper-case.
Definition: Utils.hh:152
bool all(const CONTAINER &c)
Return true if x is true for all x in container c, otherwise false.
Definition: Utils.hh:301
string join(const vector< T > &v, const string &sep=" ")
Make a string containing the string representations of each item in v, separated by sep...
Definition: Utils.hh:175
bool contains(const std::string &s, const std::string &sub)
Does s contain sub as a substring?
Definition: RivetSTL.hh:76
vector< string > pathsplit(const string &path)
Split a path string with colon delimiters.
Definition: Utils.hh:219
double max(const vector< double > &in, double errval=DBL_NAN)
Find the maximum value in the vector.
Definition: Utils.hh:465
T getEnvParam(const std::string name, const T &fallback)
Get a parameter from a named environment variable, with automatic type conversion.
Definition: Utils.hh:506
string file_extn(const string &f)
Get the file extension from a filename f.
Definition: Utils.hh:259
string to_str(const T &x)
Convert any object to a string.
Definition: Utils.hh:82
std::string toString(const AnalysisInfo &ai)
String representation.
Definition: AnalysisInfo.cc:144
bool endsWith(const string &s, const string &end)
Check whether a string end is found at the end of s.
Definition: Utils.hh:167
double min(const vector< double > &in, double errval=DBL_NAN)
Find the minimum value in the vector.
Definition: Utils.hh:459
Jets & ifilter_select(Jets &jets, const Cut &c)
Filter a jet collection in-place to the subset that passes the supplied Cut.
Definition: JetUtils.cc:7
Error for e.g. use of invalid bin ranges.
Definition: Exceptions.hh:22
string basename(const string &p)
Get the basename (i.e. terminal file name) from a path p.
Definition: Utils.hh:241
unsigned int count(const CONTAINER &c)
Return number of true elements in the container c .
Definition: Utils.hh:272