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