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