Jpp
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
JQuantile.hh
Go to the documentation of this file.
1 #ifndef __JTOOLS__JQUANTILE__
2 #define __JTOOLS__JQUANTILE__
3 
4 #include <ostream>
5 #include <iomanip>
6 #include <cmath>
7 #include <limits>
8 #include <algorithm>
9 #include <map>
10 #include <iterator>
11 
12 #include "JLang/JException.hh"
13 #include "JLang/JTitle.hh"
14 #include "JMath/JMath.hh"
15 #include "Jeep/JPrint.hh"
16 
17 
18 /**
19  * \author mdejong
20  */
21 
22 namespace JTOOLS {}
23 namespace JPP { using namespace JTOOLS; }
24 
25 namespace JTOOLS {
26 
27  using JLANG::JTitle;
29  using JLANG::JNoValue;
30 
31  /**
32  * Auxiliary data structure for quantiles.
33  */
34  struct JQuantile_t :
35  public JTitle
36  {
37  /**
38  * Constructor.
39  *
40  * \param title title
41  * \param quantiles quantiles
42  */
43  JQuantile_t(const JTitle& title = "",
44  const bool quantiles = false) :
45  JTitle (title),
47  {
48  reset();
49  }
50 
51 
52  /**
53  * Reset.
54  */
55  void reset()
56  {
57  sum = 0.0;
58  rms = 0.0;
59  tot = 0.0;
60  num = 0;
61  min = +std::numeric_limits<double>::max();
62  max = -std::numeric_limits<double>::max();
63 
64  buffer.clear();
65  }
66 
67  protected:
68  double sum;
69  double rms;
70  double tot;
71  double min;
72  double max;
73  long long int num;
74  bool quantiles;
76  };
77 
78 
79  /**
80  * Quantile calculator.\n
81  * This class acts as a zero-dimensional histogram.
82  */
83  struct JQuantile :
84  public JQuantile_t,
85  public JMATH::JMath<JQuantile>
86  {
87  /**
88  * Constructor.
89  *
90  * \param title title
91  * \param quantiles quantiles
92  */
93  JQuantile(const JTitle& title = "",
94  const bool quantiles = false) :
96  {}
97 
98 
99  /**
100  * Constructor.\n
101  * Set quantiles according to minimal and maximal value in input data.
102  *
103  * \param title title
104  * \param __begin begin of data
105  * \param __end end of data
106  * \param quantiles quantiles
107  * \param w weight
108  */
109  template<class iterator_type>
111  iterator_type __begin,
112  iterator_type __end,
113  const bool quantiles = false,
114  const double w = 1.0) :
115  JQuantile_t(title, quantiles)
116  {
117  put(__begin, __end, w);
118  }
119 
120 
121  /**
122  * Constructor.\n
123  * Set quantiles according to minimal and maximal value in input data.
124  *
125  * \param title title
126  * \param __begin begin of data
127  * \param __end end of data
128  * \param member pointer to data member
129  * \param quantiles quantiles
130  * \param w weight
131  */
132  template<class iterator_type, class value_type, class result_type>
134  iterator_type __begin,
135  iterator_type __end,
136  result_type value_type::*member,
137  const bool quantiles = false,
138  const double w = 1.0) :
139  JQuantile_t(title, quantiles)
140  {
141  put(__begin, __end, member, w);
142  }
143 
144 
145  /**
146  * Constructor.\n
147  * Set quantiles according to minimal and maximal value in input data.
148  *
149  * \param title title
150  * \param __begin begin of data
151  * \param __end end of data
152  * \param function pointer to member method
153  * \param quantiles quantiles
154  * \param w weight
155  */
156  template<class iterator_type, class value_type, class result_type>
158  iterator_type __begin,
159  iterator_type __end,
160  result_type (value_type::*function)() const,
161  const bool quantiles = false,
162  const double w = 1.0) :
163  JQuantile_t(title, quantiles)
164  {
165  put(__begin, __end, function, w);
166  }
167 
168 
169  /**
170  * Add quantile.
171  *
172  * \param Q quantile
173  * \return this quantile
174  */
176  {
177  sum += Q.sum;
178  rms += Q.rms;
179  tot += Q.tot;
180  num += Q.num;
181  min = std::min(min, Q.min);
182  max = std::max(max, Q.max);
183 
184  if (quantiles) {
185  std::copy(Q.buffer.begin(), Q.buffer.end(), std::inserter(buffer, buffer.end()));
186  }
187 
188  return *this;
189  }
190 
191 
192  /**
193  * Put value.
194  *
195  * \param x value
196  * \param w weight
197  */
198  void put(const double x, const double w = 1.0)
199  {
200  sum += w*x;
201  rms += w*x*x;
202  tot += w;
203  num += 1;
204  min = std::min(min, x);
205  max = std::max(max, x);
206 
207  if (quantiles) {
208  buffer.insert(std::make_pair(x,w));
209  }
210  }
211 
212 
213  /**
214  * Put data.
215  *
216  * \param __begin begin of data
217  * \param __end end of data
218  * \param w weight
219  */
220  template<class iterator_type>
221  void put(iterator_type __begin,
222  iterator_type __end,
223  const double w = 1.0)
224  {
225  for (iterator_type i = __begin; i != __end; ++i) {
226  put(*i, w);
227  }
228  }
229 
230 
231  /**
232  * Put data.
233  *
234  * \param __begin begin of data
235  * \param __end end of data
236  * \param member pointer to data member
237  * \param w weight
238  */
239  template<class iterator_type, class value_type, class result_type>
240  void put(iterator_type __begin,
241  iterator_type __end,
242  result_type value_type::*member,
243  const double w = 1.0)
244  {
245  for (iterator_type i = __begin; i != __end; ++i) {
246  put((*i).*member, w);
247  }
248  }
249 
250 
251  /**
252  * Put data.
253  *
254  * \param __begin begin of data
255  * \param __end end of data
256  * \param function pointer to member method
257  * \param w weight
258  */
259  template<class iterator_type, class value_type, class result_type>
260  void put(iterator_type __begin,
261  iterator_type __end,
262  result_type (value_type::*function)() const,
263  const double w = 1.0)
264  {
265  for (iterator_type i = __begin; i != __end; ++i) {
266  put(((*i).*function)(), w);
267  }
268  }
269 
270 
271  /**
272  * Get total count.
273  *
274  * \return count
275  */
276  long long int getCount() const
277  {
278  return num;
279  }
280 
281 
282  /**
283  * Get total weight.
284  *
285  * \return weight
286  */
287  double getTotal() const
288  {
289  return tot;
290  }
291 
292 
293  /**
294  * Get weighted sum.
295  *
296  * \return weighted sum
297  */
298  double getSum() const
299  {
300  return sum;
301  }
302 
303 
304  /**
305  * Get minimum.
306  *
307  * \return minimum
308  */
309  double getMin() const
310  {
311  return min;
312  }
313 
314 
315  /**
316  * Get maximum.
317  *
318  * \return maximum
319  */
320  double getMax() const
321  {
322  return max;
323  }
324 
325 
326  /**
327  * Get mean value.
328  *
329  * \return mean value
330  */
331  double getMean() const
332  {
333  if (tot != 0.0)
334  return sum / tot;
335  else
336  THROW(JDivisionByZero, "JQuantile::getMean()");
337  }
338 
339 
340  /**
341  * Get RMS.
342  *
343  * \return RMS
344  */
345  double getRMS() const
346  {
347  if (tot != 0.0)
348  return sqrt(rms/tot);
349  else
350  THROW(JDivisionByZero, "JQuantile::getRMS()");
351  }
352 
353 
354  /**
355  * Get standard deviation
356  *
357  * \return standard deviation
358  */
359  double getSTDev() const
360  {
361  if (tot != 0.0)
362  return sqrt(rms*tot - sum*sum)/tot;
363  else
364  THROW(JDivisionByZero, "JQuantile::getSTDev()");
365  }
366 
367 
368  /**
369  * Get maximal deviation from average.
370  *
371  * \param relative if true, relative to average, else absolute
372  * \return deviation
373  */
374  double getDeviation(const bool relative = true) const
375  {
376  if (relative)
377  return std::max(getMax() - getMean(), getMean() - getMin());
378  else
379  return getMax() - getMin();
380  }
381 
382 
383  /**
384  * Test relative accuracy.
385  *
386  * \param precision relative precision
387  * \return true if reached accuracy; else false
388  */
389  bool hasAccuracy(const double precision) const
390  {
391  return getCount() > 3 && getSTDev() < precision * getMean();
392  }
393 
394 
395  /**
396  * Get quantile.
397  *
398  * \param Q quantile
399  * \param reverse reverse
400  * \return value
401  */
402  double getQuantile(const double Q, const bool reverse = false) const
403  {
404  if (quantiles) {
405 
406  double W = 0.0;
407 
408  for (std::map<double, double>::const_iterator i = buffer.begin(); i != buffer.end(); ++i) {
409  W += i->second;
410  }
411 
412  if (reverse)
413  return getQuantile(buffer.rbegin(), buffer.rend(), Q*W);
414  else
415  return getQuantile(buffer. begin(), buffer. end(), Q*W);
416  }
417 
418  THROW(JNoValue, "Option 'quantiles' at JQuantile() incompatible with method getQuantile().");
419  }
420 
421 
422  /**
423  * Print quantile.
424  *
425  * \param out output stream
426  * \param lpr long print
427  */
428  std::ostream& print(std::ostream& out, bool lpr = true) const
429  {
430  using namespace std;
431 
432  const int nc = getTitle().size();
433 
434  if (lpr) {
435  out << setw(nc) << left << " " << ' '
436  << setw(10) << left << " mean" << ' '
437  << setw(10) << left << " STD" << ' '
438  << setw(10) << left << " deviation" << endl;
439  }
440 
441  out << setw(nc) << left << getTitle() << ' '
442  << SCIENTIFIC(10,2) << getMean() << ' '
443  << SCIENTIFIC(10,2) << getSTDev() << ' '
444  << SCIENTIFIC(10,2) << getDeviation(false) << endl;
445 
446  return out;
447  }
448 
449 
450  /**
451  * Print quantile.
452  *
453  * \param out output stream
454  * \param quantile quantile
455  * \return output stream
456  */
457  friend inline std::ostream& operator<<(std::ostream& out, const JQuantile& quantile)
458  {
459  return quantile.print(out, getLongprint(out));
460  }
461 
462  protected:
463  /**
464  * Get quantile.
465  *
466  * \param __begin begin of data
467  * \param __end end of data
468  * \param W weight
469  * \return value
470  */
471  template<class T>
472  static double getQuantile(T __begin, T __end, const double W)
473  {
474  double w = 0.0;
475 
476  for (T i = __begin; i != __end; ++i) {
477 
478  w += i->second;
479 
480  if (w >= W) {
481  return i->first;
482  }
483  }
484 
485  THROW(JNoValue, "Invalid weight " << W);
486  }
487  };
488 }
489 
490 #endif
JQuantile_t(const JTitle &title="", const bool quantiles=false)
Constructor.
Definition: JQuantile.hh:43
data_type w[N+1][M+1]
Definition: JPolint.hh:708
Exceptions.
bool hasAccuracy(const double precision) const
Test relative accuracy.
Definition: JQuantile.hh:389
Auxiliary base class for aritmetic operations of derived class types.
Definition: JMath.hh:26
double getTotal() const
Get total weight.
Definition: JQuantile.hh:287
JQuantile(const JTitle &title, iterator_type __begin, iterator_type __end, result_type value_type::*member, const bool quantiles=false, const double w=1.0)
Constructor.
Definition: JQuantile.hh:133
long long int num
Definition: JQuantile.hh:73
double getSTDev() const
Get standard deviation.
Definition: JQuantile.hh:359
Quantile calculator.
Definition: JQuantile.hh:83
friend std::ostream & operator<<(std::ostream &out, const JQuantile &quantile)
Print quantile.
Definition: JQuantile.hh:457
double getMax() const
Get maximum.
Definition: JQuantile.hh:320
JQuantile(const JTitle &title, iterator_type __begin, iterator_type __end, result_type(value_type::*function)() const, const bool quantiles=false, const double w=1.0)
Constructor.
Definition: JQuantile.hh:157
void put(iterator_type __begin, iterator_type __end, const double w=1.0)
Put data.
Definition: JQuantile.hh:221
#define THROW(JException_t, A)
Marco for throwing exception with std::ostream compatible message.
Definition: JException.hh:670
void put(iterator_type __begin, iterator_type __end, result_type(value_type::*function)() const, const double w=1.0)
Put data.
Definition: JQuantile.hh:260
std::multimap< double, double > buffer
Definition: JQuantile.hh:75
double getRMS() const
Get RMS.
Definition: JQuantile.hh:345
const std::string & getTitle() const
Get title.
Definition: JTitle.hh:55
double getMean() const
Get mean value.
Definition: JQuantile.hh:331
double getQuantile(const double Q, const bool reverse=false) const
Get quantile.
Definition: JQuantile.hh:402
bool getLongprint(std::ostream &out)
Get long print option.
Definition: JPrint.hh:157
Exception for missing value.
Definition: JException.hh:198
JQuantile(const JTitle &title="", const bool quantiles=false)
Constructor.
Definition: JQuantile.hh:93
double getMin() const
Get minimum.
Definition: JQuantile.hh:309
I/O formatting auxiliaries.
double getSum() const
Get weighted sum.
Definition: JQuantile.hh:298
std::ostream & print(std::ostream &out, bool lpr=true) const
Print quantile.
Definition: JQuantile.hh:428
JQuantile(const JTitle &title, iterator_type __begin, iterator_type __end, const bool quantiles=false, const double w=1.0)
Constructor.
Definition: JQuantile.hh:110
Auxiliary class for title.
Definition: JTitle.hh:19
do set_variable OUTPUT_DIRECTORY $WORKDIR T
void put(iterator_type __begin, iterator_type __end, result_type value_type::*member, const double w=1.0)
Put data.
Definition: JQuantile.hh:240
void put(const double x, const double w=1.0)
Put value.
Definition: JQuantile.hh:198
long long int getCount() const
Get total count.
Definition: JQuantile.hh:276
JQuantile & add(const JQuantile &Q)
Add quantile.
Definition: JQuantile.hh:175
Auxiliary data structure for quantiles.
Definition: JQuantile.hh:34
double getDeviation(const bool relative=true) const
Get maximal deviation from average.
Definition: JQuantile.hh:374
std::string title
Definition: JTitle.hh:73
Exception for division by zero.
Definition: JException.hh:270
void copy(const Head &from, JHead &to)
Copy header from from to to.
Definition: JHead.cc:153
Base class for data structures with artithmetic capabilities.
static double getQuantile(T __begin, T __end, const double W)
Get quantile.
Definition: JQuantile.hh:472
void reset()
Reset.
Definition: JQuantile.hh:55
Auxiliary data structure for floating point format specification.
Definition: JPrint.hh:518