CMS 3D CMS Logo

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
helper.h
Go to the documentation of this file.
1 #include <bitset>
2 #include <string>
3 #include <sstream>
4 #include <vector>
5 #include <map>
6 #include <memory>
8 
9 // Need a safe assertion function
10 #ifdef NDEBUG
11 #define assert_no_abort(expr) ((void)0)
12 #else
13 #define assert_no_abort(expr) ((void)((expr) || (__assert_no_abort(#expr, __FILE__, __LINE__, __PRETTY_FUNCTION__), 0)))
14 template <typename T = void>
15 void __assert_no_abort(const char* assertion, const char* file, unsigned int line, const char* function) {
16  //std::cout << file << ":" << line << ": " << function << ": Assertion `" << assertion << "' failed. (no abort)" << std::endl;
17  edm::LogWarning("L1T") << file << ":" << line << ": " << function << ": Assertion `" << assertion
18  << "' failed. (no abort)";
19 }
20 #endif
21 
22 namespace {
23 
24  // Return an integer as a hex string
25  template <typename INT>
27  std::stringstream s;
28  s << "0x" << std::hex << i;
29  return s.str();
30  }
31 
32  // Return an integer as a binary string
33  template <typename INT>
34  std::string to_binary(INT i, int n) {
35  std::stringstream s;
36  if (sizeof(i) <= 4) {
37  std::bitset<32> b(i);
38  s << "0b" << b.to_string().substr(32 - n, 32);
39  } else if (sizeof(i) <= 8) {
40  std::bitset<64> b(i);
41  s << "0b" << b.to_string().substr(64 - n, 64);
42  }
43  return s.str();
44  }
45 
46  // Return the size of a 1D plain array
47  template <typename T, size_t N>
48  constexpr size_t array_size(T (&)[N]) {
49  return N;
50  }
51 
52  // Return the elements of a 1D plain array as a string (elements are separated by ' ')
53  template <typename T, size_t N>
54  std::string array_as_string(const T (&arr)[N]) {
55  std::stringstream s;
56  const char* sep = "";
57  for (size_t i = 0; i < N; ++i) {
58  s << sep << arr[i];
59  sep = " ";
60  }
61  return s.str();
62  }
63 
64  // This function allows one to loop over a container in reversed order using C++11 for(auto ...) loop
65  // e.g.
66  // for (auto x: reversed(v)) {
67  // // do something
68  // }
69  // See http://stackoverflow.com/a/21510185
70  namespace details {
71  template <class T>
72  struct _reversed {
73  T& t;
74  _reversed(T& _t) : t(_t) {}
75  decltype(t.rbegin()) begin() { return t.rbegin(); }
76  decltype(t.rend()) end() { return t.rend(); }
77  };
78  } // namespace details
79  template <class T>
80  details::_reversed<T> reversed(T& t) {
81  return details::_reversed<T>(t);
82  }
83 
84  // Split a string by delimiters (default: ' ') into a vector of string
85  // See http://stackoverflow.com/a/53878
86  template <class STR = std::string>
87  std::vector<STR> split_string(const std::string& s, char c = ' ', char d = ' ') {
88  std::vector<STR> result;
89  const char* str = s.c_str();
90  do {
91  const char* begin = str;
92  while (*str != c && *str != d && *str)
93  str++;
94  result.emplace_back(begin, str);
95  } while (0 != *str++);
96  return result;
97  }
98 
99  // Flatten a vector<vector<T> > into a vector<T>
100  // The input type T can be different from the output type T
101  template <class T1, class T2>
102  void flatten_container(const T1& input, T2& output) {
103  typename T1::const_iterator it;
104  for (it = input.begin(); it != input.end(); ++it) {
105  output.insert(output.end(), it->begin(), it->end());
106  }
107  }
108 
109  // Check type for map of vector
110  template <typename>
111  struct is_map_of_vectors : public std::false_type {};
112 
113  template <typename T1, typename T2>
114  struct is_map_of_vectors<std::map<T1, std::vector<T2> > > : public std::true_type {};
115 
116  // Merge a map of vectors (map1) into another map of vectors (map2)
117  template <typename Map>
118  void merge_map_into_map(const Map& map1, Map& map2) {
119  // This is customized for maps of containers.
120  typedef typename Map::iterator Iterator;
121  typedef typename Map::mapped_type Container;
122 
123  for (auto& kv1 : map1) {
124  std::pair<Iterator, bool> ins = map2.insert(kv1);
125  if (!ins.second) { // if insertion into map2 was not successful
126  if (is_map_of_vectors<Map>::value) { // special case for map of vectors
127  const Container* container1 = &(kv1.second);
128  Container* container2 = &(ins.first->second);
129  container2->insert(container2->end(), container1->begin(), container1->end());
130  } // else do nothing
131  }
132  }
133  }
134 
135  // A simple nearest-neighbor clustering algorithm
136  // It iterates through a sorted container once, whenever the 'adjacent'
137  // comparison between two elements evaluates to true, the 'cluster'
138  // operator is called to merge them.
139  template <class ForwardIt, class BinaryPredicate, class BinaryOp>
140  ForwardIt adjacent_cluster(ForwardIt first, ForwardIt last, BinaryPredicate adjacent, BinaryOp cluster) {
141  if (first == last)
142  return last;
143 
144  ForwardIt result = first;
145  while (++first != last) {
146  if (!adjacent(*result, *first)) {
147  *++result = std::move(*first);
148  } else {
149  cluster(*result, *first);
150  }
151  }
152  return ++result;
153  }
154 
155  // Textbook merge sort algorithm with the same interface as std::sort()
156  // An internal buffer of the same size as the container is used internally.
157  template <typename RandomAccessIterator, typename Compare = std::less<> >
158  void merge_sort_merge(RandomAccessIterator first,
159  RandomAccessIterator middle,
160  RandomAccessIterator last,
161  Compare cmp) {
162  const std::ptrdiff_t len = std::distance(first, last);
164  typedef typename std::iterator_traits<RandomAccessIterator>::pointer pointer;
165  std::pair<pointer, std::ptrdiff_t> p = std::get_temporary_buffer<value_type>(len);
166  pointer buf = p.first;
167  pointer buf_end = std::next(p.first, p.second);
168 
169  RandomAccessIterator first1 = first;
170  RandomAccessIterator last1 = middle;
171  RandomAccessIterator first2 = middle;
172  RandomAccessIterator last2 = last;
173 
174  while (first1 != last1 && first2 != last2) {
175  if (cmp(*first2, *first1)) {
176  *buf++ = *first2++;
177  } else {
178  *buf++ = *first1++;
179  }
180  }
181  while (first1 != last1) {
182  *buf++ = *first1++;
183  }
184  while (first2 != last2) {
185  *buf++ = *first2++;
186  }
187 
188  buf = p.first;
189  std::copy(buf, buf_end, first);
190  std::return_temporary_buffer(p.first);
191  }
192 
193  // See above
194  template <typename RandomAccessIterator, typename Compare = std::less<> >
195  void merge_sort(RandomAccessIterator first, RandomAccessIterator last, Compare cmp) {
196  const std::ptrdiff_t len = std::distance(first, last);
197  if (len > 1) {
198  RandomAccessIterator middle = std::next(first, len / 2);
199  merge_sort(first, middle, cmp);
200  merge_sort(middle, last, cmp);
201  merge_sort_merge(first, middle, last, cmp);
202  }
203  }
204 
205  // An extended version of the merge sort algorithm to incorporate a 3-way
206  // comparator. It resorts back to 2-way comparator when one of the three
207  // lists to be merged is empty.
208  template <typename RandomAccessIterator, typename Compare, typename Compare3>
209  void merge_sort_merge3(RandomAccessIterator first,
210  RandomAccessIterator one_third,
211  RandomAccessIterator two_third,
212  RandomAccessIterator last,
213  Compare cmp,
214  Compare3 cmp3) {
215  const std::ptrdiff_t len = std::distance(first, last);
217  typedef typename std::iterator_traits<RandomAccessIterator>::pointer pointer;
218  std::pair<pointer, std::ptrdiff_t> p = std::get_temporary_buffer<value_type>(len);
219  pointer buf = p.first;
220  pointer buf_end = std::next(p.first, p.second);
221 
222  RandomAccessIterator first1 = first;
223  RandomAccessIterator last1 = one_third;
224  RandomAccessIterator first2 = one_third;
225  RandomAccessIterator last2 = two_third;
226  RandomAccessIterator first3 = two_third;
227  RandomAccessIterator last3 = last;
228 
229  while (first1 != last1 && first2 != last2 && first3 != last3) {
230  int rr = cmp3(*first1, *first2, *first3);
231  if (rr == 0) {
232  *buf++ = *first1++;
233  } else if (rr == 1) {
234  *buf++ = *first2++;
235  } else if (rr == 2) {
236  *buf++ = *first3++;
237  }
238  }
239 
240  if (first3 == last3) {
241  // do nothing
242  } else if (first2 == last2) {
243  first2 = first3;
244  last2 = last3;
245  } else if (first1 == last1) {
246  first1 = first2;
247  last1 = last2;
248  first2 = first3;
249  last2 = last3;
250  }
251 
252  while (first1 != last1 && first2 != last2) {
253  if (cmp(*first2, *first1)) {
254  *buf++ = *first2++;
255  } else {
256  *buf++ = *first1++;
257  }
258  }
259  while (first1 != last1) {
260  *buf++ = *first1++;
261  }
262  while (first2 != last2) {
263  *buf++ = *first2++;
264  }
265 
266  buf = p.first;
267  std::copy(buf, buf_end, first);
268  std::return_temporary_buffer(p.first);
269  }
270 
271  // See above
272  template <typename RandomAccessIterator, typename Compare, typename Compare3>
273  void merge_sort3(RandomAccessIterator first, RandomAccessIterator last, Compare cmp, Compare3 cmp3) {
274  const std::ptrdiff_t len = std::distance(first, last);
275  if (len > 1) {
276  RandomAccessIterator one_third = std::next(first, (len + 2) / 3);
277  RandomAccessIterator two_third = std::next(first, (len + 2) / 3 * 2);
278  merge_sort3(first, one_third, cmp, cmp3);
279  merge_sort3(one_third, two_third, cmp, cmp3);
280  merge_sort3(two_third, last, cmp, cmp3);
281  merge_sort_merge3(first, one_third, two_third, last, cmp, cmp3);
282  }
283  }
284 
285  // See above. 'Hint' is provided to force the very first division. This is needed to match FW.
286  template <typename RandomAccessIterator, typename Compare, typename Compare3>
287  void merge_sort3_with_hint(
288  RandomAccessIterator first, RandomAccessIterator last, Compare cmp, Compare3 cmp3, std::ptrdiff_t d) {
289  const std::ptrdiff_t len = std::distance(first, last);
290  if (len > 1) {
291  RandomAccessIterator one_third = std::next(first, d);
292  RandomAccessIterator two_third = std::next(first, d * 2);
293  merge_sort3(first, one_third, cmp, cmp3);
294  merge_sort3(one_third, two_third, cmp, cmp3);
295  merge_sort3(two_third, last, cmp, cmp3);
296  merge_sort_merge3(first, one_third, two_third, last, cmp, cmp3);
297  }
298  }
299 
300 } // namespace
static char to_hex(unsigned int i)
Definition: types.cc:27
ins
Definition: cuy.py:314
TGeoIterator Iterator
static std::string const input
Definition: EdmProvDump.cc:48
Definition: helper.h:70
#define end
Definition: vmac.h:39
d
Definition: ztail.py:151
#define N
Definition: blowfish.cc:9
double b
Definition: hdecay.h:118
#define begin
Definition: vmac.h:32
#define str(s)
long double T
edm::AssociationVector< reco::JetRefBaseProd, Values > Container
def move(src, dest)
Definition: eostools.py:511
#define constexpr
void __assert_no_abort(const char *assertion, const char *file, unsigned int line, const char *function)
Definition: helper.h:15