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 
11 #include "JLang/JException.hh"
12 #include "JLang/JTitle.hh"
13 #include "Jeep/JPrint.hh"
14 
15 
16 /**
17  * \author mdejong
18  */
19 
20 namespace JTOOLS {}
21 namespace JPP { using namespace JTOOLS; }
22 
23 namespace JTOOLS {
24 
25  using JLANG::JTitle;
27  using JLANG::JNoValue;
28 
29 
30  /**
31  * Quantile calculator.
32  * This class acts as a zero-dimensional histogram.
33  */
34  class JQuantile :
35  public JTitle
36  {
37  public:
38  /**
39  * Constructor.
40  *
41  * \param title title
42  * \param option option
43  */
44  JQuantile(const JTitle& title = "",
45  const int option = 0) :
46  JTitle (title),
47  quantiles(false)
48  {
49  reset();
50 
51  quantiles = (option > 0);
52  }
53 
54 
55  /**
56  * Reset.
57  */
58  void reset()
59  {
60  sum = 0.0;
61  rms = 0.0;
62  tot = 0.0;
63  num = 0;
64  min = +std::numeric_limits<double>::max();
65  max = -std::numeric_limits<double>::max();
66 
67  buffer.clear();
68  }
69 
70 
71  /**
72  * Put value.
73  *
74  * \param x value
75  * \param w weight
76  */
77  void put(const double x, const double w = 1.0)
78  {
79  sum += w*x;
80  rms += w*x*x;
81  tot += w;
82  num += 1;
83  min = std::min(min, x);
84  max = std::max(max, x);
85 
86  if (quantiles) {
87  buffer.insert(std::make_pair(x,w));
88  }
89  }
90 
91 
92  /**
93  * Get total count.
94  *
95  * \return count
96  */
97  long long int getCount() const
98  {
99  return num;
100  }
101 
102 
103  /**
104  * Get total weight.
105  *
106  * \return weight
107  */
108  double getTotal() const
109  {
110  return tot;
111  }
112 
113 
114 
115  /**
116  * Get weighted sum.
117  *
118  * \return weighted sum
119  */
120  double getSum() const
121  {
122  return sum;
123  }
124 
125 
126  /**
127  * Get mean value.
128  *
129  * \return mean value
130  */
131  double getMean() const
132  {
133  if (tot != 0.0)
134  return sum / tot;
135  else
136  throw JDivisionByZero("JQuantile::getMean()");
137  }
138 
139 
140  /**
141  * Get RMS.
142  *
143  * \return RMS
144  */
145  double getRMS() const
146  {
147  if (tot != 0.0)
148  return sqrt(rms/tot);
149  else
150  throw JDivisionByZero("JQuantile::getRMS()");
151  }
152 
153 
154  /**
155  * Get standard deviation
156  *
157  * \return standard deviation
158  */
159  double getSTDev() const
160  {
161  if (tot != 0.0)
162  return sqrt(rms*tot - sum*sum)/tot;
163  else
164  throw JDivisionByZero("JQuantile::getSTDev()");
165  }
166 
167 
168  /**
169  * Get maximal deviation from average.
170  *
171  * \param relative relative to average or absolute
172  * \return deviation
173  */
174  double getDeviation(const bool relative = true) const
175  {
176  if (relative)
177  return std::max(max - getMean(), getMean() - min);
178  else
179  return std::max(fabs(max), fabs(min));
180  }
181 
182 
183  /**
184  * Test relative accuracy.
185  *
186  * \param precision relative precision
187  * \return true if reached accuracy; else false
188  */
189  bool hasAccuracy(const double precision) const
190  {
191  return getCount() > 3 && getSTDev() < precision * getMean();
192  }
193 
194 
195  /**
196  * Get quantile.
197  *
198  * \param Q quantile
199  * \param reverse reverse
200  * \return value
201  */
202  double getQuantile(const double Q, const bool reverse = false) const
203  {
204  if (quantiles) {
205 
206  double W = 0.0;
207 
208  for (std::map<double, double>::const_iterator i = buffer.begin(); i != buffer.end(); ++i) {
209  W += i->second;
210  }
211 
212  if (reverse)
213  return getQuantile(buffer.rbegin(), buffer.rend(), Q*W);
214  else
215  return getQuantile(buffer. begin(), buffer. end(), Q*W);
216  }
217 
218  throw JNoValue("JQuantile::getQuantile()");
219  }
220 
221 
222  /**
223  * Print quantile.
224  *
225  * \param out output stream
226  * \param lpr long print
227  */
228  std::ostream& print(std::ostream& out, bool lpr = true) const
229  {
230  using namespace std;
231 
232  const int nc = getTitle().size();
233 
234  if (lpr) {
235  out << setw(nc) << left << " " << ' '
236  << setw(10) << left << " mean" << ' '
237  << setw(10) << left << " STD" << ' '
238  << setw(10) << left << " deviation" << endl;
239  }
240 
241  out << setw(nc) << left << getTitle() << ' '
242  << SCIENTIFIC(10,2) << getMean() << ' '
243  << SCIENTIFIC(10,2) << getSTDev() << ' '
244  << SCIENTIFIC(10,2) << getDeviation(false) << endl;
245 
246  return out;
247  }
248 
249 
250  /**
251  * Print quantile.
252  *
253  * \param out output stream
254  * \param quantile quantile
255  * \return output stream
256  */
257  friend inline std::ostream& operator<<(std::ostream& out, const JQuantile& quantile)
258  {
259  return quantile.print(out, getLongprint(out));
260  }
261 
262  protected:
263  double sum;
264  double rms;
265  double tot;
266  double min;
267  double max;
268  long long int num;
269 
270  bool quantiles;
272 
273 
274  /**
275  * Get quantile.
276  *
277  * \param __begin begin of data
278  * \param __end end of data
279  * \param W weight
280  * \return value
281  */
282  template<class T>
283  static double getQuantile(T __begin, T __end, const double W)
284  {
285  double w = 0.0;
286 
287  for (T i = __begin; i != __end; ++i) {
288 
289  w += i->second;
290 
291  if (w >= W) {
292  return i->first;
293  }
294  }
295 
296  throw JNoValue("JQuantile::getQuantile()");
297  }
298  };
299 }
300 
301 #endif
double getQuantile(const double Q, const bool reverse=false) const
Get quantile.
Definition: JQuantile.hh:202
Exceptions.
long long int num
Definition: JQuantile.hh:268
friend std::ostream & operator<<(std::ostream &out, const JQuantile &quantile)
Print quantile.
Definition: JQuantile.hh:257
std::map< double, double > buffer
Definition: JQuantile.hh:271
void put(const double x, const double w=1.0)
Put value.
Definition: JQuantile.hh:77
const std::string & getTitle() const
Get title.
Definition: JTitle.hh:55
double getTotal() const
Get total weight.
Definition: JQuantile.hh:108
Quantile calculator.
Definition: JQuantile.hh:34
double getRMS() const
Get RMS.
Definition: JQuantile.hh:145
bool getLongprint(std::ostream &out)
Get long print option.
Definition: JPrint.hh:138
Exception for missing value.
Definition: JException.hh:180
bool hasAccuracy(const double precision) const
Test relative accuracy.
Definition: JQuantile.hh:189
I/O formatting auxiliaries.
double getSTDev() const
Get standard deviation.
Definition: JQuantile.hh:159
Auxiliary class for title.
Definition: JTitle.hh:19
JQuantile(const JTitle &title="", const int option=0)
Constructor.
Definition: JQuantile.hh:44
void reset()
Reset.
Definition: JQuantile.hh:58
std::ostream & print(std::ostream &out, bool lpr=true) const
Print quantile.
Definition: JQuantile.hh:228
double getMean() const
Get mean value.
Definition: JQuantile.hh:131
std::string title
Definition: JTitle.hh:73
Exception for division by zero.
Definition: JException.hh:252
double getSum() const
Get weighted sum.
Definition: JQuantile.hh:120
long long int getCount() const
Get total count.
Definition: JQuantile.hh:97
static double getQuantile(T __begin, T __end, const double W)
Get quantile.
Definition: JQuantile.hh:283
double getDeviation(const bool relative=true) const
Get maximal deviation from average.
Definition: JQuantile.hh:174
Auxiliary data structure for floating point format specification.
Definition: JPrint.hh:498