#ifndef __statistics_h__ #define __statistics_h__ 1 #include #include namespace utils { template void clearpq(std::priority_queue& q) { struct HackedQueue : private std::priority_queue { static S& Container(std::priority_queue& q) { return q.*&HackedQueue::c; } }; HackedQueue::Container(q).clear(); } class statistics { size_t N; double A; double varL; double varH; double m,M; double Median; bool computeMedian; // These heap stores are only used when computeMedian=true. // Max heap stores the smaller half elements: std::priority_queue s; // Min heap stores the greater half elements: std::priority_queue,std::greater > g; public: statistics(bool computeMedian=false) : computeMedian(computeMedian) { clear(); } void clear() {N=0; A=varL=varH=0.0; m=DBL_MAX; M=-m; clearpq(s); clearpq(g);} double count() {return N;} double mean() {return A;} double max() {return M;} double min() {return m;} double sum() {return N*A;} void add(double t) { ++N; double diff=t-A; A += diff/N; double v=diff*(t-A); if(diff < 0.0) varL += v; else varH += v; if(t < m) m=t; if(t > M) M=t; if(computeMedian) { if(N == 1) s.push(Median=t); else { if(s.size() > g.size()) { // left side heap has more elements if(t < Median) { g.push(s.top()); s.pop(); s.push(t); } else g.push(t); Median=0.5*(s.top()+g.top()); } else if(s.size() == g.size()) { // both heaps are balanced if(t < Median) { s.push(t); Median=(double) s.top(); } else { g.push(t); Median=(double) g.top(); } } else { // right side heap has more elements if(t > Median) { s.push(g.top()); g.pop(); g.push(t); } else s.push(t); Median=0.5*(s.top()+g.top()); } } } } double stdev(double var, double f) { if(N <= f) return DBL_MAX; return sqrt(var*f/(N-f)); } double stdev() { return stdev(varL+varH,1.0); } double stdevL() { return stdev(varL,2.0); } double stdevH() { return stdev(varH,2.0); } double stderror() { return stdev()/sqrt((double) N); } double median() { if(!computeMedian) { std::cerr << "Constructor requires median=true" << std::endl; exit(-1); } return Median; } void output(const char *text, size_t m) { std::cout << text << ": \n" << m << "\t" << A << "\t" << stdevL() << "\t" << stdevH() << std::endl; } }; } #endif