Rivet API documentation

Rivet 4.1.3
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/TypeTraits.hh"
7#include "Rivet/Tools/PrettyPrint.hh"
8#include "Rivet/Tools/Exceptions.hh"
9#include <ostream>
10#include <cctype>
11#include <cerrno>
12#include <stdexcept>
13#include <numeric>
14#include <limits>
15#include <climits>
16#include <cfloat>
17#include <cmath>
18#include <sstream>
19#include <functional>
20
22
23
25#ifndef DEPRECATED
26#if __GNUC__ && __cplusplus && RIVET_NO_DEPRECATION_WARNINGS == 0
27 #define DEPRECATED(x) __attribute__((deprecated(x)))
28#else
29 #define DEPRECATED(x)
30#endif
31#endif
32
33
34namespace Rivet {
35
36
38 static constexpr double DBL_NAN = std::numeric_limits<double>::quiet_NaN();
39
40
46 template<typename T>
47 inline T& maybe(const T& x, std::function<bool(const T&)> fn, const T& fallback) {
48 return fn(x) ? x : fallback;
49 }
50
51
54
56 struct bad_lexical_cast : public std::runtime_error {
57 bad_lexical_cast(const std::string& what) : std::runtime_error(what) {}
58 };
59
61 template<typename T, typename U>
62 T lexical_cast(const U& in) {
63 try {
64 std::stringstream ss;
65 ss << in;
66 T out;
67 ss >> out;
68 return out;
69 } catch (const std::exception& e) {
70 throw bad_lexical_cast(e.what());
71 }
72 }
73
77 template <typename T>
78 inline string to_str(const T& x) {
79 return lexical_cast<string>(x);
80 }
81
83 inline string& ireplace_first(string& str, const string& patt, const string& repl) {
84 if (!contains(str, patt)) return str; //< contains from RivetSTL
85 str.replace(str.find(patt), patt.size(), repl);
86 return str;
87 }
88
92 template <typename T>
93 inline string toString(T&& x) { return to_str(std::forward<T>(x)); }
94
96 template <typename T>
97 inline string toStr(T&& x) { return to_str(std::forward<T>(x)); }
98
99
101 inline string replace_first(string str, const string& patt, const string& repl) {
102 return ireplace_first(str, patt, repl);
103 }
104
110 inline string& ireplace_all(string& str, const string& patt, const string& repl) {
111 if (!contains(str, patt)) return str; //< contains from RivetSTL
112 while (true) {
113 string::size_type it = str.find(patt);
114 if (it == string::npos) break;
115 str.replace(it, patt.size(), repl);
116 }
117 return str;
118 }
119
125 inline string replace_all(string str, const string& patt, const string& repl) {
126 return ireplace_all(str, patt, repl);
127 }
128
129
131 inline int nocase_cmp(const string& s1, const string& s2) {
132 string::const_iterator it1 = s1.begin();
133 string::const_iterator it2 = s2.begin();
134 while ( (it1 != s1.end()) && (it2 != s2.end()) ) {
135 if(::toupper(*it1) != ::toupper(*it2)) { // < Letters differ?
136 // Return -1 to indicate smaller than, 1 otherwise
137 return (::toupper(*it1) < ::toupper(*it2)) ? -1 : 1;
138 }
139 // Proceed to the next character in each string
140 ++it1;
141 ++it2;
142 }
143 size_t size1 = s1.size(), size2 = s2.size(); // Cache lengths
144 // Return -1,0 or 1 according to strings' lengths
145 if (size1 == size2) return 0;
146 return (size1 < size2) ? -1 : 1;
147 }
148
149
151 inline bool nocase_equals(const string& s1, const string& s2) {
152 return nocase_cmp(s1, s2) == 0;
153 }
154
155
157 inline string toLower(const string& s) {
158 string out = s;
159 std::transform(out.begin(), out.end(), out.begin(), (int(*)(int)) std::tolower);
160 return out;
161 }
162
163
165 inline string toUpper(const string& s) {
166 string out = s;
167 std::transform(out.begin(), out.end(), out.begin(), (int(*)(int)) std::toupper);
168 return out;
169 }
170
171
173 inline bool startsWith(const string& s, const string& start) {
174 if (s.length() < start.length()) return false;
175 return s.substr(0, start.length()) == start;
176 }
177
178
180 inline bool endsWith(const string& s, const string& end) {
181 if (s.length() < end.length()) return false;
182 return s.substr(s.length() - end.length()) == end;
183 }
184
185
186 // Terminating version of strjoin, for empty fargs list
187 inline string strcat() { return ""; }
189 template<typename T, typename... Ts>
190 inline string strcat(T value, Ts... fargs) {
191 const string strthis = lexical_cast<string>(value);
192 const string strnext = strcat(fargs...);
193 return strnext.empty() ? strthis : strthis + strnext;
194 }
195
196
198 template <typename T>
199 inline string join(const vector<T>& v, const string& sep=" ") {
200 string rtn;
201 for (size_t i = 0; i < v.size(); ++i) {
202 if (i != 0) rtn += sep;
203 rtn += to_str(v[i]);
204 }
205 return rtn;
206 }
207
209 template <>
210 inline string join(const vector<string>& v, const string& sep) {
211 string rtn;
212 for (size_t i = 0; i < v.size(); ++i) {
213 if (i != 0) rtn += sep;
214 rtn += v[i];
215 }
216 return rtn;
217 }
218
220 template <typename T>
221 inline string join(const set<T>& s, const string& sep=" ") {
222 string rtn;
223 for (const T& x : s) {
224 if (rtn.size() > 0) rtn += sep;
225 rtn += to_str(x);
226 }
227 return rtn;
228 }
229
231 template <>
232 inline string join(const set<string>& s, const string& sep) {
233 string rtn;
234 for (const string & x : s) {
235 if (rtn.size() > 0) rtn += sep;
236 rtn += x;
237 }
238 return rtn;
239 }
240
242 inline vector<string> split(const string& s, const string& sep) {
243 vector<string> dirs;
244 string tmp = s;
245 while (true) {
246 const size_t delim_pos = tmp.find(sep);
247 if (delim_pos == string::npos) break;
248 const string dir = tmp.substr(0, delim_pos);
249 if (dir.length()) dirs.push_back(dir); // Don't insert "empties"
250 tmp.replace(0, delim_pos+1, "");
251 }
252 if (tmp.length()) dirs.push_back(tmp); // Don't forget the trailing component!
253 return dirs;
254 }
255
257 inline string lpad(const string& s, size_t width, const string& padchar=" ") {
258 if (s.size() >= width) return s;
259 return string(width - s.size(), padchar[0]) + s;
260 }
261
263 inline string rpad(const string& s, size_t width, const string& padchar=" ") {
264 if (s.size() >= width) return s;
265 return s + string(width - s.size(), padchar[0]);
266 }
267
269
270
271
274
278 inline vector<string> pathsplit(const string& path) {
279 return split(path, ":");
280 }
281
286 inline string pathjoin(const vector<string>& paths) {
287 return join(paths, ":");
288 }
289
291 inline string operator / (const string& a, const string& b) {
292 // Ensure that a doesn't end with a slash, and b doesn't start with one, to avoid "//"
293 const string anorm = (a.find("/") != string::npos) ? a.substr(0, a.find_last_not_of("/")+1) : a;
294 const string bnorm = (b.find("/") != string::npos) ? b.substr(b.find_first_not_of("/")) : b;
295 return anorm + "/" + bnorm;
296 }
297
299 inline string basename(const string& p) {
300 if (!contains(p, "/")) return p;
301 return p.substr(p.rfind("/")+1);
302 }
303
305 inline string dirname(const string& p) {
306 if (!contains(p, "/")) return "";
307 return p.substr(0, p.rfind("/"));
308 }
309
311 inline string file_stem(const string& f) {
312 if (!contains(f, ".")) return f;
313 return f.substr(0, f.rfind("."));
314 }
315
317 inline string file_extn(const string& f) {
318 if (!contains(f, ".")) return "";
319 return f.substr(f.rfind(".")+1);
320 }
321
323
324
325
328
330 template <typename CONTAINER,
331 typename = std::enable_if_t< is_citerable_v<std::decay_t<CONTAINER>> >>
332 inline unsigned int count(const CONTAINER& c) {
333 // return std::count_if(std::begin(c), std::end(c), [](const typename CONTAINER::value_type& x){return bool(x);});
334 unsigned int rtn = 0;
335 for (const auto& x : c) if (bool(x)) rtn += 1;
336 return rtn;
337 }
338
339 // /// Return number of elements in the container @a c for which @c f(x) is true.
340 // template <typename CONTAINER>
341 // inline unsigned int count(const CONTAINER& c, const std::function<bool(typename CONTAINER::value_type)>& f) {
342 // return std::count_if(std::begin(c), std::end(c), f);
343 // }
344
346 template <typename CONTAINER, typename FN,
347 //typename FN = bool(const typename std::decay_t<CONTAINER>::value_type&, const std::decay_t<T>&),
348 typename = std::enable_if_t< is_citerable_v<std::decay_t<CONTAINER>> >>
349 inline unsigned int count(const CONTAINER& c, const FN& f) {
350 return std::count_if(std::begin(c), std::end(c), f);
351 }
352
353
354
356 template <typename CONTAINER,
357 typename = std::enable_if_t< is_citerable_v<std::decay_t<CONTAINER>> >>
358 inline bool any(const CONTAINER& c) {
359 // return std::any_of(std::begin(c), std::end(c), [](const auto& x){return bool(x);});
360 for (const auto& x : c) if (bool(x)) return true;
361 return false;
362 }
363
364 // /// Return true if f(x) is true for any x in container c, otherwise false.
365 // template <typename CONTAINER>
366 // inline bool any(const CONTAINER& c, const std::function<bool(typename CONTAINER::value_type)>& f) {
367 // return std::any_of(std::begin(c), std::end(c), f);
368 // }
369
371 template <typename CONTAINER, typename FN,
372 //typename FN = double(const typename std::decay_t<CONTAINER>::value_type&, const std::decay_t<T>&),
373 typename = std::enable_if_t< is_citerable_v<std::decay_t<CONTAINER>> >>
374 inline bool any(const CONTAINER& c, const FN& f) {
375 return std::any_of(std::begin(c), std::end(c), f);
376 }
377
378
379
381 template <typename CONTAINER,
382 typename = std::enable_if_t< is_citerable_v<std::decay_t<CONTAINER>> >>
383 inline bool all(const CONTAINER& c) {
384 // return std::all_of(std::begin(c), std::end(c), [](const auto& x){return bool(x);});
385 for (const auto& x : c) if (!bool(x)) return false;
386 return true;
387 }
388
389 // /// Return true if @a f(x) is true for all @c x in container @a c, otherwise false.
390 // template <typename CONTAINER>
391 // inline bool all(const CONTAINER& c, const std::function<bool(typename CONTAINER::value_type)>& f) {
392 // return std::all_of(std::begin(c), std::end(c), f);
393 // }
394
396 template <typename CONTAINER, typename FN,
397 //typename FN = double(const typename std::decay_t<CONTAINER>::value_type&, const std::decay_t<T>&),
398 typename = std::enable_if_t< is_citerable_v<std::decay_t<CONTAINER>> >>
399 inline bool all(const CONTAINER& c, const FN& f) {
400 return std::all_of(std::begin(c), std::end(c), f);
401 }
402
403
405 template <typename CONTAINER,
406 typename = std::enable_if_t< is_citerable_v<std::decay_t<CONTAINER>> >>
407 inline bool none(const CONTAINER& c) {
408 // return std::none_of(std::begin(c), std::end(c), [](){});
409 for (const auto& x : c) if (bool(x)) return false;
410 return true;
411 }
412
413 // /// Return true if @a f(x) is false for all @c x in container @a c, otherwise false.
414 // template <typename C>
415 // inline bool none(const C& c, const std::function<bool(typename C::value_type)>& f) {
416 // return std::none_of(std::begin(c), std::end(c), f);
417 // }
418
420 template <typename CONTAINER, typename FN,
421 //typename FN = double(const typename std::decay_t<CONTAINER>::value_type&, const std::decay_t<T>&),
422 typename = std::enable_if_t< is_citerable_v<std::decay_t<CONTAINER>> >>
423 inline bool none(const CONTAINER& c, const FN& f) {
424 return std::none_of(std::begin(c), std::end(c), f);
425 }
426
427
428 // /// A single-container-arg version of std::transform, aka @c map
429 // template <typename CONTAINER1, typename CONTAINER2>
430 // inline const CONTAINER2& transform(const CONTAINER1& in, CONTAINER2& out,
431 // const std::function<typename CONTAINER2::value_type(typename CONTAINER1::value_type)>& f) {
432 // out.clear(); out.resize(in.size());
433 // std::transform(in.begin(), in.end(), out.begin(), f);
434 // return out;
435 // }
436
438 template <typename CONTAINER1, typename CONTAINER2,
439 typename FN = typename std::decay_t<CONTAINER2>::value_type(
440 const typename std::decay_t<CONTAINER1>::value_type::ParticleBase&),
441 typename = std::enable_if_t< is_citerable_v<std::decay_t<CONTAINER1>> &&
442 is_citerable_v<std::decay_t<CONTAINER2>> >>
443 inline const CONTAINER2& transform(const CONTAINER1& in, CONTAINER2& out, FN&& f) {
444 out.clear(); out.resize(in.size());
445 std::transform(in.begin(), in.end(), out.begin(), std::forward<FN>(f));
446 return out;
447 }
448
452 template <typename CONTAINER1, typename RTN,
453 typename = std::enable_if_t< is_citerable_v<std::decay_t<CONTAINER1>> >>
454 inline std::vector<RTN> transform(const CONTAINER1& in,
455 const std::function<RTN(typename CONTAINER1::value_type::ParticleBase)>& f) {
456 std::vector<RTN> out;
457 transform(in, out, f);
458 return out;
459 }
460
461 // /// A single-container-arg version of std::accumulate, aka @c reduce
462 // template <typename CONTAINER1, typename T>
463 // inline T accumulate(const CONTAINER1& in, const T& init, const std::function<T(typename CONTAINER1::value_type)>& f) {
464 // const T rtn = std::accumulate(in.begin(), in.end(), init, f);
465 // return rtn;
466 // }
467
469 template <typename CONTAINER1, typename T, typename FN,
470 typename = std::enable_if_t< is_citerable_v<std::decay_t<CONTAINER1>> >>
471 inline T accumulate(const CONTAINER1& in, const T& init, const FN& f) {
472 const T rtn = std::accumulate(in.begin(), in.end(), init, f);
473 return rtn;
474 }
475
476
480 template <typename CONTAINER,
481 typename = std::enable_if_t< is_citerable_v<std::decay_t<CONTAINER>> >>
482 inline typename CONTAINER::value_type sum(const CONTAINER& c) {
483 typename CONTAINER::value_type rtn; //< default construct return type
484 for (const auto& x : c) rtn += x;
485 return rtn;
486 }
487
491 template <typename CONTAINER, typename T,
492 typename = std::enable_if_t< is_citerable_v<std::decay_t<CONTAINER>> >>
493 inline T sum(const CONTAINER& c, const T& start) {
494 T rtn = start;
495 for (const auto& x : c) rtn += x;
496 return rtn;
497 }
498
500 template <typename CONTAINER, typename T,
501 typename FN = T(const typename std::decay_t<CONTAINER>::value_type::ParticleBase&),
502 typename = std::enable_if_t< is_citerable_v<std::decay_t<CONTAINER>> >>
503 inline T sum(const CONTAINER& c, FN&& fn, const T& start=T()) {
504 auto f = std::function(std::forward<FN>(fn));
505 T rtn = start;
506 for (const auto& x : c) rtn += fn(x);
507 return rtn;
508 }
509
510
514 template <typename CONTAINER, typename T,
515 typename = std::enable_if_t< is_citerable_v<std::decay_t<CONTAINER>> >>
516 inline T& isum(const CONTAINER& c, T& out) {
517 for (const auto& x : c) out += x;
518 return out;
519 }
520
524 template <typename CONTAINER, typename FN, typename T,
525 //typename FN = double(const typename std::decay_t<CONTAINER>::value_type&, const std::decay_t<T>&),
526 typename = std::enable_if_t< is_citerable_v<std::decay_t<CONTAINER>> >>
527 inline T& isum(const CONTAINER& c, const FN& f, T& out) {
528 for (const auto& x : c) out += f(x);
529 return out;
530 }
531
532
533
537 template <typename CONTAINER, typename FN,
538 typename = std::enable_if_t< is_citerable_v<std::decay_t<CONTAINER>> >>
539 inline CONTAINER& idiscard(CONTAINER& c, const FN& f) {
540 const auto newend = std::remove_if(std::begin(c), std::end(c), f);
541 c.erase(newend, c.end());
542 return c;
543 }
544
546 template <typename CONTAINER,
547 typename = std::enable_if_t< is_citerable_v<std::decay_t<CONTAINER>> >>
548 inline CONTAINER& idiscard(CONTAINER& c, const typename CONTAINER::value_type& y) {
549 return idiscard(c, [&](typename CONTAINER::value_type& x){ return x == y; });
550 }
551
553 template <typename CONTAINER,
554 typename = std::enable_if_t< is_citerable_v<std::decay_t<CONTAINER>> >>
555 inline CONTAINER& idiscard_if_any(CONTAINER& c, const CONTAINER& ys) {
556 return idiscard(c, [&](typename CONTAINER::value_type& x){ return contains(ys, x); });
557 }
558
559
563 template <typename CONTAINER, typename FN,
564 typename = std::enable_if_t< is_citerable_v<std::decay_t<CONTAINER>> >>
565 inline CONTAINER discard(const CONTAINER& c, const FN& f) {
566 CONTAINER rtn = c;
567 return idiscard(rtn, f);
568 }
569
571 template <typename CONTAINER,
572 typename = std::enable_if_t< is_citerable_v<std::decay_t<CONTAINER>> >>
573 inline CONTAINER discard(const CONTAINER& c, const typename CONTAINER::value_type& y) {
574 return discard(c, [&](typename CONTAINER::value_type& x){ return x == y; });
575 }
576
578 template <typename CONTAINER,
579 typename = std::enable_if_t< is_citerable_v<std::decay_t<CONTAINER>> >>
580 inline CONTAINER discard_if_any(const CONTAINER& c, const CONTAINER& ys) {
581 return discard(c, [&](typename CONTAINER::value_type& x){ return contains(ys, x); });
582 }
583
584
590 template <typename CONTAINER, typename FN,
591 //typename FN = bool(const typename std::decay_t<CONTAINER>::value_type&, const std::decay_t<T>&),
592 typename = std::enable_if_t< is_citerable_v<std::decay_t<CONTAINER>> >>
593 inline CONTAINER& discard(const CONTAINER& c, const FN& f, CONTAINER& out) {
594 out = discard(c, f);
595 return out;
596 }
597
599 template <typename CONTAINER,
600 typename = std::enable_if_t< is_citerable_v<std::decay_t<CONTAINER>> >>
601 inline CONTAINER& discard(const CONTAINER& c, const typename CONTAINER::value_type& y, CONTAINER& out) {
602 return discard(c, [&](typename CONTAINER::value_type& x){ return x == y; }, out);
603 }
604
606 template <typename CONTAINER,
607 typename = std::enable_if_t< is_citerable_v<std::decay_t<CONTAINER>> >>
608 inline CONTAINER& discard_if_any(const CONTAINER& c, const CONTAINER& ys, CONTAINER& out) {
609 return discard(c, [&](typename CONTAINER::value_type& x){ return contains(ys, x); }, out);
610 }
611
612
613
617 template <typename CONTAINER, typename FN,
618 typename = std::enable_if_t< is_citerable_v<std::decay_t<CONTAINER>> >>
619 inline CONTAINER& iselect(CONTAINER& c, const FN& f) {
620 auto invf = [&](const typename CONTAINER::value_type& x){ return !f(x); };
621 return idiscard(c, invf); //< yes, intentional!
622 }
623
624 // No single equality-comparison version for select, since that would be silly!
625
627 template <typename CONTAINER,
628 typename = std::enable_if_t< is_citerable_v<std::decay_t<CONTAINER>> >>
629 inline CONTAINER& iselect_if_any(CONTAINER& c, const CONTAINER& ys) {
630 return iselect(c, [&](typename CONTAINER::value_type& x){ return contains(ys, x); });
631 }
632
633
637 template <typename CONTAINER, typename FN,
638 typename = std::enable_if_t< is_citerable_v<std::decay_t<CONTAINER>> >>
639 inline CONTAINER select(const CONTAINER& c, const FN& f) {
640 CONTAINER rtn = c;
641 return iselect(rtn, f);
642 }
643
644 // No single equality-comparison version for select, since that would be silly!
645
647 template <typename CONTAINER,
648 typename = std::enable_if_t< is_citerable_v<std::decay_t<CONTAINER>> >>
649 inline CONTAINER select_if_any(const CONTAINER& c, const CONTAINER& ys) {
650 return select(c, [&](typename CONTAINER::value_type& x){ return contains(ys, x); });
651 }
652
653
659 template <typename CONTAINER, typename FN,
660 typename = std::enable_if_t< is_citerable_v<std::decay_t<CONTAINER>> >>
661 inline CONTAINER& select(const CONTAINER& c, const FN& f, CONTAINER& out) {
662 out = select(c, f);
663 return out;
664 }
665
666 // No single equality-comparison version for select, since that would be silly!
667
669 template <typename CONTAINER,
670 typename = std::enable_if_t< is_citerable_v<std::decay_t<CONTAINER>> >>
671 inline CONTAINER& select_if_any(const CONTAINER& c, const CONTAINER& ys, CONTAINER& out) {
672 return select(c, [&](typename CONTAINER::value_type& x){ return contains(ys, x); }, out);
673 }
674
675
676
681 template <typename CONTAINER,
682 typename = std::enable_if_t< is_citerable_v<std::decay_t<CONTAINER>> >>
683 inline CONTAINER slice(const CONTAINER& c, int i, int j) {
684 CONTAINER rtn;
685 const size_t off1 = (i >= 0) ? i : c.size() + i;
686 const size_t off2 = (j >= 0) ? j : c.size() + j;
687 if (off1 > c.size() || off2 > c.size()) throw RangeError("Attempting to slice beyond requested offsets");
688 if (off2 < off1) throw RangeError("Requested offsets in invalid order");
689 rtn.resize(off2 - off1);
690 std::copy(c.begin()+off1, c.begin()+off2, rtn.begin());
691 return rtn;
692 }
693
697 template <typename CONTAINER,
698 typename = std::enable_if_t< is_citerable_v<std::decay_t<CONTAINER>> >>
699 inline CONTAINER slice(const CONTAINER& c, int i) {
700 return slice(c, i, c.size());
701 }
702
706 template <typename CONTAINER,
707 typename = std::enable_if_t< is_citerable_v<std::decay_t<CONTAINER>> >>
708 inline CONTAINER head(const CONTAINER& c, int n) {
709 // if (n > c.size()) throw RangeError("Requested head longer than container");
710 if (n < 0) n = std::max(0, (int)c.size()+n);
711 n = std::min(n, (int)c.size());
712 return slice(c, 0, n);
713 }
714
718 template <typename CONTAINER,
719 typename = std::enable_if_t< is_citerable_v<std::decay_t<CONTAINER>> >>
720 inline CONTAINER tail(const CONTAINER& c, int n) {
721 // if (n > c.size()) throw RangeError("Requested tail longer than container");
722 if (n < 0) n = std::max(0, (int)c.size()+n);
723 n = std::min(n, (int)c.size());
724 return slice(c, c.size()-n);
725 }
726
727
728 using std::min;
729 using std::max;
730
732 inline double min(const vector<double>& in, double errval=DBL_NAN) {
733 const auto e = std::min_element(in.begin(), in.end());
734 return e != in.end() ? *e : errval;
735 }
736
738 inline double max(const vector<double>& in, double errval=DBL_NAN) {
739 const auto e = std::max_element(in.begin(), in.end());
740 return e != in.end() ? *e : errval;
741 }
742
744 inline pair<double,double> minmax(const vector<double>& in, double errval=DBL_NAN) {
745 const auto e = std::minmax_element(in.begin(), in.end());
746 const double rtnmin = e.first != in.end() ? *e.first : errval;
747 const double rtnmax = e.second != in.end() ? *e.first : errval;
748 return std::make_pair(rtnmin, rtnmax);
749 }
750
751
753 inline int min(const vector<int>& in, int errval=-1) {
754 const auto e = std::min_element(in.begin(), in.end());
755 return e != in.end() ? *e : errval;
756 }
757
759 inline int max(const vector<int>& in, int errval=-1) {
760 const auto e = std::max_element(in.begin(), in.end());
761 return e != in.end() ? *e : errval;
762 }
763
765 inline pair<int,int> minmax(const vector<int>& in, int errval=-1) {
766 const auto e = std::minmax_element(in.begin(), in.end());
767 const double rtnmin = e.first != in.end() ? *e.first : errval;
768 const double rtnmax = e.second != in.end() ? *e.first : errval;
769 return std::make_pair(rtnmin, rtnmax);
770 }
771
773
774
777
783 template <typename CONTAINER,
784 typename FN = double(const typename std::decay_t<CONTAINER>::value_type::ParticleBase&),
785 typename = isCIterable<CONTAINER>>
786 inline int closestMatchIndex(const CONTAINER& c, FN&& fn,
787 double target, double minval=-DBL_MAX, double maxval=DBL_MAX) {
788 auto f = std::function(std::forward<FN>(fn));
789 int ibest = -1;
790 double best = DBL_NAN;
791 for (size_t i = 0; i < c.size(); ++i) {
792 const double val = f(c[i]);
793 if (isnan(val)) continue;
794 if (val < minval || val > maxval) continue;
795 if (isnan(best) || fabs(val-target) < fabs(best-target)) {
796 best = val;
797 ibest = i;
798 }
799 }
800 return ibest;
801 }
802
811 template <typename CONTAINER1, typename CONTAINER2,
812 typename FN = double(const typename std::decay_t<CONTAINER1>::value_type::ParticleBase&,
813 const typename std::decay_t<CONTAINER2>::value_type::ParticleBase&),
814 typename = isCIterable<CONTAINER1, CONTAINER2>>
815 inline pair<int,int> closestMatchIndices(const CONTAINER1& c1, const CONTAINER2& c2, FN&& fn,
816 double target, double minval=-DBL_MAX, double maxval=DBL_MAX) {
817 auto f = std::function(std::forward<FN>(fn));
818 pair<int,int> ijbest{-1,-1};
819 double best = DBL_NAN;
820 for (size_t i = 0; i < c1.size(); ++i) {
821 for (size_t j = 0; j < c2.size(); ++j) {
822 const double val = f(c1[i], c2[j]);
823 if (isnan(val)) continue;
824 if (val < minval || val > maxval) continue;
825 if (isnan(best) || fabs(val-target) < fabs(best-target)) {
826 best = val;
827 ijbest = {i,j};
828 }
829 }
830 }
831 return ijbest;
832 }
833
842 template <typename CONTAINER, typename T,
843 typename FN = double(const typename std::decay_t<CONTAINER>::value_type::ParticleBase&, const std::decay_t<T>&),
844 typename = isCIterable<CONTAINER>>
845 inline int closestMatchIndex(const CONTAINER& c, const T& x, FN&& fn,
846 double target, double minval=-DBL_MAX, double maxval=DBL_MAX) {
847 pair<int,int> ijbest = closestMatchIndices(c, vector<T>{x}, std::forward<FN>(fn), target, minval, maxval);
848 return ijbest.first;
849 }
850
859 template <typename CONTAINER, typename T, typename FN, typename = isCIterable<CONTAINER>>
860 inline int closestMatchIndex(const T& x, const CONTAINER& c, FN&& fn,
861 double target, double minval=-DBL_MAX, double maxval=DBL_MAX) {
862 return closestMatchIndex(c, x, std::forward<FN>(fn), target, minval, maxval);
863 }
864
866
867
873 template <typename T>
874 T getEnvParam(const std::string name, const T& fallback) {
875 char* env = getenv(name.c_str());
876 return env ? lexical_cast<T>(env) : fallback;
877 }
878
879
880
884 template<class T>
885 vector<T> slice(const vector<T>& v, int startidx, int endidx) {
886
887 if (startidx < 0 || endidx <= startidx || endidx >= v.size())
888 throw RangeError("Requested start or end indices incompatible with given vector");
889
890 auto start = v.begin() + startidx;
891 auto end = v.begin() + endidx;
892
893 vector<T> output(endidx - startidx);
894
895 copy(start, end, output.begin());
896
897 return output;
898 }
899
900
901}
902
903#endif
int closestMatchIndex(const CONTAINER &c, FN &&fn, double target, double minval=-DBL_MAX, double maxval=DBL_MAX)
Return the index from a vector which best matches fn(c[i]) to the target value.
Definition Utils.hh:786
pair< int, int > closestMatchIndices(const CONTAINER1 &c1, const CONTAINER2 &c2, FN &&fn, double target, double minval=-DBL_MAX, double maxval=DBL_MAX)
Return the indices from two vectors which best match fn(c1[i], c2[j]) to the target value.
Definition Utils.hh:815
CONTAINER head(const CONTAINER &c, int n)
Head slice of the n first container elements.
Definition Utils.hh:708
bool any(const CONTAINER &c)
Return true if x is true for any x in container c, otherwise false.
Definition Utils.hh:358
CONTAINER discard_if_any(const CONTAINER &c, const CONTAINER &ys)
Version with several element-equality comparisons in place of a function.
Definition Utils.hh:580
CONTAINER slice(const CONTAINER &c, int i, int j)
Slice of the container elements cf. Python's [i:j] syntax.
Definition Utils.hh:683
T accumulate(const CONTAINER1 &in, const T &init, const FN &f)
A single-container-arg version of std::accumulate, aka reduce.
Definition Utils.hh:471
CONTAINER & idiscard_if_any(CONTAINER &c, const CONTAINER &ys)
Version with several element-equality comparisons in place of a function.
Definition Utils.hh:555
pair< double, double > minmax(const vector< double > &in, double errval=DBL_NAN)
Find the minimum and maximum values in the vector.
Definition Utils.hh:744
bool none(const CONTAINER &c)
Return true if x is false for all x in container c, otherwise false.
Definition Utils.hh:407
CONTAINER tail(const CONTAINER &c, int n)
Tail slice of the n last container elements.
Definition Utils.hh:720
bool all(const CONTAINER &c)
Return true if x is true for all x in container c, otherwise false.
Definition Utils.hh:383
unsigned int count(const CONTAINER &c)
Return number of true elements in the container c .
Definition Utils.hh:332
T & isum(const CONTAINER &c, T &out)
Definition Utils.hh:516
CONTAINER & iselect_if_any(CONTAINER &c, const CONTAINER &ys)
Version with several element-equality comparisons in place of a function.
Definition Utils.hh:629
CONTAINER select_if_any(const CONTAINER &c, const CONTAINER &ys)
Version with several element-equality comparisons in place of a function.
Definition Utils.hh:649
Jets & idiscard(Jets &jets, const Cut &c)
Filter a jet collection in-place to the subset that fails the supplied Cut.
Jets select(const Jets &jets, const Cut &c)
Filter a jet collection in-place to the subset that passes the supplied Cut.
Definition JetUtils.hh:157
Jets & iselect(Jets &jets, const Cut &c)
Filter a jet collection in-place to the subset that passes the supplied Cut.
Jets discard(const Jets &jets, const Cut &c)
Filter a jet collection in-place to the subset that fails the supplied Cut.
Definition JetUtils.hh:176
double p(const ParticleBase &p)
Unbound function access to p.
Definition ParticleBaseUtils.hh:653
string dirname(const string &p)
Get the dirname (i.e. path to the penultimate directory) from a path p.
Definition Utils.hh:305
string file_extn(const string &f)
Get the file extension from a filename f.
Definition Utils.hh:317
string pathjoin(const vector< string > &paths)
Join several filesystem paths together with the standard ':' delimiter.
Definition Utils.hh:286
vector< string > pathsplit(const string &path)
Split a path string with colon delimiters.
Definition Utils.hh:278
string basename(const string &p)
Get the basename (i.e. terminal file name) from a path p.
Definition Utils.hh:299
string file_stem(const string &f)
Get the stem (i.e. part without a file extension) from a filename f.
Definition Utils.hh:311
bool endsWith(const string &s, const string &end)
Check whether a string end is found at the end of s.
Definition Utils.hh:180
bool nocase_equals(const string &s1, const string &s2)
Case-insensitive string equality function.
Definition Utils.hh:151
string toStr(T &&x)
Perfect-forwarding alias for to_str() with a more Rivet-user-facing name.
Definition Utils.hh:97
bool startsWith(const string &s, const string &start)
Check whether a string start is found at the start of s.
Definition Utils.hh:173
string & ireplace_all(string &str, const string &patt, const string &repl)
Replace all instances of patt with repl in-place.
Definition Utils.hh:110
string toUpper(const string &s)
Convert a string to upper-case.
Definition Utils.hh:165
string rpad(const string &s, size_t width, const string &padchar=" ")
Right-pad the given string s to width width.
Definition Utils.hh:263
string to_str(const T &x)
Convert any object to a string.
Definition Utils.hh:78
string lpad(const string &s, size_t width, const string &padchar=" ")
Left-pad the given string s to width width.
Definition Utils.hh:257
string toLower(const string &s)
Convert a string to lower-case.
Definition Utils.hh:157
string replace_all(string str, const string &patt, const string &repl)
Replace all instances of patt with repl.
Definition Utils.hh:125
T lexical_cast(const U &in)
Convert between any types via stringstream.
Definition Utils.hh:62
vector< string > split(const string &s, const string &sep)
Split a string on a specified separator string.
Definition Utils.hh:242
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:199
string & ireplace_first(string &str, const string &patt, const string &repl)
Replace the first instance of patt with repl in-place.
Definition Utils.hh:83
string replace_first(string str, const string &patt, const string &repl)
Replace the first instance of patt with repl.
Definition Utils.hh:101
int nocase_cmp(const string &s1, const string &s2)
Case-insensitive string comparison function.
Definition Utils.hh:131
T getEnvParam(const std::string name, const T &fallback)
Get a parameter from a named environment variable, with automatic type conversion.
Definition Utils.hh:874
Definition MC_CENT_PPB_Projections.hh:10
std::enable_if_t< std::is_arithmetic_v< N1 > &&std::is_arithmetic_v< N2 >, signed_if_mixed_t< N1, N2 > > max(N1 a, N2 b)
Get the maximum of two numbers.
Definition MathUtils.hh:115
T sum(const DressedLeptons &c, FN &&fn, const T &start=T())
Generic sum function, adding fn(x) for all x in container c, starting with start.
Definition DressedLepton.hh:60
static constexpr double DBL_NAN
Convenient const for getting the double NaN value.
Definition Utils.hh:38
std::enable_if_t< std::is_arithmetic_v< N1 > &&std::is_arithmetic_v< N2 >, signed_if_mixed_t< N1, N2 > > min(N1 a, N2 b)
Get the minimum of two numbers.
Definition MathUtils.hh:104
bool contains(const std::string &s, const std::string &sub)
Does s contain sub as a substring?
Definition RivetSTL.hh:201
T & maybe(const T &x, std::function< bool(const T &)> fn, const T &fallback)
Wrapper for avoiding repetition/recalculation when computing and maybe using a value.
Definition Utils.hh:47
std::string toString(const AnalysisInfo &ai)
String representation.
Error for e.g. use of invalid bin ranges.
Definition Exceptions.hh:22
Exception class for throwing from lexical_cast when a parse goes wrong.
Definition Utils.hh:56