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