CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups 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>
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::pair<pointer, std::ptrdiff_t> p = std::get_temporary_buffer<value_type>(len);
152  pointer buf = p.first;
153  pointer buf_end = std::next(p.first, p.second);
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.first;
175  std::copy(buf, buf_end, first);
176  std::return_temporary_buffer(p.first);
177  }
178 
179  // See above
180  template <typename RandomAccessIterator, typename Compare = std::less<> >
181  void merge_sort(RandomAccessIterator first, RandomAccessIterator last, Compare cmp) {
182  const std::ptrdiff_t len = std::distance(first, last);
183  if (len > 1) {
184  RandomAccessIterator middle = std::next(first, len / 2);
185  merge_sort(first, middle, cmp);
186  merge_sort(middle, last, cmp);
187  merge_sort_merge(first, middle, last, cmp);
188  }
189  }
190 
191  // An extended version of the merge sort algorithm to incorporate a 3-way
192  // comparator. It resorts back to 2-way comparator when one of the three
193  // lists to be merged is empty.
194  template <typename RandomAccessIterator, typename Compare, typename Compare3>
195  void merge_sort_merge3(RandomAccessIterator first,
196  RandomAccessIterator one_third,
197  RandomAccessIterator two_third,
198  RandomAccessIterator last,
199  Compare cmp,
200  Compare3 cmp3) {
201  const std::ptrdiff_t len = std::distance(first, last);
203  typedef typename std::iterator_traits<RandomAccessIterator>::pointer pointer;
204  std::pair<pointer, std::ptrdiff_t> p = std::get_temporary_buffer<value_type>(len);
205  pointer buf = p.first;
206  pointer buf_end = std::next(p.first, p.second);
207 
208  RandomAccessIterator first1 = first;
209  RandomAccessIterator last1 = one_third;
210  RandomAccessIterator first2 = one_third;
211  RandomAccessIterator last2 = two_third;
212  RandomAccessIterator first3 = two_third;
213  RandomAccessIterator last3 = last;
214 
215  while (first1 != last1 && first2 != last2 && first3 != last3) {
216  int rr = cmp3(*first1, *first2, *first3);
217  if (rr == 0) {
218  *buf++ = *first1++;
219  } else if (rr == 1) {
220  *buf++ = *first2++;
221  } else if (rr == 2) {
222  *buf++ = *first3++;
223  }
224  }
225 
226  if (first3 == last3) {
227  // do nothing
228  } else if (first2 == last2) {
229  first2 = first3;
230  last2 = last3;
231  } else if (first1 == last1) {
232  first1 = first2;
233  last1 = last2;
234  first2 = first3;
235  last2 = last3;
236  }
237 
238  while (first1 != last1 && first2 != last2) {
239  if (cmp(*first2, *first1)) {
240  *buf++ = *first2++;
241  } else {
242  *buf++ = *first1++;
243  }
244  }
245  while (first1 != last1) {
246  *buf++ = *first1++;
247  }
248  while (first2 != last2) {
249  *buf++ = *first2++;
250  }
251 
252  buf = p.first;
253  std::copy(buf, buf_end, first);
254  std::return_temporary_buffer(p.first);
255  }
256 
257  // See above
258  template <typename RandomAccessIterator, typename Compare, typename Compare3>
259  void merge_sort3(RandomAccessIterator first, RandomAccessIterator last, Compare cmp, Compare3 cmp3) {
260  const std::ptrdiff_t len = std::distance(first, last);
261  if (len > 1) {
262  RandomAccessIterator one_third = std::next(first, (len + 2) / 3);
263  RandomAccessIterator two_third = std::next(first, (len + 2) / 3 * 2);
264  merge_sort3(first, one_third, cmp, cmp3);
265  merge_sort3(one_third, two_third, cmp, cmp3);
266  merge_sort3(two_third, last, cmp, cmp3);
267  merge_sort_merge3(first, one_third, two_third, last, cmp, cmp3);
268  }
269  }
270 
271  // See above. 'Hint' is provided to force the very first division. This is needed to match FW.
272  template <typename RandomAccessIterator, typename Compare, typename Compare3>
273  void merge_sort3_with_hint(
274  RandomAccessIterator first, RandomAccessIterator last, Compare cmp, Compare3 cmp3, std::ptrdiff_t d) {
275  const std::ptrdiff_t len = std::distance(first, last);
276  if (len > 1) {
277  RandomAccessIterator one_third = std::next(first, d);
278  RandomAccessIterator two_third = std::next(first, d * 2);
279  merge_sort3(first, one_third, cmp, cmp3);
280  merge_sort3(one_third, two_third, cmp, cmp3);
281  merge_sort3(two_third, last, cmp, cmp3);
282  merge_sort_merge3(first, one_third, two_third, last, cmp, cmp3);
283  }
284  }
285 
286 } // namespace
static char to_hex(unsigned int i)
Definition: types.cc:26
const edm::EventSetup & c
TGeoIterator Iterator
static std::string const input
Definition: EdmProvDump.cc:47
tuple result
Definition: mps_fire.py:311
tuple d
Definition: ztail.py:151
string INT
Definition: conddblib.py:35
def move
Definition: eostools.py:511
tuple ins
Definition: cuy.py:313
#define N
Definition: blowfish.cc:9
double b
Definition: hdecay.h:118
string end
Definition: dataset.py:937
tuple last
Definition: dqmdumpme.py:56
#define str(s)
long double T
edm::AssociationVector< reco::JetRefBaseProd, Values > Container