1 #ifndef ContainerStatistics_H
2 #define ContainerStatistics_H
7 #include <boost/accumulators/accumulators.hpp>
8 #include <boost/accumulators/statistics/stats.hpp>
9 #include <boost/accumulators/statistics/mean.hpp>
10 #include <boost/accumulators/statistics/median.hpp>
11 #include <boost/accumulators/statistics/max.hpp>
12 #include <boost/accumulators/statistics/min.hpp>
13 #include <boost/accumulators/statistics/count.hpp>
14 #include <boost/accumulators/statistics/sum.hpp>
16 using namespace boost::accumulators;
23 typedef accumulator_set<DataType, stats<tag::mean,tag::min, tag::max, tag::count>> Basic;
24 typedef accumulator_set<DataType, stats<tag::median>> Median;
27 HistogramBin(DataType limit=0, quint64 count=0) : _limit(limit), _count(count) {}
33 enum PropertySets{pBASIC=0, pMIN=1, pMAX=2, pDISTANCE=4, pDELTA=8,pNETTOCOUNT=16, pCOUNT=32, pSUM=64,
34 pMEAN=128, pMEDIAN=256, pPREDOMINANT=512, pSTDEV=1024, pHISTOGRAM=2048, pLAST=4096, pALL=4294967296};
38 _markers.resize(index(pLAST));
39 DataType undefined = undef<DataType>();
40 std::fill(_markers.begin(), _markers.end(), undefined);
43 double operator[](PropertySets method)
const{
47 quint32 ind = index(method);
48 if ( ind < _markers.size()) {
49 if ( hasType(method, pMEAN | pMIN | pMAX | pMEDIAN))
50 return (DataType)_markers[ind];
52 return _markers[ind] ;
57 std::vector<HistogramBin> histogram() {
62 double prop(PropertySets method)
const{
63 return operator[](method);
66 quint16 significantDigits()
const {
71 void findSignificantDigits(
double distance) {
75 double d = prop(pMAX) - prop(pMIN);
76 int lenBase = log10(std::abs(d)) / 2;
77 QString num = QString::number(distance,
'g',10);
78 quint32 len = num.size();
79 for(
int i=num.size() - 2; i >=0; ++i){
88 _sigDigits = -log10(distance) + std::max( 3 - lenBase,1);
89 _sigDigits = std::min(len, _sigDigits);
92 void binCount(quint32 value) {
98 template<
typename IterType>
bool calculate(
const IterType& begin,
const IterType& end, PropertySets mode=pBASIC){
102 DataType undefined = undef<DataType>();
103 double sigDigits = 0;
105 std::for_each(begin, end, [&] (
const DataType& sample){
107 if ( sample != undefined) {
108 rest = fabs(sample - (qint64)sample);
109 sigDigits = std::max(sigDigits, rest - sigDigits);
110 basicMarkers(sample);
111 if ( hasType(mode, pMEDIAN)) {
117 bool isUndefined = boost::accumulators::count(basicMarkers) == 0;
118 std::fill(_markers.begin(), _markers.end(), rUNDEF);
120 _markers[index(pMIN)] = boost::accumulators::min(basicMarkers);
121 _markers[index(pMAX)] = boost::accumulators::max(basicMarkers);
122 _markers[index(pDISTANCE)] = std::abs(prop(pMAX) - prop(pMIN));
123 _markers[index(pDELTA)] = prop(pMAX) - prop(pMIN);
124 _markers[index(pNETTOCOUNT)] = boost::accumulators::count(basicMarkers);
125 _markers[index(pCOUNT)] = count;
126 _markers[index(pSUM)] = boost::accumulators::sum(basicMarkers);
127 _markers[index(pMEAN)] = boost::accumulators::mean(basicMarkers);
128 _markers[index(pMEDIAN)] = boost::accumulators::median(median);
129 findSignificantDigits(sigDigits);
131 if ( mode & pSTDEV) {
132 _markers[index(pSTDEV)] = calcStdDev(begin, end, undefined);
134 if ( mode & pHISTOGRAM) {
136 double ncount = prop(pNETTOCOUNT);
138 if (_binCount == iUNDEF ){
139 if ( prop(pSTDEV) == rUNDEF) {
140 _markers[index(pSTDEV)] = calcStdDev(begin, end, undefined);
142 if ( _markers[index(pSTDEV)] != rUNDEF ) {
143 double h = 3.5 * _markers[index(pSTDEV)] / pow(ncount, 0.3333);
144 _binCount = prop(pDISTANCE) / h;
149 _bins.resize(_binCount);
150 double delta = prop(pDELTA);
151 for(
int i=0; i < _binCount; ++i ) {
152 _bins[i] = HistogramBin(i * ( delta / _binCount));
154 std::for_each(begin, end, [&] (
const DataType& sample){
155 quint16 index = getOffsetFactorFor(sample);
156 _bins[index]._count++;
164 bool isValid()
const {
165 return prop(pMAX) != rUNDEF;
168 double stretchLinear(
double input,
int stretchRange)
const {
169 if ( input == rUNDEF)
172 double stretchFactor = stretchRange / prop(pDELTA);
173 quint16 index = getOffsetFactorFor(input);
174 return _bins[index]._limit * stretchFactor;
186 if (percent == rUNDEF) {
187 return std::pair<double,double>(prop(pMIN),prop(pMAX));
189 double delta = prop(pDELTA);
190 double downsizeBy = percent * delta / 100;
191 double newLower = prop(pMIN) + downsizeBy;
192 double newUpper = prop(pMAX) - downsizeBy;
193 return std::pair<double,double>(newLower,newUpper);
197 std::vector<double> _markers;
200 std::vector<HistogramBin> _bins;
201 quint32 _binCount=iUNDEF;
203 quint32 index(PropertySets method)
const {
206 return (quint32)(log(method) / log(2) + 0.2);
209 template<
typename IterType>
double calcStdDev(
const IterType& begin,
const IterType& end, DataType undefined) {
210 double ncount = prop(pNETTOCOUNT);
214 double mean = prop(pMEAN);
215 std::for_each(begin, end, [&] (
const DataType& sample){
216 if ( sample != undefined)
217 acc += (sample - mean) * (sample - mean);
219 return sqrt(acc / (ncount-1));
224 quint16 getOffsetFactorFor(
const DataType& sample)
const {
227 double rmin = prop(pMIN);
228 return _bins.size() * (double)(sample - rmin) / prop(pDELTA);
231 double getBinWidth()
const {
232 if (_bins.size() > 1) {
233 return _bins[1]._limit;
235 return _bins[0]._limit;
241 typedef ContainerStatistics<double> NumericStatistics;
244 #endif // ContainerStatistics_H