Jpp
JMergeSort.cc
Go to the documentation of this file.
1 
2 #include <iostream>
3 #include <iomanip>
4 #include <functional>
5 #include <limits>
6 #include <vector>
7 #include <algorithm>
8 
9 #include "TRandom3.h"
10 
11 #include "JTools/JMergeSort.hh"
12 
13 #include "Jeep/JTimer.hh"
14 #include "Jeep/JParser.hh"
15 #include "Jeep/JMessage.hh"
16 
17 
18 namespace JTOOLS {
19 
20  /**
21  * Merge multiple sorted ranges.
22  *
23  * \param __begin begin of data
24  * \param N number of delimiters (equals number of ranges plus one)
25  * \param delimiter incremental delimiters
26  */
27  template<class T>
28  void inplace_merge(T __begin, const size_t N, const size_t* delimiter)
29  {
30  switch (N - 1) {
31 
32  case 0:
33  case 1:
34  break;
35 
36  case 2:
37 
38  std::inplace_merge(__begin + delimiter[0],
39  __begin + delimiter[1],
40  __begin + delimiter[2]);
41 
42  break;
43 
44  default:
45 
46  const size_t n = (N - 1) >> 1;
47 
48  inplace_merge(__begin, n + 1, delimiter);
49  inplace_merge(__begin, N - n, delimiter + n);
50 
51  std::inplace_merge(__begin + delimiter[ 0 ],
52  __begin + delimiter[ n ],
53  __begin + delimiter[N-1]);
54 
55  break;
56  };
57  }
58 
59 
60  /**
61  * Auxiliary class to convert value to element.
62  */
63  template<class T>
64  struct JGetElement
65  {
66  /**
67  * Default constructor.
68  */
70  {}
71 
72 
73  /**
74  * Type conversion operator.
75  *
76  * \param x value
77  * \return element
78  */
79  inline T operator()(const double x) const
80  {
81  return (T) x;
82  }
83 
84 
85  /**
86  * Get end marker.
87  *
88  * \return element
89  */
90  static inline T getEndMarker()
91  {
92  return std::numeric_limits<T>::max();
93  }
94  };
95 
96 
97  /**
98  * Test whether range is sorted.
99  *
100  * \param __begin begin of data
101  * \param __end end of data
102  * \return true if sorted; else false
103  */
104  template<class T>
105  inline bool is_sorted(T __begin, T __end)
106  {
107  if (std::distance(__begin, __end) > 1) {
108  for (T q = __begin, p = q++; q != __end; ++p, ++q) {
109  if (*p > *q) {
110  return false;
111  }
112  }
113  }
114 
115  return true;
116  }
117 }
118 
119 
120 /**
121  * \file
122  *
123  * Example program to test performance of JTOOLS::JMergeSort.
124  * \author mdejong
125  */
126 int main(int argc, char **argv)
127 {
128  using namespace std;
129 
130  double rate_Hz;
131  bool do_test;
132  int debug;
133 
134  try {
135 
136  JParser<> zap("Example program to test performance of merge sort.");
137 
138  zap['B'] = make_field(rate_Hz);
139  zap['D'] = make_field(do_test);
140  zap['d'] = make_field(debug) = 0;
141 
142  zap(argc, argv);
143  }
144  catch(const exception &error) {
145  FATAL(error.what() << endl);
146  }
147 
148 
149  using namespace JPP;
150 
151  if (rate_Hz <= 0.0) {
152  FATAL("Rate " << rate_Hz << " < 0 Hz." << endl);
153  }
154 
155  const double period = 1.0e9 / rate_Hz; // [ns]
156 
157  const double Tmin = 0.0; // [ns]
158  const double Tmax = 1.0e8; // [ns]
159 
160  const int NUMBER_OF_PMTS = 31;
161  const int NUMBER_OF_MODULES = 115 * 18;
162 
163 
164  //typedef int hit_type;
165  typedef double hit_type;
166  typedef JGetElement<hit_type> JGetElement_t;
167  const JGetElement_t getElement;
168  typedef std::vector<hit_type> JBuffer1D;
169  typedef std::vector<JBuffer1D> JBuffer2D;
170 
171 
172  // generate random data
173 
174  JBuffer2D input(NUMBER_OF_PMTS);
175 
176  for (int i = 0; i != NUMBER_OF_PMTS; ++i) {
177 
178  for (double t1 = Tmin + gRandom->Exp(period); t1 < Tmax; t1 += gRandom->Exp(period)) {
179  input[i].push_back(getElement(t1));
180  }
181 
182  NOTICE("PMT[" << setw(2) << i << "] " << input[i].size() << endl);
183 
184  input[i].push_back(JGetElement_t::getEndMarker());
185  }
186 
187 
188  if (true) {
189 
190  JTimer timer("std::sort");
191 
192  JBuffer1D buffer;
193 
194  timer.start();
195 
196  for (int i = 0; i != NUMBER_OF_MODULES; ++i) {
197 
198  buffer.clear();
199 
200  for (int i = 0; i != NUMBER_OF_PMTS; ++i) {
201  copy(input[i].begin(), input[i].end() - 1, back_inserter(buffer));
202  }
203 
204  std::sort(buffer.begin(), buffer.end());
205 
206  if (do_test && !JTOOLS::is_sorted(buffer.begin(), buffer.end())) {
207  FATAL("std::sort failed." << endl);
208  }
209  }
210 
211  timer.stop();
212  timer.print(cout, false);
213  }
214 
215  if (true) {
216 
217  JTimer timer("std::inplace_merge");
218 
219  JBuffer1D buffer;
220 
221  vector<size_t> delimiter(NUMBER_OF_PMTS + 1);
222 
223  timer.start();
224 
225  for (int i = 0; i != NUMBER_OF_MODULES; ++i) {
226 
227  size_t n = 0;
228 
229  for (int i = 0; i != NUMBER_OF_PMTS; ++i) {
230  n += input[i].size() - 1;
231  }
232 
233  buffer.resize(n);
234 
235  JBuffer1D::iterator out = buffer.begin();
236 
237  delimiter[0] = 0;
238 
239  for (int i = 0; i != NUMBER_OF_PMTS; ++i) {
240 
241  out = copy(input[i].begin(), input[i].end() - 1, out);
242 
243  delimiter[i+1] = distance(buffer.begin(), out);
244  }
245 
246  inplace_merge(buffer.begin(), delimiter.size(), delimiter.data());
247 
248  if (do_test && !JTOOLS::is_sorted(buffer.begin(), buffer.end())) {
249  FATAL("std::inplace_merge failed." << endl);
250  }
251  }
252 
253  timer.stop();
254  timer.print(cout, false);
255  }
256 
257  if (true) {
258 
259  JTimer timer("JMergeSort");
260 
261  JBuffer1D buffer;
262  JMergeSort<hit_type> merge;
263 
264  timer.start();
265 
266  for (int i = 0; i != NUMBER_OF_MODULES; ++i) {
267 
268  buffer.clear();
269 
270  merge(input, buffer);
271 
272  if (do_test && !JTOOLS::is_sorted(buffer.begin(), buffer.end())) {
273  FATAL("JMergeSort failed." << endl);
274  }
275  }
276 
277  timer.stop();
278  timer.print(cout, false);
279  }
280 }
JMessage.hh
JTOOLS::JGetElement::operator()
T operator()(const double x) const
Type conversion operator.
Definition: JMergeSort.cc:79
JTOOLS::JGetElement
Auxiliary class to convert value to element.
Definition: JMergeSort.cc:64
JTOOLS::n
const int n
Definition: JPolint.hh:628
std::vector
Definition: JSTDTypes.hh:12
KM3NETDAQ::NUMBER_OF_PMTS
static const int NUMBER_OF_PMTS
Total number of PMTs in module.
Definition: JDAQ.hh:26
JTOOLS::JGetElement::getEndMarker
static T getEndMarker()
Get end marker.
Definition: JMergeSort.cc:90
JTOOLS::inplace_merge
void inplace_merge(T __begin, const size_t N, const size_t *delimiter)
Merge multiple sorted ranges.
Definition: JMergeSort.cc:28
JPARSER::JParser
Utility class to parse command line options.
Definition: JParser.hh:1493
distance
std::vector< T >::difference_type distance(typename std::vector< T >::const_iterator first, typename PhysicsEvent::const_iterator< T > second)
Specialisation of STL distance.
Definition: PhysicsEvent.hh:434
NOTICE
#define NOTICE(A)
Definition: JMessage.hh:64
main
int main(int argc, char **argv)
Definition: JMergeSort.cc:126
JAANET::copy
void copy(const Head &from, JHead &to)
Copy header from from to to.
Definition: JHead.cc:152
JPP
This name space includes all other name spaces (except KM3NETDAQ, KM3NET and ANTARES).
Definition: JAAnetToolkit.hh:37
JMergeSort.hh
debug
int debug
debug level
Definition: JSirene.cc:59
JParser.hh
JTOOLS::JGetElement::JGetElement
JGetElement()
Default constructor.
Definition: JMergeSort.cc:69
make_field
#define make_field(A,...)
macro to convert parameter to JParserTemplateElement object
Definition: JParser.hh:1954
std
Definition: jaanetDictionary.h:36
JTimer.hh
JTOOLS::is_sorted
bool is_sorted(T __begin, T __end)
Test whether range is sorted.
Definition: JMergeSort.cc:105
JTOOLS
Auxiliary classes and methods for multi-dimensional interpolations and histograms.
Definition: JAbstractCollection.hh:9
FATAL
#define FATAL(A)
Definition: JMessage.hh:67