rivet is hosted by Hepforge, IPPP Durham
Rivet 4.0.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/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
43
45 struct bad_lexical_cast : public std::runtime_error {
46 bad_lexical_cast(const std::string& what) : std::runtime_error(what) {}
47 };
48
50 template<typename T, typename U>
51 T lexical_cast(const U& in) {
52 try {
53 std::stringstream ss;
54 ss << in;
55 T out;
56 ss >> out;
57 return out;
58 } catch (const std::exception& e) {
59 throw bad_lexical_cast(e.what());
60 }
61 }
62
66 template <typename T>
67 inline string to_str(const T& x) {
68 return lexical_cast<string>(x);
69 }
70
74 template <typename T>
75 inline string toString(const T& x) {
76 return lexical_cast<string>(x);
77 }
78
80 inline string& replace_first(string& str, const string& patt, const string& repl) {
81 if (!contains(str, patt)) return str; //< contains from RivetSTL
82 str.replace(str.find(patt), patt.size(), repl);
83 return str;
84 }
85
91 inline string& replace_all(string& str, const string& patt, const string& repl) {
92 if (!contains(str, patt)) return str; //< contains from RivetSTL
93 while (true) {
94 string::size_type it = str.find(patt);
95 if (it == string::npos) break;
96 str.replace(it, patt.size(), repl);
97 }
98 return str;
99 }
100
101
103 inline int nocase_cmp(const string& s1, const string& s2) {
104 string::const_iterator it1 = s1.begin();
105 string::const_iterator it2 = s2.begin();
106 while ( (it1 != s1.end()) && (it2 != s2.end()) ) {
107 if(::toupper(*it1) != ::toupper(*it2)) { // < Letters differ?
108 // Return -1 to indicate smaller than, 1 otherwise
109 return (::toupper(*it1) < ::toupper(*it2)) ? -1 : 1;
110 }
111 // Proceed to the next character in each string
112 ++it1;
113 ++it2;
114 }
115 size_t size1 = s1.size(), size2 = s2.size(); // Cache lengths
116 // Return -1,0 or 1 according to strings' lengths
117 if (size1 == size2) return 0;
118 return (size1 < size2) ? -1 : 1;
119 }
120
121
123 inline bool nocase_equals(const string& s1, const string& s2) {
124 return nocase_cmp(s1, s2) == 0;
125 }
126
127
129 inline string toLower(const string& s) {
130 string out = s;
131 std::transform(out.begin(), out.end(), out.begin(), (int(*)(int)) std::tolower);
132 return out;
133 }
134
135
137 inline string toUpper(const string& s) {
138 string out = s;
139 std::transform(out.begin(), out.end(), out.begin(), (int(*)(int)) std::toupper);
140 return out;
141 }
142
143
145 inline bool startsWith(const string& s, const string& start) {
146 if (s.length() < start.length()) return false;
147 return s.substr(0, start.length()) == start;
148 }
149
150
152 inline bool endsWith(const string& s, const string& end) {
153 if (s.length() < end.length()) return false;
154 return s.substr(s.length() - end.length()) == end;
155 }
156
157
158 // Terminating version of strjoin, for empty fargs list
159 inline string strcat() { return ""; }
161 template<typename T, typename... Ts>
162 inline string strcat(T value, Ts... fargs) {
163 const string strthis = lexical_cast<string>(value);
164 const string strnext = strcat(fargs...);
165 return strnext.empty() ? strthis : strthis + strnext;
166 }
167
168
170 template <typename T>
171 inline string join(const vector<T>& v, const string& sep=" ") {
172 string rtn;
173 for (size_t i = 0; i < v.size(); ++i) {
174 if (i != 0) rtn += sep;
175 rtn += to_str(v[i]);
176 }
177 return rtn;
178 }
179
181 template <>
182 inline string join(const vector<string>& v, const string& sep) {
183 string rtn;
184 for (size_t i = 0; i < v.size(); ++i) {
185 if (i != 0) rtn += sep;
186 rtn += v[i];
187 }
188 return rtn;
189 }
190
192 template <typename T>
193 inline string join(const set<T>& s, const string& sep=" ") {
194 string rtn;
195 for (const T& x : s) {
196 if (rtn.size() > 0) rtn += sep;
197 rtn += to_str(x);
198 }
199 return rtn;
200 }
201
203 template <>
204 inline string join(const set<string>& s, const string& sep) {
205 string rtn;
206 for (const string & x : s) {
207 if (rtn.size() > 0) rtn += sep;
208 rtn += x;
209 }
210 return rtn;
211 }
212
214 inline vector<string> split(const string& s, const string& sep) {
215 vector<string> dirs;
216 string tmp = s;
217 while (true) {
218 const size_t delim_pos = tmp.find(sep);
219 if (delim_pos == string::npos) break;
220 const string dir = tmp.substr(0, delim_pos);
221 if (dir.length()) dirs.push_back(dir); // Don't insert "empties"
222 tmp.replace(0, delim_pos+1, "");
223 }
224 if (tmp.length()) dirs.push_back(tmp); // Don't forget the trailing component!
225 return dirs;
226 }
227
229 inline string lpad(const string& s, size_t width, const string& padchar=" ") {
230 if (s.size() >= width) return s;
231 return string(width - s.size(), padchar[0]) + s;
232 }
233
235 inline string rpad(const string& s, size_t width, const string& padchar=" ") {
236 if (s.size() >= width) return s;
237 return s + string(width - s.size(), padchar[0]);
238 }
239
241
242
243
246
250 inline vector<string> pathsplit(const string& path) {
251 return split(path, ":");
252 }
253
258 inline string pathjoin(const vector<string>& paths) {
259 return join(paths, ":");
260 }
261
263 inline string operator / (const string& a, const string& b) {
264 // Ensure that a doesn't end with a slash, and b doesn't start with one, to avoid "//"
265 const string anorm = (a.find("/") != string::npos) ? a.substr(0, a.find_last_not_of("/")+1) : a;
266 const string bnorm = (b.find("/") != string::npos) ? b.substr(b.find_first_not_of("/")) : b;
267 return anorm + "/" + bnorm;
268 }
269
271 inline string basename(const string& p) {
272 if (!contains(p, "/")) return p;
273 return p.substr(p.rfind("/")+1);
274 }
275
277 inline string dirname(const string& p) {
278 if (!contains(p, "/")) return "";
279 return p.substr(0, p.rfind("/"));
280 }
281
283 inline string file_stem(const string& f) {
284 if (!contains(f, ".")) return f;
285 return f.substr(0, f.rfind("."));
286 }
287
289 inline string file_extn(const string& f) {
290 if (!contains(f, ".")) return "";
291 return f.substr(f.rfind(".")+1);
292 }
293
295
296
297
300
302 template <typename CONTAINER,
303 typename = std::enable_if_t< is_citerable_v<std::decay_t<CONTAINER>> >>
304 inline unsigned int count(const CONTAINER& c) {
305 // return std::count_if(std::begin(c), std::end(c), [](const typename CONTAINER::value_type& x){return bool(x);});
306 unsigned int rtn = 0;
307 for (const auto& x : c) if (bool(x)) rtn += 1;
308 return rtn;
309 }
310
311 // /// Return number of elements in the container @a c for which @c f(x) is true.
312 // template <typename CONTAINER>
313 // inline unsigned int count(const CONTAINER& c, const std::function<bool(typename CONTAINER::value_type)>& f) {
314 // return std::count_if(std::begin(c), std::end(c), f);
315 // }
316
318 template <typename CONTAINER, typename FN,
319 //typename FN = bool(const typename std::decay_t<CONTAINER>::value_type&, const std::decay_t<T>&),
320 typename = std::enable_if_t< is_citerable_v<std::decay_t<CONTAINER>> >>
321 inline unsigned int count(const CONTAINER& c, const FN& f) {
322 return std::count_if(std::begin(c), std::end(c), f);
323 }
324
325
326
328 template <typename CONTAINER,
329 typename = std::enable_if_t< is_citerable_v<std::decay_t<CONTAINER>> >>
330 inline bool any(const CONTAINER& c) {
331 // return std::any_of(std::begin(c), std::end(c), [](const auto& x){return bool(x);});
332 for (const auto& x : c) if (bool(x)) return true;
333 return false;
334 }
335
336 // /// Return true if f(x) is true for any x in container c, otherwise false.
337 // template <typename CONTAINER>
338 // inline bool any(const CONTAINER& c, const std::function<bool(typename CONTAINER::value_type)>& f) {
339 // return std::any_of(std::begin(c), std::end(c), f);
340 // }
341
343 template <typename CONTAINER, typename FN,
344 //typename FN = double(const typename std::decay_t<CONTAINER>::value_type&, const std::decay_t<T>&),
345 typename = std::enable_if_t< is_citerable_v<std::decay_t<CONTAINER>> >>
346 inline bool any(const CONTAINER& c, const FN& f) {
347 return std::any_of(std::begin(c), std::end(c), f);
348 }
349
350
351
353 template <typename CONTAINER,
354 typename = std::enable_if_t< is_citerable_v<std::decay_t<CONTAINER>> >>
355 inline bool all(const CONTAINER& c) {
356 // return std::all_of(std::begin(c), std::end(c), [](const auto& x){return bool(x);});
357 for (const auto& x : c) if (!bool(x)) return false;
358 return true;
359 }
360
361 // /// Return true if @a f(x) is true for all @c x in container @a c, otherwise false.
362 // template <typename CONTAINER>
363 // inline bool all(const CONTAINER& c, const std::function<bool(typename CONTAINER::value_type)>& f) {
364 // return std::all_of(std::begin(c), std::end(c), f);
365 // }
366
368 template <typename CONTAINER, typename FN,
369 //typename FN = double(const typename std::decay_t<CONTAINER>::value_type&, const std::decay_t<T>&),
370 typename = std::enable_if_t< is_citerable_v<std::decay_t<CONTAINER>> >>
371 inline bool all(const CONTAINER& c, const FN& f) {
372 return std::all_of(std::begin(c), std::end(c), f);
373 }
374
375
377 template <typename CONTAINER,
378 typename = std::enable_if_t< is_citerable_v<std::decay_t<CONTAINER>> >>
379 inline bool none(const CONTAINER& c) {
380 // return std::none_of(std::begin(c), std::end(c), [](){});
381 for (const auto& x : c) if (bool(x)) return false;
382 return true;
383 }
384
385 // /// Return true if @a f(x) is false for all @c x in container @a c, otherwise false.
386 // template <typename C>
387 // inline bool none(const C& c, const std::function<bool(typename C::value_type)>& f) {
388 // return std::none_of(std::begin(c), std::end(c), f);
389 // }
390
392 template <typename CONTAINER, typename FN,
393 //typename FN = double(const typename std::decay_t<CONTAINER>::value_type&, const std::decay_t<T>&),
394 typename = std::enable_if_t< is_citerable_v<std::decay_t<CONTAINER>> >>
395 inline bool none(const CONTAINER& c, const FN& f) {
396 return std::none_of(std::begin(c), std::end(c), f);
397 }
398
399
400 // /// A single-container-arg version of std::transform, aka @c map
401 // template <typename CONTAINER1, typename CONTAINER2>
402 // inline const CONTAINER2& transform(const CONTAINER1& in, CONTAINER2& out,
403 // const std::function<typename CONTAINER2::value_type(typename CONTAINER1::value_type)>& f) {
404 // out.clear(); out.resize(in.size());
405 // std::transform(in.begin(), in.end(), out.begin(), f);
406 // return out;
407 // }
408
412 template <typename CONTAINER1, typename CONTAINER2,
413 typename FN = typename std::decay_t<CONTAINER2>::value_type(
414 const typename std::decay_t<CONTAINER1>::value_type::ParticleBase&),
415 typename = std::enable_if_t< is_citerable_v<std::decay_t<CONTAINER1>> &&
416 is_citerable_v<std::decay_t<CONTAINER2>> >>
417 inline const CONTAINER2& transform(const CONTAINER1& in, CONTAINER2& out, FN&& f) {
418 out.clear(); out.resize(in.size());
419 std::transform(in.begin(), in.end(), out.begin(), std::forward<FN>(f));
420 return out;
421 }
422
425 template <typename CONTAINER1, typename RTN,
426 typename = std::enable_if_t< is_citerable_v<std::decay_t<CONTAINER1>> >>
427 inline std::vector<RTN> transform(const CONTAINER1& in,
428 const std::function<RTN(typename CONTAINER1::value_type::ParticleBase)>& f) {
429 std::vector<RTN> out;
430 transform(in, out, f);
431 return out;
432 }
433
434 // /// A single-container-arg version of std::accumulate, aka @c reduce
435 // template <typename CONTAINER1, typename T>
436 // inline T accumulate(const CONTAINER1& in, const T& init, const std::function<T(typename CONTAINER1::value_type)>& f) {
437 // const T rtn = std::accumulate(in.begin(), in.end(), init, f);
438 // return rtn;
439 // }
440
442 template <typename CONTAINER1, typename T, typename FN,
443 typename = std::enable_if_t< is_citerable_v<std::decay_t<CONTAINER1>> >>
444 inline T accumulate(const CONTAINER1& in, const T& init, const FN& f) {
445 const T rtn = std::accumulate(in.begin(), in.end(), init, f);
446 return rtn;
447 }
448
449
453 template <typename CONTAINER,
454 typename = std::enable_if_t< is_citerable_v<std::decay_t<CONTAINER>> >>
455 inline typename CONTAINER::value_type sum(const CONTAINER& c) {
456 typename CONTAINER::value_type rtn; //< default construct return type
457 for (const auto& x : c) rtn += x;
458 return rtn;
459 }
460
464 template <typename CONTAINER, typename T,
465 typename = std::enable_if_t< is_citerable_v<std::decay_t<CONTAINER>> >>
466 inline T sum(const CONTAINER& c, const T& start) {
467 T rtn = start;
468 for (const auto& x : c) rtn += x;
469 return rtn;
470 }
471
473 template <typename CONTAINER, typename T,
474 typename FN = T(const typename std::decay_t<CONTAINER>::value_type&),
475 typename = std::enable_if_t< is_citerable_v<std::decay_t<CONTAINER>> >>
476 inline T sum(CONTAINER&& c, FN&& fn, const T& start=T()) {
477 auto f = std::function(std::forward<FN>(fn));
478 T rtn = start;
479 for (const auto& x : c) rtn += fn(x);
480 return rtn;
481 }
482
483
487 template <typename CONTAINER, typename T,
488 typename = std::enable_if_t< is_citerable_v<std::decay_t<CONTAINER>> >>
489 inline T& isum(const CONTAINER& c, T& out) {
490 for (const auto& x : c) out += x;
491 return out;
492 }
493
497 template <typename CONTAINER, typename FN, typename T,
498 //typename FN = double(const typename std::decay_t<CONTAINER>::value_type&, const std::decay_t<T>&),
499 typename = std::enable_if_t< is_citerable_v<std::decay_t<CONTAINER>> >>
500 inline T& isum(const CONTAINER& c, const FN& f, T& out) {
501 for (const auto& x : c) out += f(x);
502 return out;
503 }
504
505
506
510 template <typename CONTAINER, typename FN,
511 typename = std::enable_if_t< is_citerable_v<std::decay_t<CONTAINER>> >>
512 inline CONTAINER& idiscard(CONTAINER& c, const FN& f) {
513 const auto newend = std::remove_if(std::begin(c), std::end(c), f);
514 c.erase(newend, c.end());
515 return c;
516 }
517
519 template <typename CONTAINER,
520 typename = std::enable_if_t< is_citerable_v<std::decay_t<CONTAINER>> >>
521 inline CONTAINER& idiscard(CONTAINER& c, const typename CONTAINER::value_type& y) {
522 return idiscard(c, [&](typename CONTAINER::value_type& x){ return x == y; });
523 }
524
526 template <typename CONTAINER,
527 typename = std::enable_if_t< is_citerable_v<std::decay_t<CONTAINER>> >>
528 inline CONTAINER& idiscard_if_any(CONTAINER& c, const CONTAINER& ys) {
529 return idiscard(c, [&](typename CONTAINER::value_type& x){ return contains(ys, x); });
530 }
531
532
536 template <typename CONTAINER, typename FN,
537 typename = std::enable_if_t< is_citerable_v<std::decay_t<CONTAINER>> >>
538 inline CONTAINER discard(const CONTAINER& c, const FN& f) {
539 CONTAINER rtn = c;
540 return idiscard(rtn, f);
541 }
542
544 template <typename CONTAINER,
545 typename = std::enable_if_t< is_citerable_v<std::decay_t<CONTAINER>> >>
546 inline CONTAINER discard(const CONTAINER& c, const typename CONTAINER::value_type& y) {
547 return discard(c, [&](typename CONTAINER::value_type& x){ return x == y; });
548 }
549
551 template <typename CONTAINER,
552 typename = std::enable_if_t< is_citerable_v<std::decay_t<CONTAINER>> >>
553 inline CONTAINER discard_if_any(const CONTAINER& c, const CONTAINER& ys) {
554 return discard(c, [&](typename CONTAINER::value_type& x){ return contains(ys, x); });
555 }
556
557
563 template <typename CONTAINER, typename FN,
564 //typename FN = bool(const typename std::decay_t<CONTAINER>::value_type&, const std::decay_t<T>&),
565 typename = std::enable_if_t< is_citerable_v<std::decay_t<CONTAINER>> >>
566 inline CONTAINER& discard(const CONTAINER& c, const FN& f, CONTAINER& out) {
567 out = discard(c, f);
568 return out;
569 }
570
572 template <typename CONTAINER,
573 typename = std::enable_if_t< is_citerable_v<std::decay_t<CONTAINER>> >>
574 inline CONTAINER& discard(const CONTAINER& c, const typename CONTAINER::value_type& y, CONTAINER& out) {
575 return discard(c, [&](typename CONTAINER::value_type& x){ return x == y; }, out);
576 }
577
579 template <typename CONTAINER,
580 typename = std::enable_if_t< is_citerable_v<std::decay_t<CONTAINER>> >>
581 inline CONTAINER& discard_if_any(const CONTAINER& c, const CONTAINER& ys, CONTAINER& out) {
582 return discard(c, [&](typename CONTAINER::value_type& x){ return contains(ys, x); }, out);
583 }
584
585
586
590 template <typename CONTAINER, typename FN,
591 typename = std::enable_if_t< is_citerable_v<std::decay_t<CONTAINER>> >>
592 inline CONTAINER& iselect(CONTAINER& c, const FN& f) {
593 auto invf = [&](const typename CONTAINER::value_type& x){ return !f(x); };
594 return idiscard(c, invf); //< yes, intentional!
595 }
596
597 // No single equality-comparison version for select, since that would be silly!
598
600 template <typename CONTAINER,
601 typename = std::enable_if_t< is_citerable_v<std::decay_t<CONTAINER>> >>
602 inline CONTAINER& iselect_if_any(CONTAINER& c, const CONTAINER& ys) {
603 return iselect(c, [&](typename CONTAINER::value_type& x){ return contains(ys, x); });
604 }
605
606
610 template <typename CONTAINER, typename FN,
611 typename = std::enable_if_t< is_citerable_v<std::decay_t<CONTAINER>> >>
612 inline CONTAINER select(const CONTAINER& c, const FN& f) {
613 CONTAINER rtn = c;
614 return iselect(rtn, f);
615 }
616
617 // No single equality-comparison version for select, since that would be silly!
618
620 template <typename CONTAINER,
621 typename = std::enable_if_t< is_citerable_v<std::decay_t<CONTAINER>> >>
622 inline CONTAINER select_if_any(const CONTAINER& c, const CONTAINER& ys) {
623 return select(c, [&](typename CONTAINER::value_type& x){ return contains(ys, x); });
624 }
625
626
632 template <typename CONTAINER, typename FN,
633 typename = std::enable_if_t< is_citerable_v<std::decay_t<CONTAINER>> >>
634 inline CONTAINER& select(const CONTAINER& c, const FN& f, CONTAINER& out) {
635 out = select(c, f);
636 return out;
637 }
638
639 // No single equality-comparison version for select, since that would be silly!
640
642 template <typename CONTAINER,
643 typename = std::enable_if_t< is_citerable_v<std::decay_t<CONTAINER>> >>
644 inline CONTAINER& select_if_any(const CONTAINER& c, const CONTAINER& ys, CONTAINER& out) {
645 return select(c, [&](typename CONTAINER::value_type& x){ return contains(ys, x); }, out);
646 }
647
648
649
654 template <typename CONTAINER,
655 typename = std::enable_if_t< is_citerable_v<std::decay_t<CONTAINER>> >>
656 inline CONTAINER slice(const CONTAINER& c, int i, int j) {
657 CONTAINER rtn;
658 const size_t off1 = (i >= 0) ? i : c.size() + i;
659 const size_t off2 = (j >= 0) ? j : c.size() + j;
660 if (off1 > c.size() || off2 > c.size()) throw RangeError("Attempting to slice beyond requested offsets");
661 if (off2 < off1) throw RangeError("Requested offsets in invalid order");
662 rtn.resize(off2 - off1);
663 std::copy(c.begin()+off1, c.begin()+off2, rtn.begin());
664 return rtn;
665 }
666
670 template <typename CONTAINER,
671 typename = std::enable_if_t< is_citerable_v<std::decay_t<CONTAINER>> >>
672 inline CONTAINER slice(const CONTAINER& c, int i) {
673 return slice(c, i, c.size());
674 }
675
679 template <typename CONTAINER,
680 typename = std::enable_if_t< is_citerable_v<std::decay_t<CONTAINER>> >>
681 inline CONTAINER head(const CONTAINER& c, int n) {
682 // if (n > c.size()) throw RangeError("Requested head longer than container");
683 if (n < 0) n = std::max(0, (int)c.size()+n);
684 n = std::min(n, (int)c.size());
685 return slice(c, 0, n);
686 }
687
691 template <typename CONTAINER,
692 typename = std::enable_if_t< is_citerable_v<std::decay_t<CONTAINER>> >>
693 inline CONTAINER tail(const CONTAINER& c, int n) {
694 // if (n > c.size()) throw RangeError("Requested tail longer than container");
695 if (n < 0) n = std::max(0, (int)c.size()+n);
696 n = std::min(n, (int)c.size());
697 return slice(c, c.size()-n);
698 }
699
700
701 using std::min;
702 using std::max;
703
705 inline double min(const vector<double>& in, double errval=DBL_NAN) {
706 const auto e = std::min_element(in.begin(), in.end());
707 return e != in.end() ? *e : errval;
708 }
709
711 inline double max(const vector<double>& in, double errval=DBL_NAN) {
712 const auto e = std::max_element(in.begin(), in.end());
713 return e != in.end() ? *e : errval;
714 }
715
717 inline pair<double,double> minmax(const vector<double>& in, double errval=DBL_NAN) {
718 const auto e = std::minmax_element(in.begin(), in.end());
719 const double rtnmin = e.first != in.end() ? *e.first : errval;
720 const double rtnmax = e.second != in.end() ? *e.first : errval;
721 return std::make_pair(rtnmin, rtnmax);
722 }
723
724
726 inline int min(const vector<int>& in, int errval=-1) {
727 const auto e = std::min_element(in.begin(), in.end());
728 return e != in.end() ? *e : errval;
729 }
730
732 inline int max(const vector<int>& in, int errval=-1) {
733 const auto e = std::max_element(in.begin(), in.end());
734 return e != in.end() ? *e : errval;
735 }
736
738 inline pair<int,int> minmax(const vector<int>& in, int errval=-1) {
739 const auto e = std::minmax_element(in.begin(), in.end());
740 const double rtnmin = e.first != in.end() ? *e.first : errval;
741 const double rtnmax = e.second != in.end() ? *e.first : errval;
742 return std::make_pair(rtnmin, rtnmax);
743 }
744
746
747
750
756 template <typename CONTAINER,
757 typename FN = double(const typename std::decay_t<CONTAINER>::value_type&),
758 typename = isCIterable<CONTAINER>>
759 inline int closestMatchIndex(CONTAINER&& c, FN&& fn,
760 double target, double minval=-DBL_MAX, double maxval=DBL_MAX) {
761 auto f = std::function(std::forward<FN>(fn));
762 int ibest = -1;
763 double best = DBL_NAN;
764 for (size_t i = 0; i < c.size(); ++i) {
765 const double val = f(c[i]);
766 if (isnan(val)) continue;
767 if (val < minval || val > maxval) continue;
768 if (isnan(best) || fabs(val-target) < fabs(best-target)) {
769 best = val;
770 ibest = i;
771 }
772 }
773 return ibest;
774 }
775
784 template <typename CONTAINER1, typename CONTAINER2,
785 typename FN = double(const typename std::decay_t<CONTAINER1>::value_type&,
786 const typename std::decay_t<CONTAINER2>::value_type&),
787 typename = isCIterable<CONTAINER1, CONTAINER2>>
788 inline pair<int,int> closestMatchIndices(CONTAINER1&& c1, CONTAINER2&& c2, FN&& fn,
789 double target, double minval=-DBL_MAX, double maxval=DBL_MAX) {
790 auto f = std::function(std::forward<FN>(fn));
791 pair<int,int> ijbest{-1,-1};
792 double best = DBL_NAN;
793 for (size_t i = 0; i < c1.size(); ++i) {
794 for (size_t j = 0; j < c2.size(); ++j) {
795 const double val = f(c1[i], c2[j]);
796 if (isnan(val)) continue;
797 if (val < minval || val > maxval) continue;
798 if (isnan(best) || fabs(val-target) < fabs(best-target)) {
799 best = val;
800 ijbest = {i,j};
801 }
802 }
803 }
804 return ijbest;
805 }
806
815 template <typename CONTAINER, typename T,
816 typename FN = double(const typename std::decay_t<CONTAINER>::value_type&, const std::decay_t<T>&),
817 typename = isCIterable<CONTAINER>>
818 inline int closestMatchIndex(CONTAINER&& c, const T& x, FN&& fn,
819 double target, double minval=-DBL_MAX, double maxval=DBL_MAX) {
820 pair<int,int> ijbest = closestMatchIndices(std::forward<CONTAINER>(c), vector<T>{x}, std::forward<FN>(fn), target, minval, maxval);
821 return ijbest.first;
822 }
823
832 template <typename CONTAINER, typename T, typename FN, typename = isCIterable<CONTAINER>>
833 inline int closestMatchIndex(T&& x, CONTAINER&& c, FN&& fn,
834 double target, double minval=-DBL_MAX, double maxval=DBL_MAX) {
835 return closestMatchIndex(std::forward<CONTAINER>(c), std::forward<T>(x), std::forward<FN>(fn), target, minval, maxval);
836 }
837
839
840
846 template <typename T>
847 T getEnvParam(const std::string name, const T& fallback) {
848 char* env = getenv(name.c_str());
849 return env ? lexical_cast<T>(env) : fallback;
850 }
851
852
853
857 template<class T>
858 vector<T> slice(const vector<T>& v, int startidx, int endidx) {
859
860 if (startidx < 0 || endidx <= startidx || endidx >= v.size())
861 throw RangeError("Requested start or end indices incompatible with given vector");
862
863 auto start = v.begin() + startidx;
864 auto end = v.begin() + endidx;
865
866 vector<T> output(endidx - startidx);
867
868 copy(start, end, output.begin());
869
870 return output;
871 }
872
873
874}
875
876#endif
pair< int, int > closestMatchIndices(CONTAINER1 &&c1, 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:788
int closestMatchIndex(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:759
CONTAINER head(const CONTAINER &c, int n)
Head slice of the n first container elements.
Definition Utils.hh:681
bool any(const CONTAINER &c)
Return true if x is true for any x in container c, otherwise false.
Definition Utils.hh:330
CONTAINER discard_if_any(const CONTAINER &c, const CONTAINER &ys)
Version with several element-equality comparisons in place of a function.
Definition Utils.hh:553
CONTAINER slice(const CONTAINER &c, int i, int j)
Slice of the container elements cf. Python's [i:j] syntax.
Definition Utils.hh:656
T accumulate(const CONTAINER1 &in, const T &init, const FN &f)
A single-container-arg version of std::accumulate, aka reduce.
Definition Utils.hh:444
CONTAINER & idiscard_if_any(CONTAINER &c, const CONTAINER &ys)
Version with several element-equality comparisons in place of a function.
Definition Utils.hh:528
pair< double, double > minmax(const vector< double > &in, double errval=DBL_NAN)
Find the minimum and maximum values in the vector.
Definition Utils.hh:717
bool none(const CONTAINER &c)
Return true if x is false for all x in container c, otherwise false.
Definition Utils.hh:379
CONTAINER tail(const CONTAINER &c, int n)
Tail slice of the n last container elements.
Definition Utils.hh:693
bool all(const CONTAINER &c)
Return true if x is true for all x in container c, otherwise false.
Definition Utils.hh:355
unsigned int count(const CONTAINER &c)
Return number of true elements in the container c .
Definition Utils.hh:304
T & isum(const CONTAINER &c, T &out)
Definition Utils.hh:489
CONTAINER & iselect_if_any(CONTAINER &c, const CONTAINER &ys)
Version with several element-equality comparisons in place of a function.
Definition Utils.hh:602
CONTAINER select_if_any(const CONTAINER &c, const CONTAINER &ys)
Version with several element-equality comparisons in place of a function.
Definition Utils.hh:622
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:152
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:171
string dirname(const string &p)
Get the dirname (i.e. path to the penultimate directory) from a path p.
Definition Utils.hh:277
string file_extn(const string &f)
Get the file extension from a filename f.
Definition Utils.hh:289
string pathjoin(const vector< string > &paths)
Join several filesystem paths together with the standard ':' delimiter.
Definition Utils.hh:258
vector< string > pathsplit(const string &path)
Split a path string with colon delimiters.
Definition Utils.hh:250
string basename(const string &p)
Get the basename (i.e. terminal file name) from a path p.
Definition Utils.hh:271
string file_stem(const string &f)
Get the stem (i.e. part without a file extension) from a filename f.
Definition Utils.hh:283
bool endsWith(const string &s, const string &end)
Check whether a string end is found at the end of s.
Definition Utils.hh:152
bool nocase_equals(const string &s1, const string &s2)
Case-insensitive string equality function.
Definition Utils.hh:123
bool startsWith(const string &s, const string &start)
Check whether a string start is found at the start of s.
Definition Utils.hh:145
string toUpper(const string &s)
Convert a string to upper-case.
Definition Utils.hh:137
string rpad(const string &s, size_t width, const string &padchar=" ")
Right-pad the given string s to width width.
Definition Utils.hh:235
string to_str(const T &x)
Convert any object to a string.
Definition Utils.hh:67
string lpad(const string &s, size_t width, const string &padchar=" ")
Left-pad the given string s to width width.
Definition Utils.hh:229
string toLower(const string &s)
Convert a string to lower-case.
Definition Utils.hh:129
T lexical_cast(const U &in)
Convert between any types via stringstream.
Definition Utils.hh:51
vector< string > split(const string &s, const string &sep)
Split a string on a specified separator string.
Definition Utils.hh:214
string & replace_all(string &str, const string &patt, const string &repl)
Replace all instances of patt with repl.
Definition Utils.hh:91
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:171
string & replace_first(string &str, const string &patt, const string &repl)
Replace the first instance of patt with repl.
Definition Utils.hh:80
int nocase_cmp(const string &s1, const string &s2)
Case-insensitive string comparison function.
Definition Utils.hh:103
T getEnvParam(const std::string name, const T &fallback)
Get a parameter from a named environment variable, with automatic type conversion.
Definition Utils.hh:847
Definition MC_CENT_PPB_Projections.hh:10
std::enable_if< std::is_arithmetic< N1 >::value &&std::is_arithmetic< N2 >::value, typenamestd::common_type< N1, N2 >::type >::type max(N1 a, N2 b)
Get the maximum of two numbers.
Definition MathUtils.hh:111
std::enable_if< std::is_arithmetic< N1 >::value &&std::is_arithmetic< N2 >::value, typenamestd::common_type< N1, N2 >::type >::type min(N1 a, N2 b)
Get the minimum of two numbers.
Definition MathUtils.hh:102
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
bool contains(const std::string &s, const std::string &sub)
Does s contain sub as a substring?
Definition RivetSTL.hh:97
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:45