CMS 3D CMS Logo

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