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