2 * Copyright (c) 2003 The Regents of The University of Michigan
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 * Generalized N-dimensinal vector
37 * -- these both can use the same function that prints out a
38 * specific set of stats
39 * VectorStandardDeviation totals
42 #ifndef __STATISTICS_HH__
43 #define __STATISTICS_HH__
64 #define STAT_DISPLAY_COMPAT
68 namespace Statistics {
69 typedef double result_t;
70 typedef std::vector<result_t> rvec_t;
72 typedef u_int32_t FormatFlags;
73 const FormatFlags none = 0x0000;
74 const FormatFlags total = 0x0001;
75 const FormatFlags pdf = 0x0002;
76 const FormatFlags nozero = 0x0004;
77 const FormatFlags nonan = 0x0008;
78 const FormatFlags cdf = 0x0010;
79 const FormatFlags dist = 0x0020;
80 const FormatFlags __substat = 0x8000;
81 const FormatFlags __reserved = __substat;
84 //////////////////////////////////////////////////////////////////////
86 // Statistics Framework Base classes
88 //////////////////////////////////////////////////////////////////////
97 const StatData *mydata() const;
99 const SubData *mysubdata(int index) const;
100 SubData *mysubdata_create(int index);
103 virtual std::string myname() const;
104 virtual std::string mysubname(int index) const;
105 virtual std::string mydesc() const;
106 virtual std::string mysubdesc(int index) const;
107 virtual FormatFlags myflags() const;
108 virtual bool dodisplay() const;
109 virtual int myprecision() const;
115 virtual void display(std::ostream &stream) const = 0;
116 virtual size_t size() const = 0;
117 virtual bool zero() const = 0;
119 Stat &name(const std::string &name);
120 Stat &desc(const std::string &desc);
121 Stat &precision(int p);
122 Stat &flags(FormatFlags f);
123 Stat &prereq(const Stat &prereq);
124 Stat &subname(int index, const std::string &name);
125 Stat &subdesc(int index, const std::string &name);
128 static bool less(Stat *stat1, Stat *stat2);
135 // Scalar stats involved in formulas
136 class ScalarStat : public Stat
139 ScalarStat(bool reg) : Stat(reg) {}
140 virtual result_t val() const = 0;
141 virtual bool zero() const;
142 virtual void display(std::ostream &stream) const;
146 VectorDisplay(std::ostream &stream, const std::string &myname,
147 const std::vector<std::string> *mysubnames,
148 const std::string &mydesc,
149 const std::vector<std::string> *mysubdescs,
150 int myprecision, FormatFlags myflags, const rvec_t &vec,
153 // Vector stats involved in formulas
154 class VectorStat : public Stat
157 VectorStat(bool reg) : Stat(reg) {}
158 virtual const rvec_t &val() const = 0;
159 virtual result_t total() const = 0;
160 virtual bool zero() const;
161 virtual void display(std::ostream &stream) const;
164 //////////////////////////////////////////////////////////////////////
168 //////////////////////////////////////////////////////////////////////
169 template <typename T>
179 StatStor(const Params &) : data(T()) {}
181 void set(T val, const Params &p) { data = val; }
182 void inc(T val, const Params &p) { data += val; }
183 void dec(T val, const Params &p) { data -= val; }
184 result_t val(const Params &p) const { return (result_t)data; }
185 T value(const Params &p) const { return data; }
188 template <typename T>
196 mutable result_t total;
200 AvgStor(const Params &) : current(T()), total(0), last(0) { }
202 void set(T val, const Params &p) {
203 total += current * (curTick - last);
207 void inc(T val, const Params &p) { set(current + val, p); }
208 void dec(T val, const Params &p) { set(current - val, p); }
209 result_t val(const Params &p) const {
210 total += current * (curTick - last);
212 return (result_t)(total + current) / (result_t)(curTick + 1);
214 T value(const Params &p) const { return current; }
217 template <typename T, template <typename T> class Storage, class Bin>
218 class ScalarBase : public ScalarStat
221 typedef Storage<T> storage_t;
222 typedef typename storage_t::Params params_t;
223 typedef typename Bin::Bin<storage_t> bin_t;
230 storage_t *data() { return bin.data(params); }
231 const storage_t *data() const {
232 return (const_cast<bin_t *>(&bin))->data(params);
236 // Copying stats is not allowed
237 ScalarBase(const ScalarBase &stat);
238 const ScalarBase &operator=(const ScalarBase &);
241 result_t val() const { return data()->val(params); }
242 T value() const { return data()->value(params); }
245 ScalarBase() : ScalarStat(true) {
251 // Common operators for stats
252 void operator++() { data()->inc(1, params); }
253 void operator--() { data()->dec(1, params); }
255 void operator++(int) { ++*this; }
256 void operator--(int) { --*this; }
258 template <typename U>
259 void operator=(const U& v) { data()->set(v, params); }
261 template <typename U>
262 void operator+=(const U& v) { data()->inc(v, params); }
264 template <typename U>
265 void operator-=(const U& v) { data()->dec(v, params); }
267 virtual size_t size() const { return 1; }
270 //////////////////////////////////////////////////////////////////////
274 //////////////////////////////////////////////////////////////////////
275 template <typename T, template <typename T> class Storage, class Bin>
278 template <typename T, template <typename T> class Storage, class Bin>
279 class VectorBase : public VectorStat
282 typedef Storage<T> storage_t;
283 typedef typename storage_t::Params params_t;
284 typedef typename Bin::VectorBin<storage_t> bin_t;
294 storage_t *data(int index) { return bin.data(index, params); }
295 const storage_t *data(int index) const {
296 return (const_cast<bin_t *>(&bin))->data(index, params);
300 // Copying stats is not allowed
301 VectorBase(const VectorBase &stat);
302 const VectorBase &operator=(const VectorBase &);
305 const rvec_t &val() const {
309 vec = new rvec_t(size());
311 for (int i = 0; i < size(); ++i)
312 (*vec)[i] = data(i)->val(params);
317 result_t total() const {
318 result_t total = 0.0;
319 for (int i = 0; i < size(); ++i)
320 total += data(i)->val(params);
325 VectorBase() : VectorStat(true), vec(NULL) {}
326 ~VectorBase() { if (vec) delete vec; }
328 VectorBase &init(size_t size) {
329 bin.init(size, params);
335 friend class ScalarProxy<T, Storage, Bin>;
336 ScalarProxy<T, Storage, Bin> operator[](int index);
338 virtual size_t size() const { return bin.size(); }
341 template <typename T, template <typename T> class Storage, class Bin>
342 class ScalarProxy : public ScalarStat
345 typedef Storage<T> storage_t;
346 typedef typename storage_t::Params params_t;
347 typedef typename Bin::VectorBin<storage_t> bin_t;
355 storage_t *data() { return bin->data(index, *params); }
356 const storage_t *data() const { return bin->data(index, *params); }
359 result_t val() const { return data()->val(*params); }
360 T value() const { return data()->value(*params); }
363 ScalarProxy(bin_t &b, params_t &p, int i)
364 : ScalarStat(false), bin(&b), params(&p), index(i) {}
365 ScalarProxy(const ScalarProxy &sp)
366 : ScalarStat(false), bin(sp.bin), params(sp.params), index(sp.index) {}
367 const ScalarProxy &operator=(const ScalarProxy &sp) {
375 // Common operators for stats
376 void operator++() { data()->inc(1, *params); }
377 void operator--() { data()->dec(1, *params); }
379 void operator++(int) { ++*this; }
380 void operator--(int) { --*this; }
382 template <typename U>
383 void operator=(const U& v) { data()->set(v, *params); }
385 template <typename U>
386 void operator+=(const U& v) { data()->inc(v, *params); }
388 template <typename U>
389 void operator-=(const U& v) { data()->dec(v, *params); }
391 virtual size_t size() const { return 1; }
394 template <typename T, template <typename T> class Storage, class Bin>
395 inline ScalarProxy<T, Storage, Bin>
396 VectorBase<T, Storage, Bin>::operator[](int index)
398 assert (index >= 0 && index < size());
399 return ScalarProxy<T, Storage, Bin>(bin, params, index);
402 template <typename T, template <typename T> class Storage, class Bin>
405 template <typename T, template <typename T> class Storage, class Bin>
406 class Vector2dBase : public Stat
409 typedef Storage<T> storage_t;
410 typedef typename storage_t::Params params_t;
411 typedef typename Bin::VectorBin<storage_t> bin_t;
418 std::vector<std::string> *y_subnames;
421 storage_t *data(int index) { return bin.data(index, params); }
422 const storage_t *data(int index) const {
423 return (const_cast<bin_t *>(&bin))->data(index, params);
427 // Copying stats is not allowed
428 Vector2dBase(const Vector2dBase &stat);
429 const Vector2dBase &operator=(const Vector2dBase &);
432 Vector2dBase() : Stat(true) {}
435 Vector2dBase &init(size_t _x, size_t _y) {
438 bin.init(x * y, params);
440 y_subnames = new std::vector<std::string>(y);
446 * This makes the assumption that if you're gonna subnames a 2d vector,
447 * you're subnaming across all y
449 Vector2dBase &ysubnames(const char **names)
451 for (int i=0; i < y; ++i) {
452 (*y_subnames)[i] = names[i];
456 Vector2dBase &ysubname(int index, const std::string subname)
458 (*y_subnames)[i] = subname.c_str();
461 std::string ysubname(int i) const { return (*y_subnames)[i]; }
463 friend class VectorProxy<T, Storage, Bin>;
464 VectorProxy<T, Storage, Bin> operator[](int index);
466 virtual size_t size() const { return bin.size(); }
467 virtual bool zero() const { return data(0)->value(params) == 0.0; }
470 display(std::ostream &out) const
472 bool have_subname = false;
473 for (int i = 0; i < x; ++i) {
474 if (!mysubname(i).empty())
479 result_t super_total = 0.0;
480 for (int i = 0; i < x; ++i) {
483 subname = mysubname(i);
487 subname = to_string(i);
492 result_t total = 0.0;
493 for (int j = 0; j < y; ++j) {
494 vec[j] = data(iy + j)->val(params);
495 tot_vec[j] += vec[j];
497 super_total += vec[j];
501 if (mysubdesc(i).empty()) {
507 VectorDisplay(out, myname() + "_" + subname, y_subnames, desc, 0,
508 myprecision(), myflags(), vec, total);
511 if ((myflags() & ::Statistics::total) && (x > 1)) {
512 VectorDisplay(out, myname(), y_subnames, mydesc(), 0,
513 myprecision(), myflags(), tot_vec, super_total);
519 template <typename T, template <typename T> class Storage, class Bin>
520 class VectorProxy : public VectorStat
523 typedef Storage<T> storage_t;
524 typedef typename storage_t::Params params_t;
525 typedef typename Bin::VectorBin<storage_t> bin_t;
536 storage_t *data(int index) {
538 return bin->data(offset + index, *params);
541 const storage_t *data(int index) const {
542 return (const_cast<bin_t *>(bin))->data(offset + index, *params);
546 const rvec_t &val() const {
550 vec = new rvec_t(size());
552 for (int i = 0; i < size(); ++i)
553 (*vec)[i] = data(i)->val(*params);
558 result_t total() const {
559 result_t total = 0.0;
560 for (int i = 0; i < size(); ++i)
561 total += data(i)->val(*params);
566 VectorProxy(bin_t &b, params_t &p, int o, int l)
567 : VectorStat(false), bin(&b), params(&p), offset(o), len(l), vec(NULL)
569 VectorProxy(const VectorProxy &sp)
570 : VectorStat(false), bin(sp.bin), params(sp.params), offset(sp.offset),
571 len(sp.len), vec(NULL)
578 const VectorProxy &operator=(const VectorProxy &sp) {
589 virtual size_t size() const { return len; }
591 ScalarProxy<T, Storage, Bin> operator[](int index) {
592 assert (index >= 0 && index < size());
593 return ScalarProxy<T, Storage, Bin>(*bin, *params, offset + index);
597 template <typename T, template <typename T> class Storage, class Bin>
598 inline VectorProxy<T, Storage, Bin>
599 Vector2dBase<T, Storage, Bin>::operator[](int index)
601 int offset = index * y;
602 assert (index >= 0 && offset < size());
603 return VectorProxy<T, Storage, Bin>(bin, params, offset, y);
606 //////////////////////////////////////////////////////////////////////
608 // Non formula statistics
610 //////////////////////////////////////////////////////////////////////
612 void DistDisplay(std::ostream &stream, const std::string &name,
613 const std::string &desc, int precision, FormatFlags flags,
614 result_t min_val, result_t max_val,
615 result_t underflow, result_t overflow,
616 const rvec_t &vec, int min, int max, int bucket_size,
619 template <typename T>
639 DistStor(const Params ¶ms)
640 : min_val(INT_MAX), max_val(INT_MIN), underflow(0), overflow(0),
643 void sample(T val, int number, const Params ¶ms) {
644 if (val < params.min)
646 else if (val > params.max)
649 int index = (val - params.min) / params.bucket_size;
650 assert(index < size(params));
651 vec[index] += number;
661 size_t size(const Params &) const { return vec.size(); }
663 bool zero(const Params ¶ms) const {
664 if (underflow != 0 || overflow != 0)
667 int s = size(params);
668 for (int i = 0; i < s; i++)
675 void display(std::ostream &stream, const std::string &name,
676 const std::string &desc, int precision, FormatFlags flags,
677 const Params ¶ms) const {
679 #ifdef STAT_DISPLAY_COMPAT
680 result_t min = params.min;
682 result_t min = (min_val == INT_MAX) ? params.min : min_val;
684 result_t max = (max_val == INT_MIN) ? 0 : max_val;
686 rvec_t rvec(params.size);
687 for (int i = 0; i < params.size; ++i)
690 DistDisplay(stream, name, desc, precision, flags,
691 (result_t)min, (result_t)max,
692 (result_t)underflow, (result_t)overflow,
693 rvec, params.min, params.max, params.bucket_size,
698 void FancyDisplay(std::ostream &stream, const std::string &name,
699 const std::string &desc, int precision, FormatFlags flags,
700 result_t mean, result_t variance);
701 template <typename T>
713 FancyStor(const Params &) : sum(0), squares(0), total(0) {}
715 void sample(T val, int number, const Params &) {
716 T value = val * number;
718 squares += value * value;
721 void display(std::ostream &stream, const std::string &name,
722 const std::string &desc, int precision, FormatFlags flags,
723 const Params &) const {
726 result_t variance = NAN;
730 result_t fsq = squares;
731 result_t ftot = total;
734 variance = (ftot * fsq - (fsum * fsum)) / (ftot * (ftot - 1.0));
737 FancyDisplay(stream, name, desc, precision, flags, mean, variance);
740 size_t size(const Params &) const { return 1; }
741 bool zero(const Params &) const { return total == 0; }
744 template <typename T>
755 AvgFancy(const Params &) : sum(0), squares(0) {}
757 void sample(T val, int number, const Params& p) {
758 T value = val * number;
760 squares += value * value;
762 void display(std::ostream &stream, const std::string &name,
763 const std::string &desc, int precision, FormatFlags flags,
764 const Params ¶ms) const {
765 result_t mean = sum / curTick;
766 result_t variance = (squares - sum * sum) / curTick;
768 FancyDisplay(stream, name, desc, precision, flags, mean, variance);
771 size_t size(const Params ¶ms) const { return 1; }
772 bool zero(const Params ¶ms) const { return sum == 0; }
775 template <typename T, template <typename T> class Storage, class Bin>
776 class DistBase : public Stat
779 typedef Storage<T> storage_t;
780 typedef typename storage_t::Params params_t;
781 typedef typename Bin::Bin<storage_t> bin_t;
788 storage_t *data() { return bin.data(params); }
789 const storage_t *data() const {
790 return (const_cast<bin_t *>(&bin))->data(params);
794 // Copying stats is not allowed
795 DistBase(const DistBase &stat);
796 const DistBase &operator=(const DistBase &);
799 DistBase() : Stat(true) { }
802 template <typename U>
803 void sample(const U& v, int n = 1) { data()->sample(v, n, params); }
805 virtual size_t size() const { return data()->size(params); }
806 virtual bool zero() const { return data()->zero(params); }
807 virtual void display(std::ostream &stream) const {
808 data()->display(stream, myname(), mydesc(), myprecision(), myflags(),
813 template <typename T, template <typename T> class Storage, class Bin>
814 class VectorDistProxy;
816 template <typename T, template <typename T> class Storage, class Bin>
817 class VectorDistBase : public Stat
820 typedef Storage<T> storage_t;
821 typedef typename storage_t::Params params_t;
822 typedef typename Bin::VectorBin<storage_t> bin_t;
829 storage_t *data(int index) { return bin.data(index, params); }
830 const storage_t *data(int index) const {
831 return (const_cast<bin_t *>(&bin))->data(index, params);
835 // Copying stats is not allowed
836 VectorDistBase(const VectorDistBase &stat);
837 const VectorDistBase &operator=(const VectorDistBase &);
840 VectorDistBase() : Stat(true) { }
841 ~VectorDistBase() { }
843 friend class VectorDistProxy<T, Storage, Bin>;
844 VectorDistProxy<T, Storage, Bin> operator[](int index);
845 const VectorDistProxy<T, Storage, Bin> operator[](int index) const;
847 virtual size_t size() const { return bin.size(); }
848 virtual bool zero() const { return false; }
849 virtual void display(std::ostream &stream) const;
852 template <typename T, template <typename T> class Storage, class Bin>
853 class VectorDistProxy : public Stat
856 typedef Storage<T> storage_t;
857 typedef typename storage_t::Params params_t;
858 typedef typename Bin::Bin<storage_t> bin_t;
859 typedef VectorDistBase<T, Storage, Bin> base_t;
869 storage_t *data() { return stat->data(index); }
870 const storage_t *data() const { return cstat->data(index); }
873 VectorDistProxy(const VectorDistBase<T, Storage, Bin> &s, int i)
874 : Stat(false), cstat(&s), index(i) {}
875 VectorDistProxy(const VectorDistProxy &sp)
876 : Stat(false), cstat(sp.cstat), index(sp.index) {}
877 const VectorDistProxy &operator=(const VectorDistProxy &sp) {
878 cstat = sp.cstat; index = sp.index; return *this;
882 template <typename U>
883 void sample(const U& v, int n = 1) { data()->sample(v, n, cstat->params); }
885 virtual size_t size() const { return 1; }
886 virtual bool zero() const {
887 return data()->zero(cstat->params);
889 virtual void display(std::ostream &stream) const {
890 std::stringstream name, desc;
892 if (!(cstat->mysubname(index).empty())) {
893 name << cstat->myname() << cstat->mysubname(index);
895 name << cstat->myname() << "_" << index;
897 if (!(cstat->mysubdesc(index).empty())) {
898 desc << cstat->mysubdesc(index);
900 desc << cstat->mydesc();
903 data()->display(stream, name.str(), desc.str(),
904 cstat->myprecision(), cstat->myflags(), cstat->params);
908 template <typename T, template <typename T> class Storage, class Bin>
909 inline VectorDistProxy<T, Storage, Bin>
910 VectorDistBase<T, Storage, Bin>::operator[](int index)
912 assert (index >= 0 && index < size());
913 return VectorDistProxy<T, Storage, Bin>(*this, index);
916 template <typename T, template <typename T> class Storage, class Bin>
917 inline const VectorDistProxy<T, Storage, Bin>
918 VectorDistBase<T, Storage, Bin>::operator[](int index) const
920 assert (index >= 0 && index < size());
921 return VectorDistProxy<T, Storage, Bin>(*this, index);
925 * @todo Need a way to print Distribution totals across the Vector
927 template <typename T, template <typename T> class Storage, class Bin>
929 VectorDistBase<T, Storage, Bin>::display(std::ostream &stream) const
931 for (int i = 0; i < size(); ++i) {
932 VectorDistProxy<T, Storage, Bin> proxy(*this, i);
933 proxy.display(stream);
939 VectorDistBase<T, Storage, Bin>::total(int index) const
942 for (int i=0; i < x_size(); ++i) {
943 total += data(i)->val(*params);
948 //////////////////////////////////////////////////////////////////////
952 //////////////////////////////////////////////////////////////////////
953 class Node : public RefCounted
956 virtual size_t size() const = 0;
957 virtual const rvec_t &val() const = 0;
958 virtual result_t total() const = 0;
961 typedef RefCountingPtr<Node> NodePtr;
963 class ScalarStatNode : public Node
966 const ScalarStat &stat;
967 mutable rvec_t result;
970 ScalarStatNode(const ScalarStat &s) : stat(s), result(1) {}
971 const rvec_t &val() const { result[0] = stat.val(); return result; }
972 virtual result_t total() const { return stat.val(); };
974 virtual size_t size() const { return 1; }
977 template <typename T, template <typename T> class Storage, class Bin>
978 class ScalarProxyNode : public Node
981 const ScalarProxy<T, Storage, Bin> proxy;
982 mutable rvec_t result;
985 ScalarProxyNode(const ScalarProxy<T, Storage, Bin> &p)
986 : proxy(p), result(1) { }
987 const rvec_t &val() const { result[0] = proxy.val(); return result; }
988 virtual result_t total() const { return proxy.val(); };
990 virtual size_t size() const { return 1; }
993 class VectorStatNode : public Node
996 const VectorStat &stat;
999 VectorStatNode(const VectorStat &s) : stat(s) {}
1000 const rvec_t &val() const { return stat.val(); }
1001 virtual result_t total() const { return stat.total(); };
1003 virtual size_t size() const { return stat.size(); }
1006 template <typename T>
1007 class ConstNode : public Node
1013 ConstNode(T s) : data(1, (result_t)s) {}
1014 const rvec_t &val() const { return data; }
1015 virtual result_t total() const { return data[0]; };
1017 virtual size_t size() const { return 1; }
1020 template <typename T>
1021 class FunctorNode : public Node
1025 mutable rvec_t result;
1028 FunctorNode(T &f) : functor(f) { result.resize(1); }
1029 const rvec_t &val() const {
1030 result[0] = (result_t)functor();
1033 virtual result_t total() const { return (result_t)functor(); };
1035 virtual size_t size() const { return 1; }
1038 template <typename T>
1039 class ScalarNode : public Node
1043 mutable rvec_t result;
1046 ScalarNode(T &s) : scalar(s) { result.resize(1); }
1047 const rvec_t &val() const {
1048 result[0] = (result_t)scalar;
1051 virtual result_t total() const { return (result_t)scalar; };
1053 virtual size_t size() const { return 1; }
1057 class UnaryNode : public Node
1061 mutable rvec_t result;
1064 UnaryNode(NodePtr p) : l(p) {}
1066 const rvec_t &val() const {
1067 const rvec_t &lvec = l->val();
1068 int size = lvec.size();
1072 result.resize(size);
1074 for (int i = 0; i < size; ++i)
1075 result[i] = op(lvec[i]);
1080 result_t total() const {
1082 return op(l->total());
1085 virtual size_t size() const { return l->size(); }
1089 class BinaryNode : public Node
1094 mutable rvec_t result;
1097 BinaryNode(NodePtr a, NodePtr b) : l(a), r(b) {}
1099 const rvec_t &val() const {
1101 const rvec_t &lvec = l->val();
1102 const rvec_t &rvec = r->val();
1104 assert(lvec.size() > 0 && rvec.size() > 0);
1106 if (lvec.size() == 1 && rvec.size() == 1) {
1108 result[0] = op(lvec[0], rvec[0]);
1109 } else if (lvec.size() == 1) {
1110 int size = rvec.size();
1111 result.resize(size);
1112 for (int i = 0; i < size; ++i)
1113 result[i] = op(lvec[0], rvec[i]);
1114 } else if (rvec.size() == 1) {
1115 int size = lvec.size();
1116 result.resize(size);
1117 for (int i = 0; i < size; ++i)
1118 result[i] = op(lvec[i], rvec[0]);
1119 } else if (rvec.size() == lvec.size()) {
1120 int size = rvec.size();
1121 result.resize(size);
1122 for (int i = 0; i < size; ++i)
1123 result[i] = op(lvec[i], rvec[i]);
1129 result_t total() const {
1131 return op(l->total(), r->total());
1134 virtual size_t size() const {
1142 assert(ls == rs && "Node vector sizes are not equal");
1149 class SumNode : public Node
1153 mutable rvec_t result;
1156 SumNode(NodePtr p) : l(p), result(1) {}
1158 const rvec_t &val() const {
1159 const rvec_t &lvec = l->val();
1160 int size = lvec.size();
1166 for (int i = 0; i < size; ++i)
1167 result[0] = op(result[0], lvec[i]);
1172 result_t total() const {
1173 const rvec_t &lvec = l->val();
1174 int size = lvec.size();
1177 result_t result = 0.0;
1180 for (int i = 0; i < size; ++i)
1181 result = op(result, lvec[i]);
1186 virtual size_t size() const { return 1; }
1195 Temp(NodePtr n) : node(n) {}
1196 Temp(const ScalarStat &s) : node(new ScalarStatNode(s)) {}
1197 template <typename T, template <typename T> class Storage, class Bin>
1198 Temp(const ScalarProxy<T, Storage, Bin> &p)
1199 : node(new ScalarProxyNode<T, Storage, Bin>(p)) {}
1200 Temp(const VectorStat &s) : node(new VectorStatNode(s)) {}
1202 #define TempSCALAR(T) \
1203 Temp(T value) : node(new ConstNode<T>(value)) {}
1205 TempSCALAR( signed char);
1206 TempSCALAR(unsigned char);
1207 TempSCALAR( signed short);
1208 TempSCALAR(unsigned short);
1209 TempSCALAR( signed int);
1210 TempSCALAR(unsigned int);
1211 TempSCALAR( signed long);
1212 TempSCALAR(unsigned long);
1213 TempSCALAR( signed long long);
1214 TempSCALAR(unsigned long long);
1219 operator NodePtr() { return node;}
1223 //////////////////////////////////////////////////////////////////////
1225 // Binning Interface
1227 //////////////////////////////////////////////////////////////////////
1236 off_t size() const { return memsize; }
1240 BinBase(size_t size);
1244 } // namespace Detail
1246 template <class BinType>
1247 struct StatBin : public Detail::BinBase
1249 static StatBin *&curBin() {
1250 static StatBin *current = NULL;
1254 static void setCurBin(StatBin *bin) { curBin() = bin; }
1255 static StatBin *current() { assert(curBin()); return curBin(); }
1257 static off_t &offset() {
1258 static off_t offset = 0;
1262 static off_t new_offset(size_t size) {
1263 size_t mask = sizeof(u_int64_t) - 1;
1264 off_t off = offset();
1266 // That one is for the last trailing flags byte.
1267 offset() += (size + 1 + mask) & ~mask;
1272 explicit StatBin(size_t size = 1024) : Detail::BinBase(size) {}
1274 char *memory(off_t off) {
1275 assert(offset() <= size());
1276 return Detail::BinBase::memory() + off;
1279 static void activate(StatBin &bin) { setCurBin(&bin); }
1287 BinBase() : offset(-1) {}
1288 void allocate(size_t size) {
1289 offset = new_offset(size);
1292 assert(offset != -1);
1293 return current()->memory(offset);
1297 template <class Storage>
1298 class Bin : public BinBase
1301 typedef typename Storage::Params Params;
1304 Bin() { allocate(sizeof(Storage)); }
1305 bool initialized() const { return true; }
1306 void init(const Params ¶ms) { }
1308 int size() const { return 1; }
1310 Storage *data(const Params ¶ms) {
1311 assert(initialized());
1312 char *ptr = access();
1313 char *flags = ptr + sizeof(Storage);
1314 if (!(*flags & 0x1)) {
1316 new (ptr) Storage(params);
1318 return reinterpret_cast<Storage *>(ptr);
1322 template <class Storage>
1323 class VectorBin : public BinBase
1326 typedef typename Storage::Params Params;
1332 VectorBin() : _size(0) {}
1334 bool initialized() const { return _size > 0; }
1335 void init(int s, const Params ¶ms) {
1336 assert(!initialized());
1339 allocate(_size * sizeof(Storage));
1342 int size() const { return _size; }
1344 Storage *data(int index, const Params ¶ms) {
1345 assert(initialized());
1346 assert(index >= 0 && index < size());
1347 char *ptr = access();
1348 char *flags = ptr + size() * sizeof(Storage);
1349 if (!(*flags & 0x1)) {
1351 for (int i = 0; i < size(); ++i)
1352 new (ptr + i * sizeof(Storage)) Storage(params);
1354 return reinterpret_cast<Storage *>(ptr + index * sizeof(Storage));
1359 class MainBinType {};
1360 typedef StatBin<MainBinType> MainBin;
1364 template <class Storage>
1368 typedef typename Storage::Params Params;
1371 char ptr[sizeof(Storage)];
1374 bool initialized() const { return true; }
1375 void init(const Params ¶ms) {
1376 new (ptr) Storage(params);
1378 int size() const{ return 1; }
1379 Storage *data(const Params ¶ms) {
1380 assert(initialized());
1381 return reinterpret_cast<Storage *>(ptr);
1385 template <class Storage>
1389 typedef typename Storage::Params Params;
1396 VectorBin() : ptr(NULL) { }
1401 bool initialized() const { return ptr != NULL; }
1402 void init(int s, const Params ¶ms) {
1403 assert(s > 0 && "size must be positive!");
1404 assert(!initialized());
1406 ptr = new char[_size * sizeof(Storage)];
1407 for (int i = 0; i < _size; ++i)
1408 new (ptr + i * sizeof(Storage)) Storage(params);
1411 int size() const { return _size; }
1413 Storage *data(int index, const Params ¶ms) {
1414 assert(initialized());
1415 assert(index >= 0 && index < size());
1416 return reinterpret_cast<Storage *>(ptr + index * sizeof(Storage));
1421 //////////////////////////////////////////////////////////////////////
1423 // Visible Statistics Types
1425 //////////////////////////////////////////////////////////////////////
1426 template <typename T = Counter, class Bin = NoBin>
1427 class Scalar : public Detail::ScalarBase<T, Detail::StatStor, Bin>
1430 typedef Detail::ScalarBase<T, Detail::StatStor, Bin> Base;
1432 template <typename U>
1433 void operator=(const U& v) { Base::operator=(v); }
1436 template <typename T = Counter, class Bin = NoBin>
1437 class Average : public Detail::ScalarBase<T, Detail::AvgStor, Bin>
1440 typedef Detail::ScalarBase<T, Detail::AvgStor, Bin> Base;
1442 template <typename U>
1443 void operator=(const U& v) { Base::operator=(v); }
1446 template <typename T = Counter, class Bin = NoBin>
1447 class Vector : public Detail::VectorBase<T, Detail::StatStor, Bin>
1450 template <typename T = Counter, class Bin = NoBin>
1451 class AverageVector : public Detail::VectorBase<T, Detail::AvgStor, Bin>
1454 template <typename T = Counter, class Bin = NoBin>
1455 class Vector2d : public Detail::Vector2dBase<T, Detail::StatStor, Bin>
1458 template <typename T = Counter, class Bin = NoBin>
1459 class Distribution : public Detail::DistBase<T, Detail::DistStor, Bin>
1462 typedef Detail::DistBase<T, Detail::DistStor, Bin> Base;
1463 typedef typename Detail::DistStor<T>::Params Params;
1466 Distribution &init(T min, T max, int bkt) {
1469 params.bucket_size = bkt;
1470 params.size = (max - min) / bkt + 1;
1478 template <typename T = Counter, class Bin = NoBin>
1479 class StandardDeviation : public Detail::DistBase<T, Detail::FancyStor, Bin>
1482 typedef Detail::DistBase<T, Detail::DistStor, Bin> Base;
1483 typedef typename Detail::DistStor<T>::Params Params;
1486 StandardDeviation() {
1492 template <typename T = Counter, class Bin = NoBin>
1493 class AverageDeviation : public Detail::DistBase<T, Detail::AvgFancy, Bin>
1496 typedef Detail::DistBase<T, Detail::DistStor, Bin> Base;
1497 typedef typename Detail::DistStor<T>::Params Params;
1500 AverageDeviation() {
1506 template <typename T = Counter, class Bin = NoBin>
1507 class VectorDistribution
1508 : public Detail::VectorDistBase<T, Detail::DistStor, Bin>
1511 typedef Detail::VectorDistBase<T, Detail::DistStor, Bin> Base;
1512 typedef typename Detail::DistStor<T>::Params Params;
1515 VectorDistribution &init(int size, T min, T max, int bkt) {
1518 params.bucket_size = bkt;
1519 params.size = (max - min) / bkt + 1;
1520 bin.init(size, params);
1527 template <typename T = Counter, class Bin = NoBin>
1528 class VectorStandardDeviation
1529 : public Detail::VectorDistBase<T, Detail::FancyStor, Bin>
1532 typedef Detail::VectorDistBase<T, Detail::FancyStor, Bin> Base;
1533 typedef typename Detail::DistStor<T>::Params Params;
1536 VectorStandardDeviation &init(int size) {
1537 bin.init(size, params);
1544 template <typename T = Counter, class Bin = NoBin>
1545 class VectorAverageDeviation
1546 : public Detail::VectorDistBase<T, Detail::AvgFancy, Bin>
1549 typedef Detail::VectorDistBase<T, Detail::AvgFancy, Bin> Base;
1550 typedef typename Detail::DistStor<T>::Params Params;
1553 VectorAverageDeviation &init(int size) {
1554 bin.init(size, params);
1561 class Formula : public Detail::VectorStat
1564 Detail::NodePtr root;
1565 friend class Detail::Temp;
1568 Formula() : VectorStat(true) { setInit(); }
1569 Formula(Detail::Temp r) : VectorStat(true) {
1574 const Formula &operator=(Detail::Temp r) {
1575 assert(!root && "Can't change formulas");
1581 const Formula &operator+=(Detail::Temp r) {
1582 using namespace Detail;
1584 root = NodePtr(new BinaryNode<std::plus<result_t> >(root, r));
1591 const rvec_t &val() const { return root->val(); }
1592 result_t total() const { return root->total(); }
1594 size_t size() const {
1598 return root->size();
1603 void dump(std::ostream &stream);
1606 operator+(Detail::Temp l, Detail::Temp r)
1608 using namespace Detail;
1609 return NodePtr(new BinaryNode<std::plus<result_t> >(l, r));
1613 operator-(Detail::Temp l, Detail::Temp r)
1615 using namespace Detail;
1616 return NodePtr(new BinaryNode<std::minus<result_t> >(l, r));
1620 operator*(Detail::Temp l, Detail::Temp r)
1622 using namespace Detail;
1623 return NodePtr(new BinaryNode<std::multiplies<result_t> >(l, r));
1627 operator/(Detail::Temp l, Detail::Temp r)
1629 using namespace Detail;
1630 return NodePtr(new BinaryNode<std::divides<result_t> >(l, r));
1634 operator%(Detail::Temp l, Detail::Temp r)
1636 using namespace Detail;
1637 return NodePtr(new BinaryNode<std::modulus<result_t> >(l, r));
1641 operator-(Detail::Temp l)
1643 using namespace Detail;
1644 return NodePtr(new UnaryNode<std::negate<result_t> >(l));
1647 template <typename T>
1651 using namespace Detail;
1652 return NodePtr(new ConstNode<T>(val));
1655 template <typename T>
1659 using namespace Detail;
1660 return NodePtr(new FunctorNode<T>(val));
1663 template <typename T>
1667 using namespace Detail;
1668 return NodePtr(new ScalarNode<T>(val));
1672 sum(Detail::Temp val)
1674 using namespace Detail;
1675 return NodePtr(new SumNode<std::plus<result_t> >(val));
1678 extern bool PrintDescriptions;
1680 } // namespace statistics
1682 #endif // __STATISTICS_HH__