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