more readable formatting
[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 * Declaration of Statistics objects.
31 */
32
33 /**
34 * @todo
35 *
36 * Generalized N-dimensinal vector
37 * documentation
38 * key stats
39 * interval stats
40 * -- these both can use the same function that prints out a
41 * specific set of stats
42 * VectorStandardDeviation totals
43 * Document Namespaces
44 */
45 #ifndef __STATISTICS_HH__
46 #define __STATISTICS_HH__
47
48 #include <algorithm>
49 #include <cassert>
50 #include <cmath>
51 #include <functional>
52 #include <iosfwd>
53 #include <sstream>
54 #include <string>
55 #include <vector>
56
57 #include "base/cprintf.hh"
58 #include "base/intmath.hh"
59 #include "base/refcnt.hh"
60 #include "base/str.hh"
61 #include "sim/host.hh"
62
63 //
64 // Un-comment this to enable weirdo-stat debugging
65 //
66 // #define STAT_DEBUG
67
68
69 #ifndef NAN
70 float __nan();
71 /** Define Not a number. */
72 #define NAN (__nan())
73 /** Need to define __nan() */
74 #define __M5_NAN
75 #endif
76
77 class Callback;
78
79 /** The current simulated cycle. */
80 extern Tick curTick;
81
82 /* A namespace for all of the Statistics */
83 namespace Statistics {
84 /** All results are doubles. */
85 typedef double result_t;
86 /** A vector to hold results. */
87 typedef std::vector<result_t> rvec_t;
88
89 /**
90 * Define the storage for format flags.
91 * @todo Can probably shrink this.
92 */
93 typedef u_int32_t StatFlags;
94
95 /** Nothing extra to print. */
96 const StatFlags none = 0x00000000;
97 /** This Stat is Initialized */
98 const StatFlags init = 0x00000001;
99 /** Print this stat. */
100 const StatFlags print = 0x00000002;
101 /** Print the total. */
102 const StatFlags total = 0x00000010;
103 /** Print the percent of the total that this entry represents. */
104 const StatFlags pdf = 0x00000020;
105 /** Print the cumulative percentage of total upto this entry. */
106 const StatFlags cdf = 0x00000040;
107 /** Print the distribution. */
108 const StatFlags dist = 0x00000080;
109 /** Don't print if this is zero. */
110 const StatFlags nozero = 0x00000100;
111 /** Don't print if this is NAN */
112 const StatFlags nonan = 0x00000200;
113 /** Used for SS compatability. */
114 const StatFlags __substat = 0x80000000;
115
116 /** Mask of flags that can't be set directly */
117 const StatFlags __reserved = init | print | __substat;
118
119 enum DisplayMode
120 {
121 mode_m5,
122 mode_simplescalar,
123 mode_python
124 };
125
126 extern DisplayMode DefaultMode;
127
128 /* Contains the statistic implementation details */
129 //////////////////////////////////////////////////////////////////////
130 //
131 // Statistics Framework Base classes
132 //
133 //////////////////////////////////////////////////////////////////////
134 struct StatData
135 {
136 /** The name of the stat. */
137 std::string name;
138 /** The description of the stat. */
139 std::string desc;
140 /** The formatting flags. */
141 StatFlags flags;
142 /** The display precision. */
143 int precision;
144
145
146 /** A pointer to a prerequisite Stat. */
147 const StatData *prereq;
148
149 StatData()
150 : flags(none), precision(-1), prereq(0)
151 {}
152
153 virtual ~StatData();
154
155 /**
156 * @return true if the stat is binned.
157 */
158 virtual bool binned() const = 0;
159
160 /**
161 * Print this stat to the given ostream.
162 * @param stream The stream to print to.
163 */
164 virtual void display(std::ostream &stream, DisplayMode mode) const = 0;
165 bool dodisplay() const { return !prereq || !prereq->zero(); }
166
167 /**
168 * Reset the corresponding stat to the default state.
169 */
170 virtual void reset() = 0;
171
172 /**
173 * @return true if this stat has a value and satisfies its
174 * requirement as a prereq
175 */
176 virtual bool zero() const = 0;
177
178 /**
179 * Check that this stat has been set up properly and is ready for
180 * use
181 * @return true for success
182 */
183 virtual bool check() const = 0;
184 bool baseCheck() const;
185
186 /**
187 * Checks if the first stat's name is alphabetically less than the second.
188 * This function breaks names up at periods and considers each subname
189 * separately.
190 * @param stat1 The first stat.
191 * @param stat2 The second stat.
192 * @return stat1's name is alphabetically before stat2's
193 */
194 static bool less(StatData *stat1, StatData *stat2);
195 };
196
197 struct ScalarDataBase : public StatData
198 {
199 virtual result_t val() const = 0;
200 virtual result_t total() const = 0;
201
202 virtual void display(std::ostream &stream, DisplayMode mode) const;
203 };
204
205 template <class T>
206 class ScalarData : public ScalarDataBase
207 {
208 protected:
209 T &s;
210
211 public:
212 ScalarData(T &stat) : s(stat) {}
213
214 virtual bool binned() const { return s.binned(); }
215 virtual bool check() const { return s.check(); }
216 virtual result_t val() const { return s.val(); }
217 virtual result_t total() const { return s.total(); }
218 virtual void reset() { s.reset(); }
219 virtual bool zero() const { return s.zero(); }
220 };
221
222 struct VectorDataBase : public StatData
223 {
224 /** Names and descriptions of subfields. */
225 mutable std::vector<std::string> subnames;
226 mutable std::vector<std::string> subdescs;
227
228 virtual void display(std::ostream &stream, DisplayMode mode) const;
229
230 virtual size_t size() const = 0;
231 virtual const rvec_t &val() const = 0;
232 virtual result_t total() const = 0;
233 virtual void update()
234 {
235 if (!subnames.empty()) {
236 int s = size();
237 if (subnames.size() < s)
238 subnames.resize(s);
239
240 if (subdescs.size() < s)
241 subdescs.resize(s);
242 }
243 }
244 };
245
246 template <class T>
247 class VectorData : public VectorDataBase
248 {
249 protected:
250 T &s;
251 mutable rvec_t vec;
252
253 public:
254 VectorData(T &stat) : s(stat) {}
255
256 virtual bool binned() const { return s.binned(); }
257 virtual bool check() const { return s.check(); }
258 virtual bool zero() const { return s.zero(); }
259 virtual void reset() { s.reset(); }
260
261 virtual size_t size() const { return s.size(); }
262 virtual const rvec_t &val() const
263 {
264 s.val(vec);
265 return vec;
266 }
267 virtual result_t total() const { return s.total(); }
268 virtual void update()
269 {
270 VectorDataBase::update();
271 s.update(this);
272 }
273 };
274
275 struct DistDataData
276 {
277 result_t min_val;
278 result_t max_val;
279 result_t underflow;
280 result_t overflow;
281 rvec_t vec;
282 result_t sum;
283 result_t squares;
284 result_t samples;
285
286 int min;
287 int max;
288 int bucket_size;
289 int size;
290 bool fancy;
291 };
292
293 struct DistDataBase : public StatData
294 {
295 /** Local storage for the entry values, used for printing. */
296 DistDataData data;
297
298 virtual void display(std::ostream &stream, DisplayMode mode) const;
299 virtual void update() = 0;
300 };
301
302 template <class T>
303 class DistData : public DistDataBase
304 {
305 protected:
306 T &s;
307
308 public:
309 DistData(T &stat) : s(stat) {}
310
311 virtual bool binned() const { return s.binned(); }
312 virtual bool check() const { return s.check(); }
313 virtual void reset() { s.reset(); }
314 virtual bool zero() const { return s.zero(); }
315 virtual void update() { return s.update(this); }
316 };
317
318 struct VectorDistDataBase : public StatData
319 {
320 std::vector<DistDataData> data;
321
322 /** Names and descriptions of subfields. */
323 mutable std::vector<std::string> subnames;
324 mutable std::vector<std::string> subdescs;
325
326 /** Local storage for the entry values, used for printing. */
327 mutable rvec_t vec;
328
329 virtual size_t size() const = 0;
330 virtual void display(std::ostream &stream, DisplayMode mode) const;
331 virtual void update()
332 {
333 int s = size();
334 if (subnames.size() < s)
335 subnames.resize(s);
336
337 if (subdescs.size() < s)
338 subdescs.resize(s);
339 }
340 };
341
342 template <class T>
343 class VectorDistData : public VectorDistDataBase
344 {
345 protected:
346 T &s;
347
348 public:
349 VectorDistData(T &stat) : s(stat) {}
350
351 virtual bool binned() const { return T::bin_t::binned; }
352 virtual bool check() const { return s.check(); }
353 virtual void reset() { s.reset(); }
354 virtual size_t size() const { return s.size(); }
355 virtual bool zero() const { return s.zero(); }
356 virtual void update()
357 {
358 VectorDistDataBase::update();
359 return s.update(this);
360 }
361 };
362
363 struct Vector2dDataBase : public StatData
364 {
365 /** Names and descriptions of subfields. */
366 std::vector<std::string> subnames;
367 std::vector<std::string> subdescs;
368 std::vector<std::string> y_subnames;
369
370 /** Local storage for the entry values, used for printing. */
371 mutable rvec_t vec;
372 mutable int x;
373 mutable int y;
374
375 virtual void display(std::ostream &stream, DisplayMode mode) const;
376 virtual void update()
377 {
378 if (subnames.size() < x)
379 subnames.resize(x);
380 }
381 };
382
383 template <class T>
384 class Vector2dData : public Vector2dDataBase
385 {
386 protected:
387 T &s;
388
389 public:
390 Vector2dData(T &stat) : s(stat) {}
391
392 virtual bool binned() const { return T::bin_t::binned; }
393 virtual bool check() const { return s.check(); }
394 virtual void reset() { s.reset(); }
395 virtual bool zero() const { return s.zero(); }
396 virtual void update()
397 {
398 Vector2dDataBase::update();
399 s.update(this);
400 }
401 };
402
403
404 class DataAccess
405 {
406 protected:
407 StatData *find() const;
408 void map(StatData *data);
409
410 StatData *statData();
411 const StatData *statData() const;
412
413 void setInit();
414 void setPrint();
415 };
416
417 template <class Parent, class Child, template <class Child> class Data>
418 class Wrap : public Child
419 {
420 protected:
421 Parent &self() { return *reinterpret_cast<Parent *>(this); }
422
423 protected:
424 Data<Child> *statData()
425 {
426 StatData *__data = DataAccess::statData();
427 Data<Child> *ptr = dynamic_cast<Data<Child> *>(__data);
428 assert(ptr);
429 return ptr;
430 }
431
432 public:
433 const Data<Child> *statData() const
434 {
435 const StatData *__data = DataAccess::statData();
436 const Data<Child> *ptr = dynamic_cast<const Data<Child> *>(__data);
437 assert(ptr);
438 return ptr;
439 }
440
441 public:
442 Wrap()
443 {
444 map(new Data<Child>(*this));
445 }
446
447 /**
448 * Set the name and marks this stat to print at the end of simulation.
449 * @param name The new name.
450 * @return A reference to this stat.
451 */
452 Parent &name(const std::string &_name)
453 {
454 Data<Child> *data = statData();
455 data->name = _name;
456 setPrint();
457 return self();
458 }
459
460 /**
461 * Set the description and marks this stat to print at the end of
462 * simulation.
463 * @param desc The new description.
464 * @return A reference to this stat.
465 */
466 Parent &desc(const std::string &_desc)
467 {
468 statData()->desc = _desc;
469 return self();
470 }
471
472 /**
473 * Set the precision and marks this stat to print at the end of simulation.
474 * @param p The new precision
475 * @return A reference to this stat.
476 */
477 Parent &precision(int _precision)
478 {
479 statData()->precision = _precision;
480 return self();
481 }
482
483 /**
484 * Set the flags and marks this stat to print at the end of simulation.
485 * @param f The new flags.
486 * @return A reference to this stat.
487 */
488 Parent &flags(StatFlags _flags)
489 {
490 statData()->flags |= _flags;
491 return self();
492 }
493
494 /**
495 * Set the prerequisite stat and marks this stat to print at the end of
496 * simulation.
497 * @param prereq The prerequisite stat.
498 * @return A reference to this stat.
499 */
500 template <class T>
501 Parent &prereq(const T &prereq)
502 {
503 statData()->prereq = prereq.statData();
504 return self();
505 }
506 };
507
508 template <class Parent, class Child, template <class Child> class Data>
509 class WrapVec : public Wrap<Parent, Child, Data>
510 {
511 public:
512 // The following functions are specific to vectors. If you use them
513 // in a non vector context, you will get a nice compiler error!
514
515 /**
516 * Set the subfield name for the given index, and marks this stat to print
517 * at the end of simulation.
518 * @param index The subfield index.
519 * @param name The new name of the subfield.
520 * @return A reference to this stat.
521 */
522 Parent &subname(int index, const std::string &name)
523 {
524 std::vector<std::string> &subn = statData()->subnames;
525 if (subn.size() <= index)
526 subn.resize(index + 1);
527 subn[index] = name;
528 return self();
529 }
530
531 /**
532 * Set the subfield description for the given index and marks this stat to
533 * print at the end of simulation.
534 * @param index The subfield index.
535 * @param desc The new description of the subfield
536 * @return A reference to this stat.
537 */
538 Parent &subdesc(int index, const std::string &desc)
539 {
540 std::vector<std::string> &subd = statData()->subdescs;
541 if (subd.size() <= index)
542 subd.resize(index + 1);
543 subd[index] = desc;
544
545 return self();
546 }
547
548 };
549
550 template <class Parent, class Child, template <class Child> class Data>
551 class WrapVec2d : public WrapVec<Parent, Child, Data>
552 {
553 public:
554 /**
555 * @warning This makes the assumption that if you're gonna subnames a 2d
556 * vector, you're subnaming across all y
557 */
558 Parent &ysubnames(const char **names)
559 {
560 Data<Child> *data = statData();
561 data->y_subnames.resize(y);
562 for (int i = 0; i < y; ++i)
563 data->y_subnames[i] = names[i];
564 return self();
565 }
566 Parent &ysubname(int index, const std::string subname)
567 {
568 Data<Child> *data = statData();
569 assert(i < y);
570 data->y_subnames.resize(y);
571 data->y_subnames[i] = subname.c_str();
572 return self();
573 }
574 };
575
576 //////////////////////////////////////////////////////////////////////
577 //
578 // Simple Statistics
579 //
580 //////////////////////////////////////////////////////////////////////
581
582 /**
583 * Templatized storage and interface for a simple scalar stat.
584 */
585 template <typename T>
586 struct StatStor
587 {
588 public:
589 /** The paramaters for this storage type, none for a scalar. */
590 struct Params { };
591
592 private:
593 /** The statistic value. */
594 T data;
595 static T &Null()
596 {
597 static T __T = T();
598 return __T;
599 }
600
601 public:
602 /**
603 * Builds this storage element and calls the base constructor of the
604 * datatype.
605 */
606 StatStor(const Params &) : data(Null()) {}
607
608 /**
609 * The the stat to the given value.
610 * @param val The new value.
611 * @param p The paramters of this storage type.
612 */
613 void set(T val, const Params &p) { data = val; }
614 /**
615 * Increment the stat by the given value.
616 * @param val The new value.
617 * @param p The paramters of this storage type.
618 */
619 void inc(T val, const Params &p) { data += val; }
620 /**
621 * Decrement the stat by the given value.
622 * @param val The new value.
623 * @param p The paramters of this storage type.
624 */
625 void dec(T val, const Params &p) { data -= val; }
626 /**
627 * Return the value of this stat as a result type.
628 * @param p The parameters of this storage type.
629 * @return The value of this stat.
630 */
631 result_t val(const Params &p) const { return (result_t)data; }
632 /**
633 * Return the value of this stat as its base type.
634 * @param p The params of this storage type.
635 * @return The value of this stat.
636 */
637 T value(const Params &p) const { return data; }
638 /**
639 * Reset stat value to default
640 */
641 void reset() { data = Null(); }
642
643 /**
644 * @return true if zero value
645 */
646 bool zero() const { return data == Null(); }
647 };
648
649 /**
650 * Templatized storage and interface to a per-cycle average stat. This keeps
651 * a current count and updates a total (count * cycles) when this count
652 * changes. This allows the quick calculation of a per cycle count of the item
653 * being watched. This is good for keeping track of residencies in structures
654 * among other things.
655 * @todo add lateny to the stat and fix binning.
656 */
657 template <typename T>
658 struct AvgStor
659 {
660 public:
661 /** The paramaters for this storage type */
662 struct Params
663 {
664 /**
665 * The current count. We stash this here because the current
666 * value is not a binned value.
667 */
668 T current;
669 };
670
671 private:
672 /** The total count for all cycles. */
673 mutable result_t total;
674 /** The cycle that current last changed. */
675 mutable Tick last;
676
677 public:
678 /**
679 * Build and initializes this stat storage.
680 */
681 AvgStor(Params &p) : total(0), last(0) { p.current = T(); }
682
683 /**
684 * Set the current count to the one provided, update the total and last
685 * set values.
686 * @param val The new count.
687 * @param p The parameters for this storage.
688 */
689 void set(T val, Params &p) {
690 total += p.current * (curTick - last);
691 last = curTick;
692 p.current = val;
693 }
694
695 /**
696 * Increment the current count by the provided value, calls set.
697 * @param val The amount to increment.
698 * @param p The parameters for this storage.
699 */
700 void inc(T val, Params &p) { set(p.current + val, p); }
701
702 /**
703 * Deccrement the current count by the provided value, calls set.
704 * @param val The amount to decrement.
705 * @param p The parameters for this storage.
706 */
707 void dec(T val, Params &p) { set(p.current - val, p); }
708
709 /**
710 * Return the current average.
711 * @param p The parameters for this storage.
712 * @return The current average.
713 */
714 result_t val(const Params &p) const {
715 total += p.current * (curTick - last);
716 last = curTick;
717 return (result_t)(total + p.current) / (result_t)(curTick + 1);
718 }
719
720 /**
721 * Return the current count.
722 * @param p The parameters for this storage.
723 * @return The current count.
724 */
725 T value(const Params &p) const { return p.current; }
726
727 /**
728 * Reset stat value to default
729 */
730 void reset()
731 {
732 total = 0;
733 last = curTick;
734 }
735
736 /**
737 * @return true if zero value
738 */
739 bool zero() const { return total == 0.0; }
740 };
741
742 /**
743 * Implementation of a scalar stat. The type of stat is determined by the
744 * Storage template. The storage for this stat is held within the Bin class.
745 * This allows for breaking down statistics across multiple bins easily.
746 */
747 template <typename T, template <typename T> class Storage, class Bin>
748 class ScalarBase : public DataAccess
749 {
750 protected:
751 /** Define the type of the storage class. */
752 typedef Storage<T> storage_t;
753 /** Define the params of the storage class. */
754 typedef typename storage_t::Params params_t;
755 /** Define the bin type. */
756 typedef typename Bin::Bin<storage_t> bin_t;
757
758 protected:
759 /** The bin of this stat. */
760 bin_t bin;
761 /** The parameters for this stat. */
762 params_t params;
763
764 protected:
765 /**
766 * Retrieve the storage from the bin.
767 * @return The storage object for this stat.
768 */
769 storage_t *data() { return bin.data(params); }
770 /**
771 * Retrieve a const pointer to the storage from the bin.
772 * @return A const pointer to the storage object for this stat.
773 */
774 const storage_t *data() const
775 {
776 bin_t *_bin = const_cast<bin_t *>(&bin);
777 params_t *_params = const_cast<params_t *>(&params);
778 return _bin->data(*_params);
779 }
780
781 protected:
782 /**
783 * Copy constructor, copies are not allowed.
784 */
785 ScalarBase(const ScalarBase &stat);
786 /**
787 * Can't copy stats.
788 */
789 const ScalarBase &operator=(const ScalarBase &);
790
791 public:
792 /**
793 * Return the current value of this stat as its base type.
794 * @return The current value.
795 */
796 T value() const { return data()->value(params); }
797
798 public:
799 /**
800 * Create and initialize this stat, register it with the database.
801 */
802 ScalarBase()
803 {
804 bin.init(params);
805 }
806
807 public:
808 // Common operators for stats
809 /**
810 * Increment the stat by 1. This calls the associated storage object inc
811 * function.
812 */
813 void operator++() { data()->inc(1, params); }
814 /**
815 * Decrement the stat by 1. This calls the associated storage object dec
816 * function.
817 */
818 void operator--() { data()->dec(1, params); }
819
820 /** Increment the stat by 1. */
821 void operator++(int) { ++*this; }
822 /** Decrement the stat by 1. */
823 void operator--(int) { --*this; }
824
825 /**
826 * Set the data value to the given value. This calls the associated storage
827 * object set function.
828 * @param v The new value.
829 */
830 template <typename U>
831 void operator=(const U& v) { data()->set(v, params); }
832
833 /**
834 * Increment the stat by the given value. This calls the associated
835 * storage object inc function.
836 * @param v The value to add.
837 */
838 template <typename U>
839 void operator+=(const U& v) { data()->inc(v, params); }
840
841 /**
842 * Decrement the stat by the given value. This calls the associated
843 * storage object dec function.
844 * @param v The value to substract.
845 */
846 template <typename U>
847 void operator-=(const U& v) { data()->dec(v, params); }
848
849 /**
850 * Return the number of elements, always 1 for a scalar.
851 * @return 1.
852 */
853 size_t size() const { return 1; }
854 /**
855 * Return true if stat is binned.
856 *@return True is stat is binned.
857 */
858 bool binned() const { return bin_t::binned; }
859
860 bool check() const { return bin.initialized(); }
861
862 /**
863 * Reset stat value to default
864 */
865 void reset() { bin.reset(); }
866
867 result_t val() { return data()->val(params); }
868
869 result_t total() { return val(); }
870
871 bool zero() { return val() == 0.0; }
872 };
873
874 //////////////////////////////////////////////////////////////////////
875 //
876 // Vector Statistics
877 //
878 //////////////////////////////////////////////////////////////////////
879 template <typename T, template <typename T> class Storage, class Bin>
880 class ScalarProxy;
881
882 /**
883 * Implementation of a vector of stats. The type of stat is determined by the
884 * Storage class. @sa ScalarBase
885 */
886 template <typename T, template <typename T> class Storage, class Bin>
887 class VectorBase : public DataAccess
888 {
889 protected:
890 /** Define the type of the storage class. */
891 typedef Storage<T> storage_t;
892 /** Define the params of the storage class. */
893 typedef typename storage_t::Params params_t;
894 /** Define the bin type. */
895 typedef typename Bin::VectorBin<storage_t> bin_t;
896
897 protected:
898 /** The bin of this stat. */
899 bin_t bin;
900 /** The parameters for this stat. */
901 params_t params;
902
903 protected:
904 /**
905 * Retrieve the storage from the bin for the given index.
906 * @param index The vector index to access.
907 * @return The storage object at the given index.
908 */
909 storage_t *data(int index) { return bin.data(index, params); }
910 /**
911 * Retrieve a const pointer to the storage from the bin
912 * for the given index.
913 * @param index The vector index to access.
914 * @return A const pointer to the storage object at the given index.
915 */
916 const storage_t *data(int index) const
917 {
918 bin_t *_bin = const_cast<bin_t *>(&bin);
919 params_t *_params = const_cast<params_t *>(&params);
920 return _bin->data(index, *_params);
921 }
922
923 protected:
924 // Copying stats is not allowed
925 /** Copying stats isn't allowed. */
926 VectorBase(const VectorBase &stat);
927 /** Copying stats isn't allowed. */
928 const VectorBase &operator=(const VectorBase &);
929
930 public:
931 /**
932 * Copy the values to a local vector and return a reference to it.
933 * @return A reference to a vector of the stat values.
934 */
935 void val(rvec_t &vec) const
936 {
937 vec.resize(size());
938 for (int i = 0; i < size(); ++i)
939 vec[i] = data(i)->val(params);
940 }
941
942 /**
943 * @return True is stat is binned.
944 */
945 bool binned() const { return bin_t::binned; }
946
947 /**
948 * Return a total of all entries in this vector.
949 * @return The total of all vector entries.
950 */
951 result_t total() const {
952 result_t total = 0.0;
953 for (int i = 0; i < size(); ++i)
954 total += data(i)->val(params);
955 return total;
956 }
957
958 /**
959 * @return the number of elements in this vector.
960 */
961 size_t size() const { return bin.size(); }
962
963 bool zero() const
964 {
965 for (int i = 0; i < size(); ++i)
966 if (data(i)->zero())
967 return true;
968 return false;
969 }
970
971 bool check() const { return bin.initialized(); }
972 void reset() { bin.reset(); }
973
974 public:
975 VectorBase() {}
976
977 /** Friend this class with the associated scalar proxy. */
978 friend class ScalarProxy<T, Storage, Bin>;
979
980 /**
981 * Return a reference (ScalarProxy) to the stat at the given index.
982 * @param index The vector index to access.
983 * @return A reference of the stat.
984 */
985 ScalarProxy<T, Storage, Bin> operator[](int index);
986
987 void update(StatData *data) {}
988 };
989
990 /**
991 * A proxy class to access the stat at a given index in a VectorBase stat.
992 * Behaves like a ScalarBase.
993 */
994 template <typename T, template <typename T> class Storage, class Bin>
995 class ScalarProxy
996 {
997 protected:
998 /** Define the type of the storage class. */
999 typedef Storage<T> storage_t;
1000 /** Define the params of the storage class. */
1001 typedef typename storage_t::Params params_t;
1002 /** Define the bin type. */
1003 typedef typename Bin::VectorBin<storage_t> bin_t;
1004
1005 private:
1006 /** Pointer to the bin in the parent VectorBase. */
1007 bin_t *bin;
1008 /** Pointer to the params in the parent VectorBase. */
1009 params_t *params;
1010 /** The index to access in the parent VectorBase. */
1011 int index;
1012
1013 protected:
1014 /**
1015 * Retrieve the storage from the bin.
1016 * @return The storage from the bin for this stat.
1017 */
1018 storage_t *data() { return bin->data(index, *params); }
1019 /**
1020 * Retrieve a const pointer to the storage from the bin.
1021 * @return A const pointer to the storage for this stat.
1022 */
1023 const storage_t *data() const
1024 {
1025 bin_t *_bin = const_cast<bin_t *>(bin);
1026 params_t *_params = const_cast<params_t *>(params);
1027 return _bin->data(index, *_params);
1028 }
1029
1030 public:
1031 /**
1032 * Return the current value of this statas a result type.
1033 * @return The current value.
1034 */
1035 result_t val() const { return data()->val(*params); }
1036 /**
1037 * Return the current value of this stat as its base type.
1038 * @return The current value.
1039 */
1040 T value() const { return data()->value(*params); }
1041
1042 public:
1043 /**
1044 * Create and initialize this proxy, do not register it with the database.
1045 * @param b The bin to use.
1046 * @param p The params to use.
1047 * @param i The index to access.
1048 */
1049 ScalarProxy(bin_t &b, params_t &p, int i)
1050 : bin(&b), params(&p), index(i) {}
1051 /**
1052 * Create a copy of the provided ScalarProxy.
1053 * @param sp The proxy to copy.
1054 */
1055 ScalarProxy(const ScalarProxy &sp)
1056 : bin(sp.bin), params(sp.params), index(sp.index) {}
1057 /**
1058 * Set this proxy equal to the provided one.
1059 * @param sp The proxy to copy.
1060 * @return A reference to this proxy.
1061 */
1062 const ScalarProxy &operator=(const ScalarProxy &sp) {
1063 bin = sp.bin;
1064 params = sp.params;
1065 index = sp.index;
1066 return *this;
1067 }
1068
1069 public:
1070 // Common operators for stats
1071 /**
1072 * Increment the stat by 1. This calls the associated storage object inc
1073 * function.
1074 */
1075 void operator++() { data()->inc(1, *params); }
1076 /**
1077 * Decrement the stat by 1. This calls the associated storage object dec
1078 * function.
1079 */
1080 void operator--() { data()->dec(1, *params); }
1081
1082 /** Increment the stat by 1. */
1083 void operator++(int) { ++*this; }
1084 /** Decrement the stat by 1. */
1085 void operator--(int) { --*this; }
1086
1087 /**
1088 * Set the data value to the given value. This calls the associated storage
1089 * object set function.
1090 * @param v The new value.
1091 */
1092 template <typename U>
1093 void operator=(const U& v) { data()->set(v, *params); }
1094
1095 /**
1096 * Increment the stat by the given value. This calls the associated
1097 * storage object inc function.
1098 * @param v The value to add.
1099 */
1100 template <typename U>
1101 void operator+=(const U& v) { data()->inc(v, *params); }
1102
1103 /**
1104 * Decrement the stat by the given value. This calls the associated
1105 * storage object dec function.
1106 * @param v The value to substract.
1107 */
1108 template <typename U>
1109 void operator-=(const U& v) { data()->dec(v, *params); }
1110
1111 /**
1112 * Return the number of elements, always 1 for a scalar.
1113 * @return 1.
1114 */
1115 size_t size() const { return 1; }
1116
1117 /**
1118 * Return true if stat is binned.
1119 *@return false since Proxies aren't printed/binned
1120 */
1121 bool binned() const { return false; }
1122
1123 /**
1124 * This stat has no state. Nothing to reset
1125 */
1126 void reset() { }
1127 };
1128
1129 template <typename T, template <typename T> class Storage, class Bin>
1130 inline ScalarProxy<T, Storage, Bin>
1131 VectorBase<T, Storage, Bin>::operator[](int index)
1132 {
1133 assert (index >= 0 && index < size());
1134 return ScalarProxy<T, Storage, Bin>(bin, params, index);
1135 }
1136
1137 template <typename T, template <typename T> class Storage, class Bin>
1138 class VectorProxy;
1139
1140 template <typename T, template <typename T> class Storage, class Bin>
1141 class Vector2dBase : public DataAccess
1142 {
1143 protected:
1144 typedef Storage<T> storage_t;
1145 typedef typename storage_t::Params params_t;
1146
1147 public:
1148 typedef typename Bin::VectorBin<storage_t> bin_t;
1149
1150 protected:
1151 size_t x;
1152 size_t y;
1153 bin_t bin;
1154 params_t params;
1155
1156 protected:
1157 storage_t *data(int index) { return bin.data(index, params); }
1158 const storage_t *data(int index) const
1159 {
1160 bin_t *_bin = const_cast<bin_t *>(&bin);
1161 params_t *_params = const_cast<params_t *>(&params);
1162 return _bin->data(index, *_params);
1163 }
1164
1165 protected:
1166 // Copying stats is not allowed
1167 Vector2dBase(const Vector2dBase &stat);
1168 const Vector2dBase &operator=(const Vector2dBase &);
1169
1170 public:
1171 Vector2dBase() {}
1172
1173 void update(Vector2dDataBase *data)
1174 {
1175 int size = this->size();
1176 data->vec.resize(size);
1177 for (int i = 0; i < size; ++i)
1178 data->vec[i] = this->data(i)->val(params);
1179 }
1180
1181 std::string ysubname(int i) const { return (*y_subnames)[i]; }
1182
1183 friend class VectorProxy<T, Storage, Bin>;
1184 VectorProxy<T, Storage, Bin> operator[](int index);
1185
1186 size_t size() const { return bin.size(); }
1187 bool zero() const { return data(0)->value(params) == 0.0; }
1188
1189 /**
1190 * Reset stat value to default
1191 */
1192 void reset() { bin.reset(); }
1193
1194 bool check() { return bin.initialized(); }
1195 };
1196
1197 template <typename T, template <typename T> class Storage, class Bin>
1198 class VectorProxy
1199 {
1200 protected:
1201 typedef Storage<T> storage_t;
1202 typedef typename storage_t::Params params_t;
1203 typedef typename Bin::VectorBin<storage_t> bin_t;
1204
1205 private:
1206 bin_t *bin;
1207 params_t *params;
1208 int offset;
1209 int len;
1210
1211 private:
1212 mutable rvec_t *vec;
1213
1214 storage_t *data(int index) {
1215 assert(index < len);
1216 return bin->data(offset + index, *params);
1217 }
1218
1219 const storage_t *data(int index) const {
1220 bin_t *_bin = const_cast<bin_t *>(bin);
1221 params_t *_params = const_cast<params_t *>(params);
1222 return _bin->data(offset + index, *_params);
1223 }
1224
1225 public:
1226 const rvec_t &val() const {
1227 if (vec)
1228 vec->resize(size());
1229 else
1230 vec = new rvec_t(size());
1231
1232 for (int i = 0; i < size(); ++i)
1233 (*vec)[i] = data(i)->val(*params);
1234
1235 return *vec;
1236 }
1237
1238 result_t total() const {
1239 result_t total = 0.0;
1240 for (int i = 0; i < size(); ++i)
1241 total += data(i)->val(*params);
1242 return total;
1243 }
1244
1245 public:
1246 VectorProxy(bin_t &b, params_t &p, int o, int l)
1247 : bin(&b), params(&p), offset(o), len(l), vec(NULL)
1248 { }
1249 VectorProxy(const VectorProxy &sp)
1250 : bin(sp.bin), params(sp.params), offset(sp.offset), len(sp.len),
1251 vec(NULL)
1252 { }
1253 ~VectorProxy() {
1254 if (vec)
1255 delete vec;
1256 }
1257
1258 const VectorProxy &operator=(const VectorProxy &sp)
1259 {
1260 bin = sp.bin;
1261 params = sp.params;
1262 offset = sp.offset;
1263 len = sp.len;
1264 if (vec)
1265 delete vec;
1266 vec = NULL;
1267 return *this;
1268 }
1269
1270 ScalarProxy<T, Storage, Bin> operator[](int index)
1271 {
1272 assert (index >= 0 && index < size());
1273 return ScalarProxy<T, Storage, Bin>(*bin, *params, offset + index);
1274 }
1275
1276 size_t size() const { return len; }
1277
1278 /**
1279 * Return true if stat is binned.
1280 *@return false since Proxies aren't printed/binned
1281 */
1282 bool binned() const { return false; }
1283
1284 /**
1285 * This stat has no state. Nothing to reset.
1286 */
1287 void reset() { }
1288 };
1289
1290 template <typename T, template <typename T> class Storage, class Bin>
1291 inline VectorProxy<T, Storage, Bin>
1292 Vector2dBase<T, Storage, Bin>::operator[](int index)
1293 {
1294 int offset = index * y;
1295 assert (index >= 0 && offset < size());
1296 return VectorProxy<T, Storage, Bin>(bin, params, offset, y);
1297 }
1298
1299 //////////////////////////////////////////////////////////////////////
1300 //
1301 // Non formula statistics
1302 //
1303 //////////////////////////////////////////////////////////////////////
1304
1305 /**
1306 * Templatized storage and interface for a distrbution stat.
1307 */
1308 template <typename T>
1309 struct DistStor
1310 {
1311 public:
1312 /** The parameters for a distribution stat. */
1313 struct Params
1314 {
1315 /** The minimum value to track. */
1316 int min;
1317 /** The maximum value to track. */
1318 int max;
1319 /** The number of entries in each bucket. */
1320 int bucket_size;
1321 /** The number of buckets. Equal to (max-min)/bucket_size. */
1322 int size;
1323 };
1324 enum { fancy = false };
1325
1326 private:
1327 /** The smallest value sampled. */
1328 T min_val;
1329 /** The largest value sampled. */
1330 T max_val;
1331 /** The number of values sampled less than min. */
1332 T underflow;
1333 /** The number of values sampled more than max. */
1334 T overflow;
1335 /** The current sum. */
1336 T sum;
1337 /** The sum of squares. */
1338 T squares;
1339 /** The number of samples. */
1340 int samples;
1341 /** Counter for each bucket. */
1342 std::vector<T> vec;
1343
1344 public:
1345 /**
1346 * Construct this storage with the supplied params.
1347 * @param params The parameters.
1348 */
1349 DistStor(const Params &params)
1350 : min_val(INT_MAX), max_val(INT_MIN), underflow(0), overflow(0),
1351 sum(T()), squares(T()), samples(0), vec(params.size)
1352 {
1353 reset();
1354 }
1355
1356 /**
1357 * Add a value to the distribution for the given number of times.
1358 * @param val The value to add.
1359 * @param number The number of times to add the value.
1360 * @param params The paramters of the distribution.
1361 */
1362 void sample(T val, int number, const Params &params)
1363 {
1364 if (val < params.min)
1365 underflow += number;
1366 else if (val > params.max)
1367 overflow += number;
1368 else {
1369 int index = (val - params.min) / params.bucket_size;
1370 assert(index < size(params));
1371 vec[index] += number;
1372 }
1373
1374 if (val < min_val)
1375 min_val = val;
1376
1377 if (val > max_val)
1378 max_val = val;
1379
1380 T sample = val * number;
1381 sum += sample;
1382 squares += sample * sample;
1383 samples += number;
1384 }
1385
1386 /**
1387 * Return the number of buckets in this distribution.
1388 * @return the number of buckets.
1389 * @todo Is it faster to return the size from the parameters?
1390 */
1391 size_t size(const Params &) const { return vec.size(); }
1392
1393 /**
1394 * Returns true if any calls to sample have been made.
1395 * @param params The paramters of the distribution.
1396 * @return True if any values have been sampled.
1397 */
1398 bool zero(const Params &params) const
1399 {
1400 return samples == 0;
1401 }
1402
1403 void update(DistDataData *data, const Params &params)
1404 {
1405 data->min = params.min;
1406 data->max = params.max;
1407 data->bucket_size = params.bucket_size;
1408 data->size = params.size;
1409
1410 data->min_val = (min_val == INT_MAX) ? 0 : min_val;
1411 data->max_val = (max_val == INT_MIN) ? 0 : max_val;
1412 data->underflow = underflow;
1413 data->overflow = overflow;
1414 data->vec.resize(params.size);
1415 for (int i = 0; i < params.size; ++i)
1416 data->vec[i] = vec[i];
1417
1418 data->sum = sum;
1419 data->squares = squares;
1420 data->samples = samples;
1421 }
1422
1423 /**
1424 * Reset stat value to default
1425 */
1426 void reset()
1427 {
1428 min_val = INT_MAX;
1429 max_val = INT_MIN;
1430 underflow = 0;
1431 overflow = 0;
1432
1433 int size = vec.size();
1434 for (int i = 0; i < size; ++i)
1435 vec[i] = T();
1436
1437 sum = T();
1438 squares = T();
1439 samples = T();
1440 }
1441 };
1442
1443 /**
1444 * Templatized storage and interface for a distribution that calculates mean
1445 * and variance.
1446 */
1447 template <typename T>
1448 struct FancyStor
1449 {
1450 public:
1451 /**
1452 * No paramters for this storage.
1453 */
1454 struct Params {};
1455 enum { fancy = true };
1456
1457 private:
1458 /** The current sum. */
1459 T sum;
1460 /** The sum of squares. */
1461 T squares;
1462 /** The number of samples. */
1463 int samples;
1464
1465 public:
1466 /**
1467 * Create and initialize this storage.
1468 */
1469 FancyStor(const Params &) : sum(T()), squares(T()), samples(0) {}
1470
1471 /**
1472 * Add a value the given number of times to this running average.
1473 * Update the running sum and sum of squares, increment the number of
1474 * values seen by the given number.
1475 * @param val The value to add.
1476 * @param number The number of times to add the value.
1477 * @param p The parameters of this stat.
1478 */
1479 void sample(T val, int number, const Params &p)
1480 {
1481 T value = val * number;
1482 sum += value;
1483 squares += value * value;
1484 samples += number;
1485 }
1486
1487 void update(DistDataData *data, const Params &params)
1488 {
1489 data->sum = sum;
1490 data->squares = squares;
1491 data->samples = samples;
1492 }
1493
1494 /**
1495 * Return the number of entries in this stat, 1
1496 * @return 1.
1497 */
1498 size_t size(const Params &) const { return 1; }
1499
1500 /**
1501 * Return true if no samples have been added.
1502 * @return True if no samples have been added.
1503 */
1504 bool zero(const Params &) const { return samples == 0; }
1505
1506 /**
1507 * Reset stat value to default
1508 */
1509 void reset()
1510 {
1511 sum = T();
1512 squares = T();
1513 samples = 0;
1514 }
1515 };
1516
1517 /**
1518 * Templatized storage for distribution that calculates per cycle mean and
1519 * variance.
1520 */
1521 template <typename T>
1522 struct AvgFancy
1523 {
1524 public:
1525 /** No parameters for this storage. */
1526 struct Params {};
1527 enum { fancy = true };
1528
1529 private:
1530 /** Current total. */
1531 T sum;
1532 /** Current sum of squares. */
1533 T squares;
1534
1535 public:
1536 /**
1537 * Create and initialize this storage.
1538 */
1539 AvgFancy(const Params &) : sum(T()), squares(T()) {}
1540
1541 /**
1542 * Add a value to the distribution for the given number of times.
1543 * Update the running sum and sum of squares.
1544 * @param val The value to add.
1545 * @param number The number of times to add the value.
1546 * @param p The paramters of the distribution.
1547 */
1548 void sample(T val, int number, const Params& p)
1549 {
1550 T value = val * number;
1551 sum += value;
1552 squares += value * value;
1553 }
1554
1555 void update(DistDataData *data, const Params &params)
1556 {
1557 data->sum = sum;
1558 data->squares = squares;
1559 data->samples = curTick;
1560 }
1561
1562 /**
1563 * Return the number of entries, in this case 1.
1564 * @return 1.
1565 */
1566 size_t size(const Params &params) const { return 1; }
1567 /**
1568 * Return true if no samples have been added.
1569 * @return True if the sum is zero.
1570 */
1571 bool zero(const Params &params) const { return sum == 0; }
1572 /**
1573 * Reset stat value to default
1574 */
1575 void reset()
1576 {
1577 sum = T();
1578 squares = T();
1579 }
1580 };
1581
1582 /**
1583 * Implementation of a distribution stat. The type of distribution is
1584 * determined by the Storage template. @sa ScalarBase
1585 */
1586 template <typename T, template <typename T> class Storage, class Bin>
1587 class DistBase : public DataAccess
1588 {
1589 protected:
1590 /** Define the type of the storage class. */
1591 typedef Storage<T> storage_t;
1592 /** Define the params of the storage class. */
1593 typedef typename storage_t::Params params_t;
1594 /** Define the bin type. */
1595 typedef typename Bin::Bin<storage_t> bin_t;
1596
1597 protected:
1598 /** The bin of this stat. */
1599 bin_t bin;
1600 /** The parameters for this stat. */
1601 params_t params;
1602
1603 protected:
1604 /**
1605 * Retrieve the storage from the bin.
1606 * @return The storage object for this stat.
1607 */
1608 storage_t *data() { return bin.data(params); }
1609 /**
1610 * Retrieve a const pointer to the storage from the bin.
1611 * @return A const pointer to the storage object for this stat.
1612 */
1613 const storage_t *data() const
1614 {
1615 bin_t *_bin = const_cast<bin_t *>(&bin);
1616 params_t *_params = const_cast<params_t *>(&params);
1617 return _bin->data(*_params);
1618 }
1619
1620 protected:
1621 // Copying stats is not allowed
1622 /** Copies are not allowed. */
1623 DistBase(const DistBase &stat);
1624 /** Copies are not allowed. */
1625 const DistBase &operator=(const DistBase &);
1626
1627 public:
1628 DistBase() { }
1629
1630 /**
1631 * Add a value to the distribtion n times. Calls sample on the storage
1632 * class.
1633 * @param v The value to add.
1634 * @param n The number of times to add it, defaults to 1.
1635 */
1636 template <typename U>
1637 void sample(const U& v, int n = 1) { data()->sample(v, n, params); }
1638
1639 /**
1640 * Return the number of entries in this stat.
1641 * @return The number of entries.
1642 */
1643 size_t size() const { return data()->size(params); }
1644 /**
1645 * Return true if no samples have been added.
1646 * @return True if there haven't been any samples.
1647 */
1648 bool zero() const { return data()->zero(params); }
1649
1650 void update(DistDataBase *base)
1651 {
1652 base->data.fancy = storage_t::fancy;
1653 data()->update(&(base->data), params);
1654 }
1655 /**
1656 * @return True is stat is binned.
1657 */
1658 bool binned() const { return bin_t::binned; }
1659 /**
1660 * Reset stat value to default
1661 */
1662 void reset()
1663 {
1664 bin.reset();
1665 }
1666
1667 bool check() { return bin.initialized(); }
1668 };
1669
1670 template <typename T, template <typename T> class Storage, class Bin>
1671 class DistProxy;
1672
1673 template <typename T, template <typename T> class Storage, class Bin>
1674 class VectorDistBase : public DataAccess
1675 {
1676 protected:
1677 typedef Storage<T> storage_t;
1678 typedef typename storage_t::Params params_t;
1679
1680 public:
1681 typedef typename Bin::VectorBin<storage_t> bin_t;
1682
1683 protected:
1684 bin_t bin;
1685 params_t params;
1686
1687 protected:
1688 storage_t *data(int index) { return bin.data(index, params); }
1689 const storage_t *data(int index) const
1690 {
1691 bin_t *_bin = const_cast<bin_t *>(&bin);
1692 params_t *_params = const_cast<params_t *>(&params);
1693 return _bin->data(index, *_params);
1694 }
1695
1696 protected:
1697 // Copying stats is not allowed
1698 VectorDistBase(const VectorDistBase &stat);
1699 const VectorDistBase &operator=(const VectorDistBase &);
1700
1701 public:
1702 VectorDistBase() {}
1703
1704 friend class DistProxy<T, Storage, Bin>;
1705 DistProxy<T, Storage, Bin> operator[](int index);
1706 const DistProxy<T, Storage, Bin> operator[](int index) const;
1707
1708 size_t size() const { return bin.size(); }
1709 bool zero() const { return false; }
1710 /**
1711 * Return true if stat is binned.
1712 *@return True is stat is binned.
1713 */
1714 bool binned() const { return bin_t::binned; }
1715 /**
1716 * Reset stat value to default
1717 */
1718 void reset() { bin.reset(); }
1719
1720 bool check() { return bin.initialized(); }
1721 void update(VectorDistDataBase *base)
1722 {
1723 int size = this->size();
1724 base->data.resize(size);
1725 for (int i = 0; i < size; ++i) {
1726 base->data[i].fancy = storage_t::fancy;
1727 data(i)->update(&(base->data[i]), params);
1728 }
1729 }
1730 };
1731
1732 template <typename T, template <typename T> class Storage, class Bin>
1733 class DistProxy
1734 {
1735 protected:
1736 typedef Storage<T> storage_t;
1737 typedef typename storage_t::Params params_t;
1738 typedef typename Bin::Bin<storage_t> bin_t;
1739 typedef VectorDistBase<T, Storage, Bin> base_t;
1740
1741 private:
1742 union {
1743 base_t *stat;
1744 const base_t *cstat;
1745 };
1746 int index;
1747
1748 protected:
1749 storage_t *data() { return stat->data(index); }
1750 const storage_t *data() const { return cstat->data(index); }
1751
1752 public:
1753 DistProxy(const VectorDistBase<T, Storage, Bin> &s, int i)
1754 : cstat(&s), index(i) {}
1755 DistProxy(const DistProxy &sp)
1756 : cstat(sp.cstat), index(sp.index) {}
1757 const DistProxy &operator=(const DistProxy &sp) {
1758 cstat = sp.cstat; index = sp.index; return *this;
1759 }
1760
1761 public:
1762 template <typename U>
1763 void sample(const U& v, int n = 1) { data()->sample(v, n, cstat->params); }
1764
1765 size_t size() const { return 1; }
1766 bool zero() const { return data()->zero(cstat->params); }
1767 /**
1768 * Return true if stat is binned.
1769 *@return false since Proxies are not binned/printed.
1770 */
1771 bool binned() const { return false; }
1772 /**
1773 * Proxy has no state. Nothing to reset.
1774 */
1775 void reset() { }
1776 };
1777
1778 template <typename T, template <typename T> class Storage, class Bin>
1779 inline DistProxy<T, Storage, Bin>
1780 VectorDistBase<T, Storage, Bin>::operator[](int index)
1781 {
1782 assert (index >= 0 && index < size());
1783 return DistProxy<T, Storage, Bin>(*this, index);
1784 }
1785
1786 template <typename T, template <typename T> class Storage, class Bin>
1787 inline const DistProxy<T, Storage, Bin>
1788 VectorDistBase<T, Storage, Bin>::operator[](int index) const
1789 {
1790 assert (index >= 0 && index < size());
1791 return DistProxy<T, Storage, Bin>(*this, index);
1792 }
1793
1794 #if 0
1795 template <typename T, template <typename T> class Storage, class Bin>
1796 result_t
1797 VectorDistBase<T, Storage, Bin>::total(int index) const
1798 {
1799 int total = 0;
1800 for (int i=0; i < x_size(); ++i) {
1801 total += data(i)->val(*params);
1802 }
1803 }
1804 #endif
1805
1806 //////////////////////////////////////////////////////////////////////
1807 //
1808 // Formula Details
1809 //
1810 //////////////////////////////////////////////////////////////////////
1811
1812 /**
1813 * Base class for formula statistic node. These nodes are used to build a tree
1814 * that represents the formula.
1815 */
1816 class Node : public RefCounted
1817 {
1818 public:
1819 /**
1820 * Return the number of nodes in the subtree starting at this node.
1821 * @return the number of nodes in this subtree.
1822 */
1823 virtual size_t size() const = 0;
1824 /**
1825 * Return the result vector of this subtree.
1826 * @return The result vector of this subtree.
1827 */
1828 virtual const rvec_t &val() const = 0;
1829 /**
1830 * Return the total of the result vector.
1831 * @return The total of the result vector.
1832 */
1833 virtual result_t total() const = 0;
1834 /**
1835 * Return true if stat is binned.
1836 *@return True is stat is binned.
1837 */
1838 virtual bool binned() const = 0;
1839 };
1840
1841 /** Reference counting pointer to a function Node. */
1842 typedef RefCountingPtr<Node> NodePtr;
1843
1844 class ScalarStatNode : public Node
1845 {
1846 private:
1847 const ScalarDataBase *data;
1848 mutable rvec_t result;
1849
1850 public:
1851 ScalarStatNode(const ScalarDataBase *d) : data(d), result(1) {}
1852 virtual const rvec_t &val() const
1853 {
1854 result[0] = data->val();
1855 return result;
1856 }
1857 virtual result_t total() const { return data->val(); };
1858
1859 virtual size_t size() const { return 1; }
1860 /**
1861 * Return true if stat is binned.
1862 *@return True is stat is binned.
1863 */
1864 virtual bool binned() const { return data->binned(); }
1865 };
1866
1867 template <typename T, template <typename T> class Storage, class Bin>
1868 class ScalarProxyNode : public Node
1869 {
1870 private:
1871 const ScalarProxy<T, Storage, Bin> proxy;
1872 mutable rvec_t result;
1873
1874 public:
1875 ScalarProxyNode(const ScalarProxy<T, Storage, Bin> &p)
1876 : proxy(p), result(1) { }
1877 virtual const rvec_t &val() const
1878 {
1879 result[0] = proxy.val();
1880 return result;
1881 }
1882 virtual result_t total() const { return proxy.val(); };
1883
1884 virtual size_t size() const { return 1; }
1885 /**
1886 * Return true if stat is binned.
1887 *@return True is stat is binned.
1888 */
1889 virtual bool binned() const { return proxy.binned(); }
1890 };
1891
1892 class VectorStatNode : public Node
1893 {
1894 private:
1895 const VectorDataBase *data;
1896
1897 public:
1898 VectorStatNode(const VectorDataBase *d) : data(d) { }
1899 virtual const rvec_t &val() const { return data->val(); }
1900 virtual result_t total() const { return data->total(); };
1901
1902 virtual size_t size() const { return data->size(); }
1903 /**
1904 * Return true if stat is binned.
1905 *@return True is stat is binned.
1906 */
1907 virtual bool binned() const { return data->binned(); }
1908 };
1909
1910 template <typename T>
1911 class ConstNode : public Node
1912 {
1913 private:
1914 rvec_t data;
1915
1916 public:
1917 ConstNode(T s) : data(1, (result_t)s) {}
1918 const rvec_t &val() const { return data; }
1919 virtual result_t total() const { return data[0]; };
1920
1921 virtual size_t size() const { return 1; }
1922 /**
1923 * Return true if stat is binned.
1924 *@return False since constants aren't binned.
1925 */
1926 virtual bool binned() const { return false; }
1927 };
1928
1929 template <typename T>
1930 class FunctorNode : public Node
1931 {
1932 private:
1933 T &functor;
1934 mutable rvec_t result;
1935
1936 public:
1937 FunctorNode(T &f) : functor(f) { result.resize(1); }
1938 const rvec_t &val() const {
1939 result[0] = (result_t)functor();
1940 return result;
1941 }
1942 virtual result_t total() const { return (result_t)functor(); };
1943
1944 virtual size_t size() const { return 1; }
1945 /**
1946 * Return true if stat is binned.
1947 *@return False since Functors aren't binned
1948 */
1949 virtual bool binned() const { return false; }
1950 };
1951
1952 template <typename T>
1953 class ScalarNode : public Node
1954 {
1955 private:
1956 T &scalar;
1957 mutable rvec_t result;
1958
1959 public:
1960 ScalarNode(T &s) : scalar(s) { result.resize(1); }
1961 const rvec_t &val() const {
1962 result[0] = (result_t)scalar;
1963 return result;
1964 }
1965 virtual result_t total() const { return (result_t)scalar; };
1966
1967 virtual size_t size() const { return 1; }
1968 /**
1969 * Return true if stat is binned.
1970 *@return False since Scalar's aren't binned
1971 */
1972 virtual bool binned() const { return false; }
1973 };
1974
1975 template <class Op>
1976 class UnaryNode : public Node
1977 {
1978 public:
1979 NodePtr l;
1980 mutable rvec_t result;
1981
1982 public:
1983 UnaryNode(NodePtr p) : l(p) {}
1984
1985 const rvec_t &val() const {
1986 const rvec_t &lvec = l->val();
1987 int size = lvec.size();
1988
1989 assert(size > 0);
1990
1991 result.resize(size);
1992 Op op;
1993 for (int i = 0; i < size; ++i)
1994 result[i] = op(lvec[i]);
1995
1996 return result;
1997 }
1998
1999 result_t total() const {
2000 Op op;
2001 return op(l->total());
2002 }
2003
2004 virtual size_t size() const { return l->size(); }
2005 /**
2006 * Return true if child of node is binned.
2007 *@return True if child of node is binned.
2008 */
2009 virtual bool binned() const { return l->binned(); }
2010 };
2011
2012 template <class Op>
2013 class BinaryNode : public Node
2014 {
2015 public:
2016 NodePtr l;
2017 NodePtr r;
2018 mutable rvec_t result;
2019
2020 public:
2021 BinaryNode(NodePtr a, NodePtr b) : l(a), r(b) {}
2022
2023 const rvec_t &val() const {
2024 Op op;
2025 const rvec_t &lvec = l->val();
2026 const rvec_t &rvec = r->val();
2027
2028 assert(lvec.size() > 0 && rvec.size() > 0);
2029
2030 if (lvec.size() == 1 && rvec.size() == 1) {
2031 result.resize(1);
2032 result[0] = op(lvec[0], rvec[0]);
2033 } else if (lvec.size() == 1) {
2034 int size = rvec.size();
2035 result.resize(size);
2036 for (int i = 0; i < size; ++i)
2037 result[i] = op(lvec[0], rvec[i]);
2038 } else if (rvec.size() == 1) {
2039 int size = lvec.size();
2040 result.resize(size);
2041 for (int i = 0; i < size; ++i)
2042 result[i] = op(lvec[i], rvec[0]);
2043 } else if (rvec.size() == lvec.size()) {
2044 int size = rvec.size();
2045 result.resize(size);
2046 for (int i = 0; i < size; ++i)
2047 result[i] = op(lvec[i], rvec[i]);
2048 }
2049
2050 return result;
2051 }
2052
2053 result_t total() const {
2054 Op op;
2055 return op(l->total(), r->total());
2056 }
2057
2058 virtual size_t size() const {
2059 int ls = l->size();
2060 int rs = r->size();
2061 if (ls == 1)
2062 return rs;
2063 else if (rs == 1)
2064 return ls;
2065 else {
2066 assert(ls == rs && "Node vector sizes are not equal");
2067 return ls;
2068 }
2069 }
2070 /**
2071 * Return true if any children of node are binned
2072 *@return True if either child of node is binned.
2073 */
2074 virtual bool binned() const { return (l->binned() || r->binned()); }
2075 };
2076
2077 template <class Op>
2078 class SumNode : public Node
2079 {
2080 public:
2081 NodePtr l;
2082 mutable rvec_t result;
2083
2084 public:
2085 SumNode(NodePtr p) : l(p), result(1) {}
2086
2087 const rvec_t &val() const {
2088 const rvec_t &lvec = l->val();
2089 int size = lvec.size();
2090 assert(size > 0);
2091
2092 result[0] = 0.0;
2093
2094 Op op;
2095 for (int i = 0; i < size; ++i)
2096 result[0] = op(result[0], lvec[i]);
2097
2098 return result;
2099 }
2100
2101 result_t total() const {
2102 const rvec_t &lvec = l->val();
2103 int size = lvec.size();
2104 assert(size > 0);
2105
2106 result_t result = 0.0;
2107
2108 Op op;
2109 for (int i = 0; i < size; ++i)
2110 result = op(result, lvec[i]);
2111
2112 return result;
2113 }
2114
2115 virtual size_t size() const { return 1; }
2116 /**
2117 * Return true if child of node is binned.
2118 *@return True if child of node is binned.
2119 */
2120 virtual bool binned() const { return l->binned(); }
2121 };
2122
2123 //////////////////////////////////////////////////////////////////////
2124 //
2125 // Binning Interface
2126 //
2127 //////////////////////////////////////////////////////////////////////
2128 struct MainBin
2129 {
2130 private:
2131 std::string _name;
2132 char *mem;
2133
2134 protected:
2135 off_t memsize;
2136 off_t size() const { return memsize; }
2137 char *memory(off_t off);
2138
2139 public:
2140 static MainBin *&curBin()
2141 {
2142 static MainBin *current = NULL;
2143 return current;
2144 }
2145
2146 static void setCurBin(MainBin *bin) { curBin() = bin; }
2147 static MainBin *current() { assert(curBin()); return curBin(); }
2148
2149 static off_t &offset()
2150 {
2151 static off_t offset = 0;
2152 return offset;
2153 }
2154
2155 static off_t new_offset(size_t size)
2156 {
2157 size_t mask = sizeof(u_int64_t) - 1;
2158 off_t off = offset();
2159
2160 // That one is for the last trailing flags byte.
2161 offset() += (size + 1 + mask) & ~mask;
2162 return off;
2163 }
2164
2165 public:
2166 MainBin(const std::string &name);
2167 ~MainBin();
2168
2169 const std::string &
2170 name() const
2171 {
2172 return _name;
2173 }
2174
2175 void
2176 activate()
2177 {
2178 setCurBin(this);
2179 }
2180
2181 class BinBase
2182 {
2183 private:
2184 int offset;
2185
2186 public:
2187 BinBase() : offset(-1) {}
2188 void allocate(size_t size)
2189 {
2190 offset = new_offset(size);
2191 }
2192 char *access()
2193 {
2194 assert(offset != -1);
2195 return current()->memory(offset);
2196 }
2197 };
2198
2199 template <class Storage>
2200 class Bin : public BinBase
2201 {
2202 public:
2203 typedef typename Storage::Params Params;
2204
2205 public:
2206 enum { binned = true };
2207 Bin() { allocate(sizeof(Storage)); }
2208 bool initialized() const { return true; }
2209 void init(Params &params) { }
2210
2211 int size() const { return 1; }
2212
2213 Storage *
2214 data(Params &params)
2215 {
2216 assert(initialized());
2217 char *ptr = access();
2218 char *flags = ptr + sizeof(Storage);
2219 if (!(*flags & 0x1)) {
2220 *flags |= 0x1;
2221 new (ptr) Storage(params);
2222 }
2223 return reinterpret_cast<Storage *>(ptr);
2224 }
2225
2226 void
2227 reset()
2228 {
2229 char *ptr = access();
2230 char *flags = ptr + size() * sizeof(Storage);
2231 if (!(*flags & 0x1))
2232 return;
2233
2234 Storage *s = reinterpret_cast<Storage *>(ptr);
2235 s->reset();
2236 }
2237 };
2238
2239 template <class Storage>
2240 class VectorBin : public BinBase
2241 {
2242 public:
2243 typedef typename Storage::Params Params;
2244
2245 private:
2246 int _size;
2247
2248 public:
2249 enum { binned = true };
2250 VectorBin() : _size(0) {}
2251
2252 bool initialized() const { return _size > 0; }
2253 void init(int s, Params &params)
2254 {
2255 assert(!initialized());
2256 assert(s > 0);
2257 _size = s;
2258 allocate(_size * sizeof(Storage));
2259 }
2260
2261 int size() const { return _size; }
2262
2263 Storage *data(int index, Params &params)
2264 {
2265 assert(initialized());
2266 assert(index >= 0 && index < size());
2267 char *ptr = access();
2268 char *flags = ptr + size() * sizeof(Storage);
2269 if (!(*flags & 0x1)) {
2270 *flags |= 0x1;
2271 for (int i = 0; i < size(); ++i)
2272 new (ptr + i * sizeof(Storage)) Storage(params);
2273 }
2274 return reinterpret_cast<Storage *>(ptr + index * sizeof(Storage));
2275 }
2276 void reset()
2277 {
2278 char *ptr = access();
2279 char *flags = ptr + size() * sizeof(Storage);
2280 if (!(*flags & 0x1))
2281 return;
2282
2283 for (int i = 0; i < _size; ++i) {
2284 char *p = ptr + i * sizeof(Storage);
2285 Storage *s = reinterpret_cast<Storage *>(p);
2286 s->reset();
2287 }
2288 }
2289 };
2290 };
2291
2292 struct NoBin
2293 {
2294 template <class Storage>
2295 struct Bin
2296 {
2297 public:
2298 typedef typename Storage::Params Params;
2299 enum { binned = false };
2300
2301 private:
2302 char ptr[sizeof(Storage)];
2303
2304 public:
2305 ~Bin()
2306 {
2307 reinterpret_cast<Storage *>(ptr)->~Storage();
2308 }
2309
2310 bool initialized() const { return true; }
2311 void init(Params &params)
2312 {
2313 new (ptr) Storage(params);
2314 }
2315 int size() const{ return 1; }
2316 Storage *data(Params &params)
2317 {
2318 assert(initialized());
2319 return reinterpret_cast<Storage *>(ptr);
2320 }
2321 void reset()
2322 {
2323 Storage *s = reinterpret_cast<Storage *>(ptr);
2324 s->reset();
2325 }
2326 };
2327
2328 template <class Storage>
2329 struct VectorBin
2330 {
2331 public:
2332 typedef typename Storage::Params Params;
2333 enum { binned = false };
2334
2335 private:
2336 char *ptr;
2337 int _size;
2338
2339 public:
2340 VectorBin() : ptr(NULL) { }
2341 ~VectorBin()
2342 {
2343 if (!initialized())
2344 return;
2345
2346 for (int i = 0; i < _size; ++i) {
2347 char *p = ptr + i * sizeof(Storage);
2348 reinterpret_cast<Storage *>(p)->~Storage();
2349 }
2350 delete [] ptr;
2351 }
2352
2353 bool initialized() const { return ptr != NULL; }
2354 void init(int s, Params &params)
2355 {
2356 assert(s > 0 && "size must be positive!");
2357 assert(!initialized());
2358 _size = s;
2359 ptr = new char[_size * sizeof(Storage)];
2360 for (int i = 0; i < _size; ++i)
2361 new (ptr + i * sizeof(Storage)) Storage(params);
2362 }
2363
2364 int size() const { return _size; }
2365
2366 Storage *data(int index, Params &params)
2367 {
2368 assert(initialized());
2369 assert(index >= 0 && index < size());
2370 return reinterpret_cast<Storage *>(ptr + index * sizeof(Storage));
2371 }
2372 void reset()
2373 {
2374 for (int i = 0; i < _size; ++i) {
2375 char *p = ptr + i * sizeof(Storage);
2376 Storage *s = reinterpret_cast<Storage *>(p);
2377 s->reset();
2378 }
2379 }
2380 };
2381 };
2382
2383 //////////////////////////////////////////////////////////////////////
2384 //
2385 // Visible Statistics Types
2386 //
2387 //////////////////////////////////////////////////////////////////////
2388 /**
2389 * @defgroup VisibleStats "Statistic Types"
2390 * These are the statistics that are used in the simulator. By default these
2391 * store counters and don't use binning, but are templatized to accept any type
2392 * and any Bin class.
2393 * @{
2394 */
2395
2396 /**
2397 * This is an easy way to assign all your stats to be binned or not
2398 * binned. If the typedef is NoBin, nothing is binned. If it is
2399 * MainBin, then all stats are binned under that Bin.
2400 */
2401 #ifdef FS_MEASURE
2402 typedef MainBin DefaultBin;
2403 #else
2404 typedef NoBin DefaultBin;
2405 #endif
2406
2407 /**
2408 * This is a simple scalar statistic, like a counter.
2409 * @sa Stat, ScalarBase, StatStor
2410 */
2411 template <typename T = Counter, class Bin = DefaultBin>
2412 class Scalar
2413 : public Wrap<Scalar<T, Bin>,
2414 ScalarBase<T, StatStor, Bin>,
2415 ScalarData>
2416 {
2417 public:
2418 /** The base implementation. */
2419 typedef ScalarBase<T, StatStor, Bin> Base;
2420
2421 Scalar()
2422 {
2423 setInit();
2424 }
2425
2426 /**
2427 * Sets the stat equal to the given value. Calls the base implementation
2428 * of operator=
2429 * @param v The new value.
2430 */
2431 template <typename U>
2432 void operator=(const U& v) { Base::operator=(v); }
2433 };
2434
2435 /**
2436 * A stat that calculates the per cycle average of a value.
2437 * @sa Stat, ScalarBase, AvgStor
2438 */
2439 template <typename T = Counter, class Bin = DefaultBin>
2440 class Average
2441 : public Wrap<Average<T, Bin>,
2442 ScalarBase<T, AvgStor, Bin>,
2443 ScalarData>
2444 {
2445 public:
2446 /** The base implementation. */
2447 typedef ScalarBase<T, AvgStor, Bin> Base;
2448
2449 Average()
2450 {
2451 setInit();
2452 }
2453
2454 /**
2455 * Sets the stat equal to the given value. Calls the base implementation
2456 * of operator=
2457 * @param v The new value.
2458 */
2459 template <typename U>
2460 void operator=(const U& v) { Base::operator=(v); }
2461 };
2462
2463 /**
2464 * A vector of scalar stats.
2465 * @sa Stat, VectorBase, StatStor
2466 */
2467 template <typename T = Counter, class Bin = DefaultBin>
2468 class Vector
2469 : public WrapVec<Vector<T, Bin>,
2470 VectorBase<T, StatStor, Bin>,
2471 VectorData>
2472 {
2473 public:
2474 /**
2475 * Set this vector to have the given size.
2476 * @param size The new size.
2477 * @return A reference to this stat.
2478 */
2479 Vector &init(size_t size) {
2480 bin.init(size, params);
2481 setInit();
2482
2483 return *this;
2484 }
2485 };
2486
2487 /**
2488 * A vector of Average stats.
2489 * @sa Stat, VectorBase, AvgStor
2490 */
2491 template <typename T = Counter, class Bin = DefaultBin>
2492 class AverageVector
2493 : public WrapVec<AverageVector<T, Bin>,
2494 VectorBase<T, AvgStor, Bin>,
2495 VectorData>
2496 {
2497 public:
2498 /**
2499 * Set this vector to have the given size.
2500 * @param size The new size.
2501 * @return A reference to this stat.
2502 */
2503 AverageVector &init(size_t size) {
2504 bin.init(size, params);
2505 setInit();
2506
2507 return *this;
2508 }
2509 };
2510
2511 /**
2512 * A 2-Dimensional vecto of scalar stats.
2513 * @sa Stat, Vector2dBase, StatStor
2514 */
2515 template <typename T = Counter, class Bin = DefaultBin>
2516 class Vector2d
2517 : public WrapVec2d<Vector2d<T, Bin>,
2518 Vector2dBase<T, StatStor, Bin>,
2519 Vector2dData>
2520 {
2521 public:
2522 Vector2d &init(size_t _x, size_t _y) {
2523 statData()->x = x = _x;
2524 statData()->y = y = _y;
2525 bin.init(x * y, params);
2526 setInit();
2527
2528 return *this;
2529 }
2530 };
2531
2532 /**
2533 * A simple distribution stat.
2534 * @sa Stat, DistBase, DistStor
2535 */
2536 template <typename T = Counter, class Bin = DefaultBin>
2537 class Distribution
2538 : public Wrap<Distribution<T, Bin>,
2539 DistBase<T, DistStor, Bin>,
2540 DistData>
2541 {
2542 private:
2543 /** Base implementation. */
2544 typedef DistBase<T, DistStor, Bin> Base;
2545 /** The Parameter type. */
2546 typedef typename DistStor<T>::Params Params;
2547
2548 public:
2549 /**
2550 * Set the parameters of this distribution. @sa DistStor::Params
2551 * @param min The minimum value of the distribution.
2552 * @param max The maximum value of the distribution.
2553 * @param bkt The number of values in each bucket.
2554 * @return A reference to this distribution.
2555 */
2556 Distribution &init(T min, T max, int bkt) {
2557 params.min = min;
2558 params.max = max;
2559 params.bucket_size = bkt;
2560 params.size = (max - min) / bkt + 1;
2561 bin.init(params);
2562 setInit();
2563
2564 return *this;
2565 }
2566 };
2567
2568 /**
2569 * Calculates the mean and variance of all the samples.
2570 * @sa Stat, DistBase, FancyStor
2571 */
2572 template <typename T = Counter, class Bin = DefaultBin>
2573 class StandardDeviation
2574 : public Wrap<StandardDeviation<T, Bin>,
2575 DistBase<T, FancyStor, Bin>,
2576 DistData>
2577 {
2578 private:
2579 /** The base implementation */
2580 typedef DistBase<T, DistStor, Bin> Base;
2581 /** The parameter type. */
2582 typedef typename DistStor<T>::Params Params;
2583
2584 public:
2585 /**
2586 * Construct and initialize this distribution.
2587 */
2588 StandardDeviation() {
2589 bin.init(params);
2590 setInit();
2591 }
2592 };
2593
2594 /**
2595 * Calculates the per cycle mean and variance of the samples.
2596 * @sa Stat, DistBase, AvgFancy
2597 */
2598 template <typename T = Counter, class Bin = DefaultBin>
2599 class AverageDeviation
2600 : public Wrap<AverageDeviation<T, Bin>,
2601 DistBase<T, AvgFancy, Bin>,
2602 DistData>
2603 {
2604 private:
2605 /** The base implementation */
2606 typedef DistBase<T, DistStor, Bin> Base;
2607 /** The parameter type. */
2608 typedef typename DistStor<T>::Params Params;
2609
2610 public:
2611 /**
2612 * Construct and initialize this distribution.
2613 */
2614 AverageDeviation()
2615 {
2616 bin.init(params);
2617 setInit();
2618 }
2619 };
2620
2621 /**
2622 * A vector of distributions.
2623 * @sa Stat, VectorDistBase, DistStor
2624 */
2625 template <typename T = Counter, class Bin = DefaultBin>
2626 class VectorDistribution
2627 : public WrapVec<VectorDistribution<T, Bin>,
2628 VectorDistBase<T, DistStor, Bin>,
2629 VectorDistData>
2630 {
2631 private:
2632 /** The base implementation */
2633 typedef VectorDistBase<T, DistStor, Bin> Base;
2634 /** The parameter type. */
2635 typedef typename DistStor<T>::Params Params;
2636
2637 public:
2638 /**
2639 * Initialize storage and parameters for this distribution.
2640 * @param size The size of the vector (the number of distributions).
2641 * @param min The minimum value of the distribution.
2642 * @param max The maximum value of the distribution.
2643 * @param bkt The number of values in each bucket.
2644 * @return A reference to this distribution.
2645 */
2646 VectorDistribution &init(int size, T min, T max, int bkt) {
2647 params.min = min;
2648 params.max = max;
2649 params.bucket_size = bkt;
2650 params.size = (max - min) / bkt + 1;
2651 bin.init(size, params);
2652 setInit();
2653
2654 return *this;
2655 }
2656 };
2657
2658 /**
2659 * This is a vector of StandardDeviation stats.
2660 * @sa Stat, VectorDistBase, FancyStor
2661 */
2662 template <typename T = Counter, class Bin = DefaultBin>
2663 class VectorStandardDeviation
2664 : public WrapVec<VectorStandardDeviation<T, Bin>,
2665 VectorDistBase<T, FancyStor, Bin>,
2666 VectorDistData>
2667 {
2668 private:
2669 /** The base implementation */
2670 typedef VectorDistBase<T, FancyStor, Bin> Base;
2671 /** The parameter type. */
2672 typedef typename DistStor<T>::Params Params;
2673
2674 public:
2675 /**
2676 * Initialize storage for this distribution.
2677 * @param size The size of the vector.
2678 * @return A reference to this distribution.
2679 */
2680 VectorStandardDeviation &init(int size) {
2681 bin.init(size, params);
2682 setInit();
2683
2684 return *this;
2685 }
2686 };
2687
2688 /**
2689 * This is a vector of AverageDeviation stats.
2690 * @sa Stat, VectorDistBase, AvgFancy
2691 */
2692 template <typename T = Counter, class Bin = DefaultBin>
2693 class VectorAverageDeviation
2694 : public WrapVec<VectorAverageDeviation<T, Bin>,
2695 VectorDistBase<T, AvgFancy, Bin>,
2696 VectorDistData>
2697 {
2698 private:
2699 /** The base implementation */
2700 typedef VectorDistBase<T, AvgFancy, Bin> Base;
2701 /** The parameter type. */
2702 typedef typename DistStor<T>::Params Params;
2703
2704 public:
2705 /**
2706 * Initialize storage for this distribution.
2707 * @param size The size of the vector.
2708 * @return A reference to this distribution.
2709 */
2710 VectorAverageDeviation &init(int size) {
2711 bin.init(size, params);
2712 setInit();
2713
2714 return *this;
2715 }
2716 };
2717
2718 /**
2719 * A formula for statistics that is calculated when printed. A formula is
2720 * stored as a tree of Nodes that represent the equation to calculate.
2721 * @sa Stat, ScalarStat, VectorStat, Node, Temp
2722 */
2723 class FormulaBase : public DataAccess
2724 {
2725 protected:
2726 /** The root of the tree which represents the Formula */
2727 NodePtr root;
2728 friend class Temp;
2729
2730 public:
2731 /**
2732 * Return the result of the Fomula in a vector. If there were no Vector
2733 * components to the Formula, then the vector is size 1. If there were,
2734 * like x/y with x being a vector of size 3, then the result returned will
2735 * be x[0]/y, x[1]/y, x[2]/y, respectively.
2736 * @return The result vector.
2737 */
2738 void val(rvec_t &vec) const;
2739
2740 /**
2741 * Return the total Formula result. If there is a Vector
2742 * component to this Formula, then this is the result of the
2743 * Formula if the formula is applied after summing all the
2744 * components of the Vector. For example, if Formula is x/y where
2745 * x is size 3, then total() will return (x[1]+x[2]+x[3])/y. If
2746 * there is no Vector component, total() returns the same value as
2747 * the first entry in the rvec_t val() returns.
2748 * @return The total of the result vector.
2749 */
2750 result_t total() const;
2751
2752 /**
2753 * Return the number of elements in the tree.
2754 */
2755 size_t size() const;
2756
2757 /**
2758 * Return true if Formula is binned. i.e. any of its children
2759 * nodes are binned
2760 * @return True if Formula is binned.
2761 */
2762 bool binned() const;
2763
2764 bool check() const { return true; }
2765
2766 /**
2767 * Formulas don't need to be reset
2768 */
2769 void reset();
2770
2771 /**
2772 *
2773 */
2774 bool zero() const;
2775
2776 /**
2777 *
2778 */
2779 void update(StatData *);
2780 };
2781
2782 class Temp;
2783 class Formula : public WrapVec<Formula, FormulaBase, VectorData>
2784 {
2785 public:
2786 /**
2787 * Create and initialize thie formula, and register it with the database.
2788 */
2789 Formula();
2790
2791 /**
2792 * Create a formula with the given root node, register it with the
2793 * database.
2794 * @param r The root of the expression tree.
2795 */
2796 Formula(Temp r);
2797
2798 /**
2799 * Set an unitialized Formula to the given root.
2800 * @param r The root of the expression tree.
2801 * @return a reference to this formula.
2802 */
2803 const Formula &operator=(Temp r);
2804
2805 /**
2806 * Add the given tree to the existing one.
2807 * @param r The root of the expression tree.
2808 * @return a reference to this formula.
2809 */
2810 const Formula &operator+=(Temp r);
2811 };
2812
2813 class FormulaNode : public Node
2814 {
2815 private:
2816 const Formula &formula;
2817 mutable rvec_t vec;
2818
2819 public:
2820 FormulaNode(const Formula &f) : formula(f) {}
2821
2822 virtual size_t size() const { return formula.size(); }
2823 virtual const rvec_t &val() const { formula.val(vec); return vec; }
2824 virtual result_t total() const { return formula.total(); }
2825 virtual bool binned() const { return formula.binned(); }
2826 };
2827
2828 /**
2829 * Helper class to construct formula node trees.
2830 */
2831 class Temp
2832 {
2833 protected:
2834 /**
2835 * Pointer to a Node object.
2836 */
2837 NodePtr node;
2838
2839 public:
2840 /**
2841 * Copy the given pointer to this class.
2842 * @param n A pointer to a Node object to copy.
2843 */
2844 Temp(NodePtr n) : node(n) { }
2845
2846 /**
2847 * Return the node pointer.
2848 * @return the node pointer.
2849 */
2850 operator NodePtr() { return node;}
2851
2852 public:
2853 /**
2854 * Create a new ScalarStatNode.
2855 * @param s The ScalarStat to place in a node.
2856 */
2857 template <typename T, class Bin>
2858 Temp(const Scalar<T, Bin> &s)
2859 : node(new ScalarStatNode(s.statData())) { }
2860
2861 /**
2862 * Create a new ScalarStatNode.
2863 * @param s The ScalarStat to place in a node.
2864 */
2865 template <typename T, class Bin>
2866 Temp(const Average<T, Bin> &s)
2867 : node(new ScalarStatNode(s.statData())) { }
2868
2869 /**
2870 * Create a new VectorStatNode.
2871 * @param s The VectorStat to place in a node.
2872 */
2873 template <typename T, class Bin>
2874 Temp(const Vector<T, Bin> &s)
2875 : node(new VectorStatNode(s.statData())) { }
2876
2877 /**
2878 *
2879 */
2880 Temp(const Formula &f)
2881 : node(new FormulaNode(f)) { }
2882
2883 /**
2884 * Create a new ScalarProxyNode.
2885 * @param p The ScalarProxy to place in a node.
2886 */
2887 template <typename T, template <typename T> class Storage, class Bin>
2888 Temp(const ScalarProxy<T, Storage, Bin> &p)
2889 : node(new ScalarProxyNode<T, Storage, Bin>(p)) { }
2890
2891 /**
2892 * Create a ConstNode
2893 * @param value The value of the const node.
2894 */
2895 Temp(signed char value)
2896 : node(new ConstNode<signed char>(value)) {}
2897
2898 /**
2899 * Create a ConstNode
2900 * @param value The value of the const node.
2901 */
2902 Temp(unsigned char value)
2903 : node(new ConstNode<unsigned char>(value)) {}
2904
2905 /**
2906 * Create a ConstNode
2907 * @param value The value of the const node.
2908 */
2909 Temp(signed short value)
2910 : node(new ConstNode<signed short>(value)) {}
2911
2912 /**
2913 * Create a ConstNode
2914 * @param value The value of the const node.
2915 */
2916 Temp(unsigned short value)
2917 : node(new ConstNode<unsigned short>(value)) {}
2918
2919 /**
2920 * Create a ConstNode
2921 * @param value The value of the const node.
2922 */
2923 Temp(signed int value)
2924 : node(new ConstNode<signed int>(value)) {}
2925
2926 /**
2927 * Create a ConstNode
2928 * @param value The value of the const node.
2929 */
2930 Temp(unsigned int value)
2931 : node(new ConstNode<unsigned int>(value)) {}
2932
2933 /**
2934 * Create a ConstNode
2935 * @param value The value of the const node.
2936 */
2937 Temp(signed long value)
2938 : node(new ConstNode<signed long>(value)) {}
2939
2940 /**
2941 * Create a ConstNode
2942 * @param value The value of the const node.
2943 */
2944 Temp(unsigned long value)
2945 : node(new ConstNode<unsigned long>(value)) {}
2946
2947 /**
2948 * Create a ConstNode
2949 * @param value The value of the const node.
2950 */
2951 Temp(signed long long value)
2952 : node(new ConstNode<signed long long>(value)) {}
2953
2954 /**
2955 * Create a ConstNode
2956 * @param value The value of the const node.
2957 */
2958 Temp(unsigned long long value)
2959 : node(new ConstNode<unsigned long long>(value)) {}
2960
2961 /**
2962 * Create a ConstNode
2963 * @param value The value of the const node.
2964 */
2965 Temp(float value)
2966 : node(new ConstNode<float>(value)) {}
2967
2968 /**
2969 * Create a ConstNode
2970 * @param value The value of the const node.
2971 */
2972 Temp(double value)
2973 : node(new ConstNode<double>(value)) {}
2974 };
2975
2976
2977 /**
2978 * @}
2979 */
2980
2981 void check();
2982 void dump(std::ostream &stream, DisplayMode mode = DefaultMode);
2983 void reset();
2984 void registerResetCallback(Callback *cb);
2985
2986 inline Temp
2987 operator+(Temp l, Temp r)
2988 {
2989 return NodePtr(new BinaryNode<std::plus<result_t> >(l, r));
2990 }
2991
2992 inline Temp
2993 operator-(Temp l, Temp r)
2994 {
2995 return NodePtr(new BinaryNode<std::minus<result_t> >(l, r));
2996 }
2997
2998 inline Temp
2999 operator*(Temp l, Temp r)
3000 {
3001 return NodePtr(new BinaryNode<std::multiplies<result_t> >(l, r));
3002 }
3003
3004 inline Temp
3005 operator/(Temp l, Temp r)
3006 {
3007 return NodePtr(new BinaryNode<std::divides<result_t> >(l, r));
3008 }
3009
3010 inline Temp
3011 operator%(Temp l, Temp r)
3012 {
3013 return NodePtr(new BinaryNode<std::modulus<result_t> >(l, r));
3014 }
3015
3016 inline Temp
3017 operator-(Temp l)
3018 {
3019 return NodePtr(new UnaryNode<std::negate<result_t> >(l));
3020 }
3021
3022 template <typename T>
3023 inline Temp
3024 constant(T val)
3025 {
3026 return NodePtr(new ConstNode<T>(val));
3027 }
3028
3029 template <typename T>
3030 inline Temp
3031 functor(T &val)
3032 {
3033 return NodePtr(new FunctorNode<T>(val));
3034 }
3035
3036 template <typename T>
3037 inline Temp
3038 scalar(T &val)
3039 {
3040 return NodePtr(new ScalarNode<T>(val));
3041 }
3042
3043 inline Temp
3044 sum(Temp val)
3045 {
3046 return NodePtr(new SumNode<std::plus<result_t> >(val));
3047 }
3048 extern bool PrintDescriptions;
3049
3050 } // namespace statistics
3051
3052 #endif // __STATISTICS_HH__