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