CMS 3D CMS Logo

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