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