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