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