fix includes
[gem5.git] / base / statistics.hh
1 /*
2 * Copyright (c) 2003 The Regents of The University of Michigan
3 * All rights reserved.
4 *
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.
15 *
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.
27 */
28
29 /** @file */
30
31 /**
32 * @todo
33 *
34 * Generalized N-dimensinal vector
35 * documentation
36 * fix AvgStor
37 * key stats
38 * interval stats
39 * -- these both can use the same function that prints out a
40 * specific set of stats
41 * VectorStandardDeviation totals
42 *
43 */
44 #ifndef __STATISTICS_HH__
45 #define __STATISTICS_HH__
46
47 #include <algorithm>
48 #include <functional>
49 #include <iosfwd>
50 #include <sstream>
51 #include <string>
52 #include <vector>
53
54 #include <assert.h>
55
56 #include "base/refcnt.hh"
57 #include "base/str.hh"
58
59 #include "sim/host.hh"
60
61 #ifndef NAN
62 float __nan();
63 #define NAN (__nan())
64 #define __M5_NAN
65 #endif
66
67 #define STAT_DISPLAY_COMPAT
68
69 extern Tick curTick;
70
71 namespace Statistics {
72 typedef double result_t;
73 typedef std::vector<result_t> rvec_t;
74
75 typedef u_int32_t FormatFlags;
76 const FormatFlags none = 0x0000;
77 const FormatFlags total = 0x0001;
78 const FormatFlags pdf = 0x0002;
79 const FormatFlags nozero = 0x0004;
80 const FormatFlags nonan = 0x0008;
81 const FormatFlags cdf = 0x0010;
82 const FormatFlags dist = 0x0020;
83 const FormatFlags __substat = 0x8000;
84 const FormatFlags __reserved = __substat;
85
86 namespace Detail {
87 //////////////////////////////////////////////////////////////////////
88 //
89 // Statistics Framework Base classes
90 //
91 //////////////////////////////////////////////////////////////////////
92 struct StatData;
93 struct SubData;
94
95 /**
96 *The base class of all Stats. This does NOT actually hold all the data, but
97 *it does provide the means for accessing all the Stats data.
98 */
99 class Stat
100 {
101 protected:
102 void setInit();
103 StatData *mydata();
104 const StatData *mydata() const;
105 StatData *print();
106 const SubData *mysubdata(int index) const;
107 SubData *mysubdata_create(int index);
108
109 public:
110 virtual std::string myname() const;
111 virtual std::string mysubname(int index) const;
112 virtual std::string mydesc() const;
113 virtual std::string mysubdesc(int index) const;
114 virtual FormatFlags myflags() const;
115 virtual bool dodisplay() const;
116 virtual int myprecision() const;
117
118 public:
119 Stat(bool reg);
120 virtual ~Stat() {}
121
122 virtual void display(std::ostream &stream) const = 0;
123 virtual size_t size() const = 0;
124 virtual bool zero() const = 0;
125
126 Stat &name(const std::string &name);
127 Stat &desc(const std::string &desc);
128 Stat &precision(int p);
129 Stat &flags(FormatFlags f);
130 Stat &prereq(const Stat &prereq);
131 Stat &subname(int index, const std::string &name);
132 Stat &subdesc(int index, const std::string &name);
133
134 public:
135 static bool less(Stat *stat1, Stat *stat2);
136
137 #ifdef STAT_DEBUG
138 int number;
139 #endif
140 };
141
142 // Scalar stats involved in formulas
143 class ScalarStat : public Stat
144 {
145 public:
146 ScalarStat(bool reg) : Stat(reg) {}
147 virtual result_t val() const = 0;
148 virtual bool zero() const;
149 virtual void display(std::ostream &stream) const;
150 };
151
152 void
153 VectorDisplay(std::ostream &stream, const std::string &myname,
154 const std::vector<std::string> *mysubnames,
155 const std::string &mydesc,
156 const std::vector<std::string> *mysubdescs,
157 int myprecision, FormatFlags myflags, const rvec_t &vec,
158 result_t mytotal);
159
160 // Vector stats involved in formulas
161 class VectorStat : public Stat
162 {
163 public:
164 VectorStat(bool reg) : Stat(reg) {}
165 virtual const rvec_t &val() const = 0;
166 virtual result_t total() const = 0;
167 virtual bool zero() const;
168 virtual void display(std::ostream &stream) const;
169 };
170
171 //////////////////////////////////////////////////////////////////////
172 //
173 // Simple Statistics
174 //
175 //////////////////////////////////////////////////////////////////////
176 template <typename T>
177 struct StatStor
178 {
179 public:
180 struct Params { };
181
182 private:
183 T data;
184
185 public:
186 StatStor(const Params &) : data(T()) {}
187
188 void set(T val, const Params &p) { data = val; }
189 void inc(T val, const Params &p) { data += val; }
190 void dec(T val, const Params &p) { data -= val; }
191 result_t val(const Params &p) const { return (result_t)data; }
192 T value(const Params &p) const { return data; }
193 };
194
195 template <typename T>
196 struct AvgStor
197 {
198 public:
199 struct Params { };
200
201 private:
202 T current;
203 mutable result_t total;
204 mutable Tick last;
205
206 public:
207 AvgStor(const Params &) : current(T()), total(0), last(0) { }
208
209 void set(T val, const Params &p) {
210 total += current * (curTick - last);
211 last = curTick;
212 current = val;
213 }
214 void inc(T val, const Params &p) { set(current + val, p); }
215 void dec(T val, const Params &p) { set(current - val, p); }
216 result_t val(const Params &p) const {
217 total += current * (curTick - last);
218 last = curTick;
219 return (result_t)(total + current) / (result_t)(curTick + 1);
220 }
221 T value(const Params &p) const { return current; }
222 };
223
224 template <typename T, template <typename T> class Storage, class Bin>
225 class ScalarBase : public ScalarStat
226 {
227 protected:
228 typedef Storage<T> storage_t;
229 typedef typename storage_t::Params params_t;
230 typedef typename Bin::Bin<storage_t> bin_t;
231
232 protected:
233 bin_t bin;
234 params_t params;
235
236 protected:
237 storage_t *data() { return bin.data(params); }
238 const storage_t *data() const {
239 return (const_cast<bin_t *>(&bin))->data(params);
240 }
241
242 protected:
243 // Copying stats is not allowed
244 ScalarBase(const ScalarBase &stat);
245 const ScalarBase &operator=(const ScalarBase &);
246
247 public:
248 result_t val() const { return data()->val(params); }
249 T value() const { return data()->value(params); }
250
251 public:
252 ScalarBase() : ScalarStat(true) {
253 bin.init(params);
254 setInit();
255 }
256
257 public:
258 // Common operators for stats
259 void operator++() { data()->inc(1, params); }
260 void operator--() { data()->dec(1, params); }
261
262 void operator++(int) { ++*this; }
263 void operator--(int) { --*this; }
264
265 template <typename U>
266 void operator=(const U& v) { data()->set(v, params); }
267
268 template <typename U>
269 void operator+=(const U& v) { data()->inc(v, params); }
270
271 template <typename U>
272 void operator-=(const U& v) { data()->dec(v, params); }
273
274 virtual size_t size() const { return 1; }
275 };
276
277 //////////////////////////////////////////////////////////////////////
278 //
279 // Vector Statistics
280 //
281 //////////////////////////////////////////////////////////////////////
282 template <typename T, template <typename T> class Storage, class Bin>
283 class ScalarProxy;
284
285 template <typename T, template <typename T> class Storage, class Bin>
286 class VectorBase : public VectorStat
287 {
288 protected:
289 typedef Storage<T> storage_t;
290 typedef typename storage_t::Params params_t;
291 typedef typename Bin::VectorBin<storage_t> bin_t;
292
293 private:
294 mutable rvec_t *vec;
295
296 protected:
297 bin_t bin;
298 params_t params;
299
300 protected:
301 storage_t *data(int index) { return bin.data(index, params); }
302 const storage_t *data(int index) const {
303 return (const_cast<bin_t *>(&bin))->data(index, params);
304 }
305
306 protected:
307 // Copying stats is not allowed
308 VectorBase(const VectorBase &stat);
309 const VectorBase &operator=(const VectorBase &);
310
311 public:
312 const rvec_t &val() const {
313 if (vec)
314 vec->resize(size());
315 else
316 vec = new rvec_t(size());
317
318 for (int i = 0; i < size(); ++i)
319 (*vec)[i] = data(i)->val(params);
320
321 return *vec;
322 }
323
324 result_t total() const {
325 result_t total = 0.0;
326 for (int i = 0; i < size(); ++i)
327 total += data(i)->val(params);
328 return total;
329 }
330
331 public:
332 VectorBase() : VectorStat(true), vec(NULL) {}
333 ~VectorBase() { if (vec) delete vec; }
334
335 VectorBase &init(size_t size) {
336 bin.init(size, params);
337 setInit();
338
339 return *this;
340 }
341
342 friend class ScalarProxy<T, Storage, Bin>;
343 ScalarProxy<T, Storage, Bin> operator[](int index);
344
345 virtual size_t size() const { return bin.size(); }
346 };
347
348 template <typename T, template <typename T> class Storage, class Bin>
349 class ScalarProxy : public ScalarStat
350 {
351 protected:
352 typedef Storage<T> storage_t;
353 typedef typename storage_t::Params params_t;
354 typedef typename Bin::VectorBin<storage_t> bin_t;
355
356 private:
357 bin_t *bin;
358 params_t *params;
359 int index;
360
361 protected:
362 storage_t *data() { return bin->data(index, *params); }
363 const storage_t *data() const { return bin->data(index, *params); }
364
365 public:
366 result_t val() const { return data()->val(*params); }
367 T value() const { return data()->value(*params); }
368
369 public:
370 ScalarProxy(bin_t &b, params_t &p, int i)
371 : ScalarStat(false), bin(&b), params(&p), index(i) {}
372 ScalarProxy(const ScalarProxy &sp)
373 : ScalarStat(false), bin(sp.bin), params(sp.params), index(sp.index) {}
374 const ScalarProxy &operator=(const ScalarProxy &sp) {
375 bin = sp.bin;
376 params = sp.params;
377 index = sp.index;
378 return *this;
379 }
380
381 public:
382 // Common operators for stats
383 void operator++() { data()->inc(1, *params); }
384 void operator--() { data()->dec(1, *params); }
385
386 void operator++(int) { ++*this; }
387 void operator--(int) { --*this; }
388
389 template <typename U>
390 void operator=(const U& v) { data()->set(v, *params); }
391
392 template <typename U>
393 void operator+=(const U& v) { data()->inc(v, *params); }
394
395 template <typename U>
396 void operator-=(const U& v) { data()->dec(v, *params); }
397
398 virtual size_t size() const { return 1; }
399 };
400
401 template <typename T, template <typename T> class Storage, class Bin>
402 inline ScalarProxy<T, Storage, Bin>
403 VectorBase<T, Storage, Bin>::operator[](int index)
404 {
405 assert (index >= 0 && index < size());
406 return ScalarProxy<T, Storage, Bin>(bin, params, index);
407 }
408
409 template <typename T, template <typename T> class Storage, class Bin>
410 class VectorProxy;
411
412 template <typename T, template <typename T> class Storage, class Bin>
413 class Vector2dBase : public Stat
414 {
415 protected:
416 typedef Storage<T> storage_t;
417 typedef typename storage_t::Params params_t;
418 typedef typename Bin::VectorBin<storage_t> bin_t;
419
420 protected:
421 size_t x;
422 size_t y;
423 bin_t bin;
424 params_t params;
425 std::vector<std::string> *y_subnames;
426
427 protected:
428 storage_t *data(int index) { return bin.data(index, params); }
429 const storage_t *data(int index) const {
430 return (const_cast<bin_t *>(&bin))->data(index, params);
431 }
432
433 protected:
434 // Copying stats is not allowed
435 Vector2dBase(const Vector2dBase &stat);
436 const Vector2dBase &operator=(const Vector2dBase &);
437
438 public:
439 Vector2dBase() : Stat(true) {}
440 ~Vector2dBase() { }
441
442 Vector2dBase &init(size_t _x, size_t _y) {
443 x = _x;
444 y = _y;
445 bin.init(x * y, params);
446 setInit();
447 y_subnames = new std::vector<std::string>(y);
448
449 return *this;
450 }
451
452 /**
453 * This makes the assumption that if you're gonna subnames a 2d vector,
454 * you're subnaming across all y
455 */
456 Vector2dBase &ysubnames(const char **names)
457 {
458 for (int i=0; i < y; ++i) {
459 (*y_subnames)[i] = names[i];
460 }
461 return *this;
462 }
463 Vector2dBase &ysubname(int index, const std::string subname)
464 {
465 (*y_subnames)[i] = subname.c_str();
466 return *this;
467 }
468 std::string ysubname(int i) const { return (*y_subnames)[i]; }
469
470 friend class VectorProxy<T, Storage, Bin>;
471 VectorProxy<T, Storage, Bin> operator[](int index);
472
473 virtual size_t size() const { return bin.size(); }
474 virtual bool zero() const { return data(0)->value(params) == 0.0; }
475
476 virtual void
477 display(std::ostream &out) const
478 {
479 bool have_subname = false;
480 for (int i = 0; i < x; ++i) {
481 if (!mysubname(i).empty())
482 have_subname = true;
483 }
484
485 rvec_t tot_vec(y);
486 result_t super_total = 0.0;
487 for (int i = 0; i < x; ++i) {
488 std::string subname;
489 if (have_subname) {
490 subname = mysubname(i);
491 if (subname.empty())
492 continue;
493 } else
494 subname = to_string(i);
495
496 int iy = i * y;
497 rvec_t vec(y);
498
499 result_t total = 0.0;
500 for (int j = 0; j < y; ++j) {
501 vec[j] = data(iy + j)->val(params);
502 tot_vec[j] += vec[j];
503 total += vec[j];
504 super_total += vec[j];
505 }
506
507 std::string desc;
508 if (mysubdesc(i).empty()) {
509 desc = mydesc();
510 } else {
511 desc = mysubdesc(i);
512 }
513
514 VectorDisplay(out, myname() + "_" + subname, y_subnames, desc, 0,
515 myprecision(), myflags(), vec, total);
516
517 }
518 if ((myflags() & ::Statistics::total) && (x > 1)) {
519 VectorDisplay(out, myname(), y_subnames, mydesc(), 0,
520 myprecision(), myflags(), tot_vec, super_total);
521
522 }
523 }
524 };
525
526 template <typename T, template <typename T> class Storage, class Bin>
527 class VectorProxy : public VectorStat
528 {
529 protected:
530 typedef Storage<T> storage_t;
531 typedef typename storage_t::Params params_t;
532 typedef typename Bin::VectorBin<storage_t> bin_t;
533
534 private:
535 bin_t *bin;
536 params_t *params;
537 int offset;
538 int len;
539
540 private:
541 mutable rvec_t *vec;
542
543 storage_t *data(int index) {
544 assert(index < len);
545 return bin->data(offset + index, *params);
546 }
547
548 const storage_t *data(int index) const {
549 return (const_cast<bin_t *>(bin))->data(offset + index, *params);
550 }
551
552 public:
553 const rvec_t &val() const {
554 if (vec)
555 vec->resize(size());
556 else
557 vec = new rvec_t(size());
558
559 for (int i = 0; i < size(); ++i)
560 (*vec)[i] = data(i)->val(*params);
561
562 return *vec;
563 }
564
565 result_t total() const {
566 result_t total = 0.0;
567 for (int i = 0; i < size(); ++i)
568 total += data(i)->val(*params);
569 return total;
570 }
571
572 public:
573 VectorProxy(bin_t &b, params_t &p, int o, int l)
574 : VectorStat(false), bin(&b), params(&p), offset(o), len(l), vec(NULL)
575 { }
576 VectorProxy(const VectorProxy &sp)
577 : VectorStat(false), bin(sp.bin), params(sp.params), offset(sp.offset),
578 len(sp.len), vec(NULL)
579 { }
580 ~VectorProxy() {
581 if (vec)
582 delete vec;
583 }
584
585 const VectorProxy &operator=(const VectorProxy &sp) {
586 bin = sp.bin;
587 params = sp.params;
588 offset = sp.offset;
589 len = sp.len;
590 if (vec)
591 delete vec;
592 vec = NULL;
593 return *this;
594 }
595
596 virtual size_t size() const { return len; }
597
598 ScalarProxy<T, Storage, Bin> operator[](int index) {
599 assert (index >= 0 && index < size());
600 return ScalarProxy<T, Storage, Bin>(*bin, *params, offset + index);
601 }
602 };
603
604 template <typename T, template <typename T> class Storage, class Bin>
605 inline VectorProxy<T, Storage, Bin>
606 Vector2dBase<T, Storage, Bin>::operator[](int index)
607 {
608 int offset = index * y;
609 assert (index >= 0 && offset < size());
610 return VectorProxy<T, Storage, Bin>(bin, params, offset, y);
611 }
612
613 //////////////////////////////////////////////////////////////////////
614 //
615 // Non formula statistics
616 //
617 //////////////////////////////////////////////////////////////////////
618
619 void DistDisplay(std::ostream &stream, const std::string &name,
620 const std::string &desc, int precision, FormatFlags flags,
621 result_t min_val, result_t max_val,
622 result_t underflow, result_t overflow,
623 const rvec_t &vec, int min, int max, int bucket_size,
624 int size);
625
626 template <typename T>
627 struct DistStor
628 {
629 public:
630 struct Params
631 {
632 int min;
633 int max;
634 int bucket_size;
635 int size;
636 };
637
638 private:
639 T min_val;
640 T max_val;
641 T underflow;
642 T overflow;
643 std::vector<T> vec;
644
645 public:
646 DistStor(const Params &params)
647 : min_val(INT_MAX), max_val(INT_MIN), underflow(0), overflow(0),
648 vec(params.size) {
649 }
650 void sample(T val, int number, const Params &params) {
651 if (val < params.min)
652 underflow += number;
653 else if (val > params.max)
654 overflow += number;
655 else {
656 int index = (val - params.min) / params.bucket_size;
657 assert(index < size(params));
658 vec[index] += number;
659 }
660
661 if (val < min_val)
662 min_val = val;
663
664 if (val > max_val)
665 max_val = val;
666 }
667
668 size_t size(const Params &) const { return vec.size(); }
669
670 bool zero(const Params &params) const {
671 if (underflow != 0 || overflow != 0)
672 return true;
673
674 int s = size(params);
675 for (int i = 0; i < s; i++)
676 if (vec[i] != 0)
677 return true;
678
679 return false;
680 }
681
682 void display(std::ostream &stream, const std::string &name,
683 const std::string &desc, int precision, FormatFlags flags,
684 const Params &params) const {
685
686 #ifdef STAT_DISPLAY_COMPAT
687 result_t min = params.min;
688 #else
689 result_t min = (min_val == INT_MAX) ? params.min : min_val;
690 #endif
691 result_t max = (max_val == INT_MIN) ? 0 : max_val;
692
693 rvec_t rvec(params.size);
694 for (int i = 0; i < params.size; ++i)
695 rvec[i] = vec[i];
696
697 DistDisplay(stream, name, desc, precision, flags,
698 (result_t)min, (result_t)max,
699 (result_t)underflow, (result_t)overflow,
700 rvec, params.min, params.max, params.bucket_size,
701 params.size);
702 }
703 };
704
705 void FancyDisplay(std::ostream &stream, const std::string &name,
706 const std::string &desc, int precision, FormatFlags flags,
707 result_t mean, result_t variance);
708 template <typename T>
709 struct FancyStor
710 {
711 public:
712 struct Params {};
713
714 private:
715 T sum;
716 T squares;
717 int total;
718
719 public:
720 FancyStor(const Params &) : sum(0), squares(0), total(0) {}
721
722 void sample(T val, int number, const Params &) {
723 T value = val * number;
724 sum += value;
725 squares += value * value;
726 total += number;
727 }
728 void display(std::ostream &stream, const std::string &name,
729 const std::string &desc, int precision, FormatFlags flags,
730 const Params &) const {
731
732 result_t mean = NAN;
733 result_t variance = NAN;
734
735 if (total != 0) {
736 result_t fsum = sum;
737 result_t fsq = squares;
738 result_t ftot = total;
739
740 mean = fsum / ftot;
741 variance = (ftot * fsq - (fsum * fsum)) / (ftot * (ftot - 1.0));
742 }
743
744 FancyDisplay(stream, name, desc, precision, flags, mean, variance);
745 }
746
747 size_t size(const Params &) const { return 1; }
748 bool zero(const Params &) const { return total == 0; }
749 };
750
751 template <typename T>
752 struct AvgFancy
753 {
754 public:
755 struct Params {};
756
757 private:
758 T sum;
759 T squares;
760
761 public:
762 AvgFancy(const Params &) : sum(0), squares(0) {}
763
764 void sample(T val, int number, const Params& p) {
765 T value = val * number;
766 sum += value;
767 squares += value * value;
768 }
769 void display(std::ostream &stream, const std::string &name,
770 const std::string &desc, int precision, FormatFlags flags,
771 const Params &params) const {
772 result_t mean = sum / curTick;
773 result_t variance = (squares - sum * sum) / curTick;
774
775 FancyDisplay(stream, name, desc, precision, flags, mean, variance);
776 }
777
778 size_t size(const Params &params) const { return 1; }
779 bool zero(const Params &params) const { return sum == 0; }
780 };
781
782 template <typename T, template <typename T> class Storage, class Bin>
783 class DistBase : public Stat
784 {
785 protected:
786 typedef Storage<T> storage_t;
787 typedef typename storage_t::Params params_t;
788 typedef typename Bin::Bin<storage_t> bin_t;
789
790 protected:
791 bin_t bin;
792 params_t params;
793
794 protected:
795 storage_t *data() { return bin.data(params); }
796 const storage_t *data() const {
797 return (const_cast<bin_t *>(&bin))->data(params);
798 }
799
800 protected:
801 // Copying stats is not allowed
802 DistBase(const DistBase &stat);
803 const DistBase &operator=(const DistBase &);
804
805 public:
806 DistBase() : Stat(true) { }
807 ~DistBase() { }
808
809 template <typename U>
810 void sample(const U& v, int n = 1) { data()->sample(v, n, params); }
811
812 virtual size_t size() const { return data()->size(params); }
813 virtual bool zero() const { return data()->zero(params); }
814 virtual void display(std::ostream &stream) const {
815 data()->display(stream, myname(), mydesc(), myprecision(), myflags(),
816 params);
817 }
818 };
819
820 template <typename T, template <typename T> class Storage, class Bin>
821 class VectorDistProxy;
822
823 template <typename T, template <typename T> class Storage, class Bin>
824 class VectorDistBase : public Stat
825 {
826 protected:
827 typedef Storage<T> storage_t;
828 typedef typename storage_t::Params params_t;
829 typedef typename Bin::VectorBin<storage_t> bin_t;
830
831 protected:
832 bin_t bin;
833 params_t params;
834
835 protected:
836 storage_t *data(int index) { return bin.data(index, params); }
837 const storage_t *data(int index) const {
838 return (const_cast<bin_t *>(&bin))->data(index, params);
839 }
840
841 protected:
842 // Copying stats is not allowed
843 VectorDistBase(const VectorDistBase &stat);
844 const VectorDistBase &operator=(const VectorDistBase &);
845
846 public:
847 VectorDistBase() : Stat(true) { }
848 ~VectorDistBase() { }
849
850 friend class VectorDistProxy<T, Storage, Bin>;
851 VectorDistProxy<T, Storage, Bin> operator[](int index);
852 const VectorDistProxy<T, Storage, Bin> operator[](int index) const;
853
854 virtual size_t size() const { return bin.size(); }
855 virtual bool zero() const { return false; }
856 virtual void display(std::ostream &stream) const;
857 };
858
859 template <typename T, template <typename T> class Storage, class Bin>
860 class VectorDistProxy : public Stat
861 {
862 protected:
863 typedef Storage<T> storage_t;
864 typedef typename storage_t::Params params_t;
865 typedef typename Bin::Bin<storage_t> bin_t;
866 typedef VectorDistBase<T, Storage, Bin> base_t;
867
868 private:
869 union {
870 base_t *stat;
871 const base_t *cstat;
872 };
873 int index;
874
875 protected:
876 storage_t *data() { return stat->data(index); }
877 const storage_t *data() const { return cstat->data(index); }
878
879 public:
880 VectorDistProxy(const VectorDistBase<T, Storage, Bin> &s, int i)
881 : Stat(false), cstat(&s), index(i) {}
882 VectorDistProxy(const VectorDistProxy &sp)
883 : Stat(false), cstat(sp.cstat), index(sp.index) {}
884 const VectorDistProxy &operator=(const VectorDistProxy &sp) {
885 cstat = sp.cstat; index = sp.index; return *this;
886 }
887
888 public:
889 template <typename U>
890 void sample(const U& v, int n = 1) { data()->sample(v, n, cstat->params); }
891
892 virtual size_t size() const { return 1; }
893 virtual bool zero() const {
894 return data()->zero(cstat->params);
895 }
896 virtual void display(std::ostream &stream) const {
897 std::stringstream name, desc;
898
899 if (!(cstat->mysubname(index).empty())) {
900 name << cstat->myname() << cstat->mysubname(index);
901 } else {
902 name << cstat->myname() << "_" << index;
903 }
904 if (!(cstat->mysubdesc(index).empty())) {
905 desc << cstat->mysubdesc(index);
906 } else {
907 desc << cstat->mydesc();
908 }
909
910 data()->display(stream, name.str(), desc.str(),
911 cstat->myprecision(), cstat->myflags(), cstat->params);
912 }
913 };
914
915 template <typename T, template <typename T> class Storage, class Bin>
916 inline VectorDistProxy<T, Storage, Bin>
917 VectorDistBase<T, Storage, Bin>::operator[](int index)
918 {
919 assert (index >= 0 && index < size());
920 return VectorDistProxy<T, Storage, Bin>(*this, index);
921 }
922
923 template <typename T, template <typename T> class Storage, class Bin>
924 inline const VectorDistProxy<T, Storage, Bin>
925 VectorDistBase<T, Storage, Bin>::operator[](int index) const
926 {
927 assert (index >= 0 && index < size());
928 return VectorDistProxy<T, Storage, Bin>(*this, index);
929 }
930
931 /**
932 * @todo Need a way to print Distribution totals across the Vector
933 */
934 template <typename T, template <typename T> class Storage, class Bin>
935 void
936 VectorDistBase<T, Storage, Bin>::display(std::ostream &stream) const
937 {
938 for (int i = 0; i < size(); ++i) {
939 VectorDistProxy<T, Storage, Bin> proxy(*this, i);
940 proxy.display(stream);
941 }
942 }
943
944 #if 0
945 result_t
946 VectorDistBase<T, Storage, Bin>::total(int index) const
947 {
948 int total = 0;
949 for (int i=0; i < x_size(); ++i) {
950 total += data(i)->val(*params);
951 }
952 }
953 #endif
954
955 //////////////////////////////////////////////////////////////////////
956 //
957 // Formula Details
958 //
959 //////////////////////////////////////////////////////////////////////
960 class Node : public RefCounted
961 {
962 public:
963 virtual size_t size() const = 0;
964 virtual const rvec_t &val() const = 0;
965 virtual result_t total() const = 0;
966 };
967
968 typedef RefCountingPtr<Node> NodePtr;
969
970 class ScalarStatNode : public Node
971 {
972 private:
973 const ScalarStat &stat;
974 mutable rvec_t result;
975
976 public:
977 ScalarStatNode(const ScalarStat &s) : stat(s), result(1) {}
978 const rvec_t &val() const { result[0] = stat.val(); return result; }
979 virtual result_t total() const { return stat.val(); };
980
981 virtual size_t size() const { return 1; }
982 };
983
984 template <typename T, template <typename T> class Storage, class Bin>
985 class ScalarProxyNode : public Node
986 {
987 private:
988 const ScalarProxy<T, Storage, Bin> proxy;
989 mutable rvec_t result;
990
991 public:
992 ScalarProxyNode(const ScalarProxy<T, Storage, Bin> &p)
993 : proxy(p), result(1) { }
994 const rvec_t &val() const { result[0] = proxy.val(); return result; }
995 virtual result_t total() const { return proxy.val(); };
996
997 virtual size_t size() const { return 1; }
998 };
999
1000 class VectorStatNode : public Node
1001 {
1002 private:
1003 const VectorStat &stat;
1004
1005 public:
1006 VectorStatNode(const VectorStat &s) : stat(s) {}
1007 const rvec_t &val() const { return stat.val(); }
1008 virtual result_t total() const { return stat.total(); };
1009
1010 virtual size_t size() const { return stat.size(); }
1011 };
1012
1013 template <typename T>
1014 class ConstNode : public Node
1015 {
1016 private:
1017 rvec_t data;
1018
1019 public:
1020 ConstNode(T s) : data(1, (result_t)s) {}
1021 const rvec_t &val() const { return data; }
1022 virtual result_t total() const { return data[0]; };
1023
1024 virtual size_t size() const { return 1; }
1025 };
1026
1027 template <typename T>
1028 class FunctorNode : public Node
1029 {
1030 private:
1031 T &functor;
1032 mutable rvec_t result;
1033
1034 public:
1035 FunctorNode(T &f) : functor(f) { result.resize(1); }
1036 const rvec_t &val() const {
1037 result[0] = (result_t)functor();
1038 return result;
1039 }
1040 virtual result_t total() const { return (result_t)functor(); };
1041
1042 virtual size_t size() const { return 1; }
1043 };
1044
1045 template <typename T>
1046 class ScalarNode : public Node
1047 {
1048 private:
1049 T &scalar;
1050 mutable rvec_t result;
1051
1052 public:
1053 ScalarNode(T &s) : scalar(s) { result.resize(1); }
1054 const rvec_t &val() const {
1055 result[0] = (result_t)scalar;
1056 return result;
1057 }
1058 virtual result_t total() const { return (result_t)scalar; };
1059
1060 virtual size_t size() const { return 1; }
1061 };
1062
1063 template <class Op>
1064 class UnaryNode : public Node
1065 {
1066 public:
1067 NodePtr l;
1068 mutable rvec_t result;
1069
1070 public:
1071 UnaryNode(NodePtr p) : l(p) {}
1072
1073 const rvec_t &val() const {
1074 const rvec_t &lvec = l->val();
1075 int size = lvec.size();
1076
1077 assert(size > 0);
1078
1079 result.resize(size);
1080 Op op;
1081 for (int i = 0; i < size; ++i)
1082 result[i] = op(lvec[i]);
1083
1084 return result;
1085 }
1086
1087 result_t total() const {
1088 Op op;
1089 return op(l->total());
1090 }
1091
1092 virtual size_t size() const { return l->size(); }
1093 };
1094
1095 template <class Op>
1096 class BinaryNode : public Node
1097 {
1098 public:
1099 NodePtr l;
1100 NodePtr r;
1101 mutable rvec_t result;
1102
1103 public:
1104 BinaryNode(NodePtr a, NodePtr b) : l(a), r(b) {}
1105
1106 const rvec_t &val() const {
1107 Op op;
1108 const rvec_t &lvec = l->val();
1109 const rvec_t &rvec = r->val();
1110
1111 assert(lvec.size() > 0 && rvec.size() > 0);
1112
1113 if (lvec.size() == 1 && rvec.size() == 1) {
1114 result.resize(1);
1115 result[0] = op(lvec[0], rvec[0]);
1116 } else if (lvec.size() == 1) {
1117 int size = rvec.size();
1118 result.resize(size);
1119 for (int i = 0; i < size; ++i)
1120 result[i] = op(lvec[0], rvec[i]);
1121 } else if (rvec.size() == 1) {
1122 int size = lvec.size();
1123 result.resize(size);
1124 for (int i = 0; i < size; ++i)
1125 result[i] = op(lvec[i], rvec[0]);
1126 } else if (rvec.size() == lvec.size()) {
1127 int size = rvec.size();
1128 result.resize(size);
1129 for (int i = 0; i < size; ++i)
1130 result[i] = op(lvec[i], rvec[i]);
1131 }
1132
1133 return result;
1134 }
1135
1136 result_t total() const {
1137 Op op;
1138 return op(l->total(), r->total());
1139 }
1140
1141 virtual size_t size() const {
1142 int ls = l->size();
1143 int rs = r->size();
1144 if (ls == 1)
1145 return rs;
1146 else if (rs == 1)
1147 return ls;
1148 else {
1149 assert(ls == rs && "Node vector sizes are not equal");
1150 return ls;
1151 }
1152 }
1153 };
1154
1155 template <class Op>
1156 class SumNode : public Node
1157 {
1158 public:
1159 NodePtr l;
1160 mutable rvec_t result;
1161
1162 public:
1163 SumNode(NodePtr p) : l(p), result(1) {}
1164
1165 const rvec_t &val() const {
1166 const rvec_t &lvec = l->val();
1167 int size = lvec.size();
1168 assert(size > 0);
1169
1170 result[0] = 0.0;
1171
1172 Op op;
1173 for (int i = 0; i < size; ++i)
1174 result[0] = op(result[0], lvec[i]);
1175
1176 return result;
1177 }
1178
1179 result_t total() const {
1180 const rvec_t &lvec = l->val();
1181 int size = lvec.size();
1182 assert(size > 0);
1183
1184 result_t result = 0.0;
1185
1186 Op op;
1187 for (int i = 0; i < size; ++i)
1188 result = op(result, lvec[i]);
1189
1190 return result;
1191 }
1192
1193 virtual size_t size() const { return 1; }
1194 };
1195
1196 class Temp
1197 {
1198 private:
1199 NodePtr node;
1200
1201 public:
1202 Temp(NodePtr n) : node(n) {}
1203 Temp(const ScalarStat &s) : node(new ScalarStatNode(s)) {}
1204 template <typename T, template <typename T> class Storage, class Bin>
1205 Temp(const ScalarProxy<T, Storage, Bin> &p)
1206 : node(new ScalarProxyNode<T, Storage, Bin>(p)) {}
1207 Temp(const VectorStat &s) : node(new VectorStatNode(s)) {}
1208
1209 #define TempSCALAR(T) \
1210 Temp(T value) : node(new ConstNode<T>(value)) {}
1211
1212 TempSCALAR( signed char);
1213 TempSCALAR(unsigned char);
1214 TempSCALAR( signed short);
1215 TempSCALAR(unsigned short);
1216 TempSCALAR( signed int);
1217 TempSCALAR(unsigned int);
1218 TempSCALAR( signed long);
1219 TempSCALAR(unsigned long);
1220 TempSCALAR( signed long long);
1221 TempSCALAR(unsigned long long);
1222 TempSCALAR(float);
1223 TempSCALAR(double);
1224 #undef TempSCALAR
1225
1226 operator NodePtr() { return node;}
1227 };
1228
1229
1230 //////////////////////////////////////////////////////////////////////
1231 //
1232 // Binning Interface
1233 //
1234 //////////////////////////////////////////////////////////////////////
1235
1236 class BinBase
1237 {
1238 private:
1239 off_t memsize;
1240 char *mem;
1241
1242 protected:
1243 off_t size() const { return memsize; }
1244 char *memory();
1245
1246 public:
1247 BinBase(size_t size);
1248 ~BinBase();
1249 };
1250
1251 } // namespace Detail
1252
1253 template <class BinType>
1254 struct StatBin : public Detail::BinBase
1255 {
1256 static StatBin *&curBin() {
1257 static StatBin *current = NULL;
1258 return current;
1259 }
1260
1261 static void setCurBin(StatBin *bin) { curBin() = bin; }
1262 static StatBin *current() { assert(curBin()); return curBin(); }
1263
1264 static off_t &offset() {
1265 static off_t offset = 0;
1266 return offset;
1267 }
1268
1269 static off_t new_offset(size_t size) {
1270 size_t mask = sizeof(u_int64_t) - 1;
1271 off_t off = offset();
1272
1273 // That one is for the last trailing flags byte.
1274 offset() += (size + 1 + mask) & ~mask;
1275
1276 return off;
1277 }
1278
1279 explicit StatBin(size_t size = 1024) : Detail::BinBase(size) {}
1280
1281 char *memory(off_t off) {
1282 assert(offset() <= size());
1283 return Detail::BinBase::memory() + off;
1284 }
1285
1286 static void activate(StatBin &bin) { setCurBin(&bin); }
1287
1288 class BinBase
1289 {
1290 private:
1291 int offset;
1292
1293 public:
1294 BinBase() : offset(-1) {}
1295 void allocate(size_t size) {
1296 offset = new_offset(size);
1297 }
1298 char *access() {
1299 assert(offset != -1);
1300 return current()->memory(offset);
1301 }
1302 };
1303
1304 template <class Storage>
1305 class Bin : public BinBase
1306 {
1307 public:
1308 typedef typename Storage::Params Params;
1309
1310 public:
1311 Bin() { allocate(sizeof(Storage)); }
1312 bool initialized() const { return true; }
1313 void init(const Params &params) { }
1314
1315 int size() const { return 1; }
1316
1317 Storage *data(const Params &params) {
1318 assert(initialized());
1319 char *ptr = access();
1320 char *flags = ptr + sizeof(Storage);
1321 if (!(*flags & 0x1)) {
1322 *flags |= 0x1;
1323 new (ptr) Storage(params);
1324 }
1325 return reinterpret_cast<Storage *>(ptr);
1326 }
1327 };
1328
1329 template <class Storage>
1330 class VectorBin : public BinBase
1331 {
1332 public:
1333 typedef typename Storage::Params Params;
1334
1335 private:
1336 int _size;
1337
1338 public:
1339 VectorBin() : _size(0) {}
1340
1341 bool initialized() const { return _size > 0; }
1342 void init(int s, const Params &params) {
1343 assert(!initialized());
1344 assert(s > 0);
1345 _size = s;
1346 allocate(_size * sizeof(Storage));
1347 }
1348
1349 int size() const { return _size; }
1350
1351 Storage *data(int index, const Params &params) {
1352 assert(initialized());
1353 assert(index >= 0 && index < size());
1354 char *ptr = access();
1355 char *flags = ptr + size() * sizeof(Storage);
1356 if (!(*flags & 0x1)) {
1357 *flags |= 0x1;
1358 for (int i = 0; i < size(); ++i)
1359 new (ptr + i * sizeof(Storage)) Storage(params);
1360 }
1361 return reinterpret_cast<Storage *>(ptr + index * sizeof(Storage));
1362 }
1363 };
1364 };
1365
1366 class MainBinType {};
1367 typedef StatBin<MainBinType> MainBin;
1368
1369 struct NoBin
1370 {
1371 template <class Storage>
1372 struct Bin
1373 {
1374 public:
1375 typedef typename Storage::Params Params;
1376
1377 private:
1378 char ptr[sizeof(Storage)];
1379
1380 public:
1381 bool initialized() const { return true; }
1382 void init(const Params &params) {
1383 new (ptr) Storage(params);
1384 }
1385 int size() const{ return 1; }
1386 Storage *data(const Params &params) {
1387 assert(initialized());
1388 return reinterpret_cast<Storage *>(ptr);
1389 }
1390 };
1391
1392 template <class Storage>
1393 struct VectorBin
1394 {
1395 public:
1396 typedef typename Storage::Params Params;
1397
1398 private:
1399 char *ptr;
1400 int _size;
1401
1402 public:
1403 VectorBin() : ptr(NULL) { }
1404 ~VectorBin() {
1405 if (initialized())
1406 delete [] ptr;
1407 }
1408 bool initialized() const { return ptr != NULL; }
1409 void init(int s, const Params &params) {
1410 assert(s > 0 && "size must be positive!");
1411 assert(!initialized());
1412 _size = s;
1413 ptr = new char[_size * sizeof(Storage)];
1414 for (int i = 0; i < _size; ++i)
1415 new (ptr + i * sizeof(Storage)) Storage(params);
1416 }
1417
1418 int size() const { return _size; }
1419
1420 Storage *data(int index, const Params &params) {
1421 assert(initialized());
1422 assert(index >= 0 && index < size());
1423 return reinterpret_cast<Storage *>(ptr + index * sizeof(Storage));
1424 }
1425 };
1426 };
1427
1428 //////////////////////////////////////////////////////////////////////
1429 //
1430 // Visible Statistics Types
1431 //
1432 //////////////////////////////////////////////////////////////////////
1433 /**@defgroup VStats VisibleStatTypes
1434 */
1435
1436 /** @ingroup VStats
1437 *This is the simplest counting stat. Default type is Counter, but can be
1438 *anything (like double, int, etc). To bin, just designate the name of the bin
1439 * when declaring. It can be used like a regular Counter.
1440 *Example: Stat<> foo;
1441 *foo += num_foos;
1442 */
1443 template <typename T = Counter, class Bin = NoBin>
1444 class Scalar : public Detail::ScalarBase<T, Detail::StatStor, Bin>
1445 {
1446 public:
1447 typedef Detail::ScalarBase<T, Detail::StatStor, Bin> Base;
1448
1449 /** sets Stat equal to value of type U */
1450 template <typename U>
1451 void operator=(const U& v) { Base::operator=(v); }
1452 };
1453
1454 /** @ingroup VStats
1455 *This calculates averages over number of cycles. Additionally, the update per
1456 *cycle is implicit if there is no change. In other words, if you want to know
1457 *the average number of instructions in the IQ per cycle, then you can use this
1458 * stat and not have to update it on cycles where there is no change.
1459 */
1460 template <typename T = Counter, class Bin = NoBin>
1461 class Average : public Detail::ScalarBase<T, Detail::AvgStor, Bin>
1462 {
1463 public:
1464 typedef Detail::ScalarBase<T, Detail::AvgStor, Bin> Base;
1465
1466 /** sets Average equalt to value of type U*/
1467 template <typename U>
1468 void operator=(const U& v) { Base::operator=(v); }
1469 };
1470
1471 /** @ingroup VStats
1472 *This is a vector of type T, ideally suited to track stats across something like
1473 * SMT threads.
1474 */
1475 template <typename T = Counter, class Bin = NoBin>
1476 class Vector : public Detail::VectorBase<T, Detail::StatStor, Bin>
1477 { };
1478
1479 /** @ingroup VStats
1480 *This is a vector of Averages of type T
1481 */
1482 template <typename T = Counter, class Bin = NoBin>
1483 class AverageVector : public Detail::VectorBase<T, Detail::AvgStor, Bin>
1484 { };
1485
1486 /** @ingroup VStats
1487 *This is a 2-dimensional vector. Intended usage is for something like tracking a
1488 * Vector stat across another Vector like SMT threads.
1489 */
1490 template <typename T = Counter, class Bin = NoBin>
1491 class Vector2d : public Detail::Vector2dBase<T, Detail::StatStor, Bin>
1492 { };
1493
1494 /** @ingroup VStats
1495 * This is essentially a Vector, but with minor differences. Where a
1496 * Vector's index maps directly to what it's tracking, a Distribution's index can
1497 * map to an arbitrary bucket type. For example, you could map 1-8 to bucket 0
1498 * of a Distribution, and if ever there are 1-8 instructions within an IQ, increment
1499 * bucket 0.
1500 */
1501 template <typename T = Counter, class Bin = NoBin>
1502 class Distribution : public Detail::DistBase<T, Detail::DistStor, Bin>
1503 {
1504 private:
1505 typedef Detail::DistBase<T, Detail::DistStor, Bin> Base;
1506 typedef typename Detail::DistStor<T>::Params Params;
1507
1508 public:
1509 /**
1510 *This must be called to set some data members of the distribution
1511 *as well as to allocate the appropriate storage size.
1512 *@param min The minimum value of the Distribution
1513 *@param max The maximum value of the Distribution (NOT the size!)
1514 *@param bkt The size of the buckets to indicate mapping. I.e. if you have
1515 *min=0, max=15, bkt=8, you will have two buckets, and anything from 0-7
1516 *will go into bucket 0, and anything from 8-15 be in bucket 1.
1517 *@return the Distribution itself.
1518 */
1519 Distribution &init(T min, T max, int bkt) {
1520 params.min = min;
1521 params.max = max;
1522 params.bucket_size = bkt;
1523 params.size = (max - min) / bkt + 1;
1524 bin.init(params);
1525 setInit();
1526
1527 return *this;
1528 }
1529 };
1530
1531 /** @ingroup VStats
1532 *This has the functionality of a standard deviation built into it. Update it
1533 *every cycle, and at the end you will have the standard deviation.
1534 */
1535 template <typename T = Counter, class Bin = NoBin>
1536 class StandardDeviation : public Detail::DistBase<T, Detail::FancyStor, Bin>
1537 {
1538 private:
1539 typedef Detail::DistBase<T, Detail::DistStor, Bin> Base;
1540 typedef typename Detail::DistStor<T>::Params Params;
1541
1542 public:
1543 StandardDeviation() {
1544 bin.init(params);
1545 setInit();
1546 }
1547 };
1548
1549 /** @ingroup VStats
1550 *This also calculates standard deviations, but there is no need to
1551 *update every cycle if there is no change, the stat will update for you.
1552 */
1553 template <typename T = Counter, class Bin = NoBin>
1554 class AverageDeviation : public Detail::DistBase<T, Detail::AvgFancy, Bin>
1555 {
1556 private:
1557 typedef Detail::DistBase<T, Detail::DistStor, Bin> Base;
1558 typedef typename Detail::DistStor<T>::Params Params;
1559
1560 public:
1561 AverageDeviation() {
1562 bin.init(params);
1563 setInit();
1564 }
1565 };
1566
1567 /** @ingroup VStats
1568 *This is a vector of Distributions. (The complexity increases!). Intended usage
1569 * is for something like tracking a distribution across a vector like SMT threads.
1570 */
1571 template <typename T = Counter, class Bin = NoBin>
1572 class VectorDistribution
1573 : public Detail::VectorDistBase<T, Detail::DistStor, Bin>
1574 {
1575 private:
1576 typedef Detail::VectorDistBase<T, Detail::DistStor, Bin> Base;
1577 typedef typename Detail::DistStor<T>::Params Params;
1578
1579 public:
1580 /**
1581 *This must be called to set some data members and allocate storage space.
1582 *@param size The size of the Vector
1583 *@param min The minumum value of the Distribution
1584 *@param max The maximum value of the Distribution (NOT the size)
1585 *@param bkt The range of the bucket. I.e if min=0, max=15, and bkt=8,
1586 *then 0-7 will be bucket 0, and 8-15 will be bucket 1.
1587 *@return return the VectorDistribution itself.
1588 */
1589 VectorDistribution &init(int size, T min, T max, int bkt) {
1590 params.min = min;
1591 params.max = max;
1592 params.bucket_size = bkt;
1593 params.size = (max - min) / bkt + 1;
1594 bin.init(size, params);
1595 setInit();
1596
1597 return *this;
1598 }
1599 };
1600
1601 /** @ingroup VStats
1602 *This is a vector of Standard Deviations. Intended usage is for tracking
1603 *Standard Deviations across a vector like SMT threads.
1604 */
1605 template <typename T = Counter, class Bin = NoBin>
1606 class VectorStandardDeviation
1607 : public Detail::VectorDistBase<T, Detail::FancyStor, Bin>
1608 {
1609 private:
1610 typedef Detail::VectorDistBase<T, Detail::FancyStor, Bin> Base;
1611 typedef typename Detail::DistStor<T>::Params Params;
1612
1613 public:
1614 /** This must be called to initialize some data members and allocate
1615 * approprate storage space for the stat.
1616 *@param size The size of the Vector
1617 * @return the VectorStandardDeviation itself.
1618 */
1619 VectorStandardDeviation &init(int size) {
1620 bin.init(size, params);
1621 setInit();
1622
1623 return *this;
1624 }
1625 };
1626
1627 /** @ingroup VStats
1628 * This is a vector of Average Deviations. Intended usage is for tracking
1629 *Average Deviations across a vector like SMT threads.
1630 */
1631 template <typename T = Counter, class Bin = NoBin>
1632 class VectorAverageDeviation
1633 : public Detail::VectorDistBase<T, Detail::AvgFancy, Bin>
1634 {
1635 private:
1636 typedef Detail::VectorDistBase<T, Detail::AvgFancy, Bin> Base;
1637 typedef typename Detail::DistStor<T>::Params Params;
1638
1639 public:
1640 /** This must be called to initialize some data members and allocate
1641 * approprate storage space for the stat.
1642 *@param size The size of the Vector
1643 * @return The VectorAverageDeviation itself.
1644 */
1645 VectorAverageDeviation &init(int size) {
1646 bin.init(size, params);
1647 setInit();
1648
1649 return *this;
1650 }
1651 };
1652
1653 /** @ingroup VStats
1654 *This is a formula type. When defining it, you can just say:
1655 *Formula foo = manchu + 3 / bar;
1656 *The calculations for Formulas are all done at the end of the simulation, this
1657 *really is just a definition of how to calculate at the end.
1658 */
1659 class Formula : public Detail::VectorStat
1660 {
1661 private:
1662 /** The root of the tree which represents the Formula */
1663 Detail::NodePtr root;
1664 friend class Detail::Temp;
1665
1666 public:
1667 Formula() : VectorStat(true) { setInit(); }
1668 Formula(Detail::Temp r) : VectorStat(true) {
1669 root = r;
1670 assert(size());
1671 }
1672
1673 const Formula &operator=(Detail::Temp r) {
1674 assert(!root && "Can't change formulas");
1675 root = r;
1676 assert(size());
1677 return *this;
1678 }
1679
1680 const Formula &operator+=(Detail::Temp r) {
1681 using namespace Detail;
1682 if (root)
1683 root = NodePtr(new BinaryNode<std::plus<result_t> >(root, r));
1684 else
1685 root = r;
1686 assert(size());
1687 return *this;
1688 }
1689
1690 const rvec_t &val() const { return root->val(); }
1691 result_t total() const { return root->total(); }
1692
1693 size_t size() const {
1694 if (!root)
1695 return 0;
1696 else
1697 return root->size();
1698 }
1699 };
1700
1701 void check();
1702 void dump(std::ostream &stream);
1703
1704 inline Detail::Temp
1705 operator+(Detail::Temp l, Detail::Temp r)
1706 {
1707 using namespace Detail;
1708 return NodePtr(new BinaryNode<std::plus<result_t> >(l, r));
1709 }
1710
1711 inline Detail::Temp
1712 operator-(Detail::Temp l, Detail::Temp r)
1713 {
1714 using namespace Detail;
1715 return NodePtr(new BinaryNode<std::minus<result_t> >(l, r));
1716 }
1717
1718 inline Detail::Temp
1719 operator*(Detail::Temp l, Detail::Temp r)
1720 {
1721 using namespace Detail;
1722 return NodePtr(new BinaryNode<std::multiplies<result_t> >(l, r));
1723 }
1724
1725 inline Detail::Temp
1726 operator/(Detail::Temp l, Detail::Temp r)
1727 {
1728 using namespace Detail;
1729 return NodePtr(new BinaryNode<std::divides<result_t> >(l, r));
1730 }
1731
1732 inline Detail::Temp
1733 operator%(Detail::Temp l, Detail::Temp r)
1734 {
1735 using namespace Detail;
1736 return NodePtr(new BinaryNode<std::modulus<result_t> >(l, r));
1737 }
1738
1739 inline Detail::Temp
1740 operator-(Detail::Temp l)
1741 {
1742 using namespace Detail;
1743 return NodePtr(new UnaryNode<std::negate<result_t> >(l));
1744 }
1745
1746 template <typename T>
1747 inline Detail::Temp
1748 constant(T val)
1749 {
1750 using namespace Detail;
1751 return NodePtr(new ConstNode<T>(val));
1752 }
1753
1754 template <typename T>
1755 inline Detail::Temp
1756 functor(T &val)
1757 {
1758 using namespace Detail;
1759 return NodePtr(new FunctorNode<T>(val));
1760 }
1761
1762 template <typename T>
1763 inline Detail::Temp
1764 scalar(T &val)
1765 {
1766 using namespace Detail;
1767 return NodePtr(new ScalarNode<T>(val));
1768 }
1769
1770 inline Detail::Temp
1771 sum(Detail::Temp val)
1772 {
1773 using namespace Detail;
1774 return NodePtr(new SumNode<std::plus<result_t> >(val));
1775 }
1776
1777 extern bool PrintDescriptions;
1778
1779 } // namespace statistics
1780
1781 #endif // __STATISTICS_HH__