statistics.hh revision 5994:19131d568007
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    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    bool check() const { return s.check(); }
171    Counter value() const { return s.value(); }
172    Result result() const { return s.result(); }
173    Result total() const { return s.total(); }
174    void reset() { s.reset(); }
175    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    bool check() const { return s.check(); }
217    bool zero() const { return s.zero(); }
218    void reset() { s.reset(); }
219
220    size_type size() const { return s.size(); }
221
222    VCounter &
223    value() const
224    {
225        s.value(cvec);
226        return cvec;
227    }
228
229    const VResult &
230    result() const
231    {
232        s.result(rvec);
233        return rvec;
234    }
235
236    Result total() const { return s.total(); }
237
238    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    bool check() const { return s.check(); }
278    void reset() { s.reset(); }
279    bool zero() const { return s.zero(); }
280
281    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    bool check() const { return s.check(); }
327    void reset() { s.reset(); }
328    size_type size() const { return s.size(); }
329    bool zero() const { return s.zero(); }
330
331    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    bool check() const { return s.check(); }
372    void reset() { s.reset(); }
373    bool zero() const { return s.zero(); }
374
375    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 _precision 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.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    void visit(Visit &visitor) { visitor.visit(*this); }
866    std::string str() const { return to_string(value()); }
867    size_type size() const { return 1; }
868    bool zero() const { return value() == 0; }
869    bool check() const { return true; }
870    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    Counter value() const { return *scalar; }
882    Result result() const { return *scalar; }
883    Result total() const { return *scalar; }
884};
885
886template <class T>
887class FunctorProxy : public ProxyInfo
888{
889  private:
890    T *functor;
891
892  public:
893    FunctorProxy(T &func) : functor(&func) {}
894    Counter value() const { return (*functor)(); }
895    Result result() const { return (*functor)(); }
896    Result total() const { return (*functor)(); }
897};
898
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.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     */
1475    void
1476    sample(Counter val, int number)
1477    {
1478        if (val < min_track)
1479            underflow += number;
1480        else if (val > max_track)
1481            overflow += number;
1482        else {
1483            size_type index =
1484                (size_type)std::floor((val - min_track) / bucket_size);
1485            assert(index < size());
1486            cvec[index] += number;
1487        }
1488
1489        if (val < min_val)
1490            min_val = val;
1491
1492        if (val > max_val)
1493            max_val = val;
1494
1495        Counter sample = val * number;
1496        sum += sample;
1497        squares += sample * sample;
1498        samples += number;
1499    }
1500
1501    /**
1502     * Return the number of buckets in this distribution.
1503     * @return the number of buckets.
1504     */
1505    size_type size() const { return cvec.size(); }
1506
1507    /**
1508     * Returns true if any calls to sample have been made.
1509     * @return True if any values have been sampled.
1510     */
1511    bool
1512    zero() const
1513    {
1514        return samples == Counter();
1515    }
1516
1517    void
1518    update(Info *info, DistData &data)
1519    {
1520        const Params *params = safe_cast<const Params *>(info->storageParams);
1521
1522        data.min_val = (min_val == CounterLimits::max()) ? 0 : min_val;
1523        data.max_val = (max_val == CounterLimits::min()) ? 0 : max_val;
1524        data.underflow = underflow;
1525        data.overflow = overflow;
1526
1527        int buckets = params->buckets;
1528        data.cvec.resize(buckets);
1529        for (off_type i = 0; i < buckets; ++i)
1530            data.cvec[i] = cvec[i];
1531
1532        data.sum = sum;
1533        data.squares = squares;
1534        data.samples = samples;
1535    }
1536
1537    /**
1538     * Reset stat value to default
1539     */
1540    void
1541    reset(Info *info)
1542    {
1543        const Params *params = safe_cast<const Params *>(info->storageParams);
1544        min_track = params->min;
1545        max_track = params->max;
1546        bucket_size = params->bucket_size;
1547
1548        min_val = CounterLimits::max();
1549        max_val = CounterLimits::min();
1550        underflow = 0;
1551        overflow = 0;
1552
1553        size_type size = cvec.size();
1554        for (off_type i = 0; i < size; ++i)
1555            cvec[i] = Counter();
1556
1557        sum = Counter();
1558        squares = Counter();
1559        samples = Counter();
1560    }
1561};
1562
1563/**
1564 * Templatized storage and interface for a distribution that calculates mean
1565 * and variance.
1566 */
1567class FancyStor
1568{
1569  public:
1570    struct Params : public StorageParams {};
1571
1572  public:
1573    enum { fancy = true };
1574
1575  private:
1576    /** The current sum. */
1577    Counter sum;
1578    /** The sum of squares. */
1579    Counter squares;
1580    /** The number of samples. */
1581    Counter samples;
1582
1583  public:
1584    /**
1585     * Create and initialize this storage.
1586     */
1587    FancyStor(Info *info)
1588        : sum(Counter()), squares(Counter()), samples(Counter())
1589    { }
1590
1591    /**
1592     * Add a value the given number of times to this running average.
1593     * Update the running sum and sum of squares, increment the number of
1594     * values seen by the given number.
1595     * @param val The value to add.
1596     * @param number The number of times to add the value.
1597     */
1598    void
1599    sample(Counter val, int number)
1600    {
1601        Counter value = val * number;
1602        sum += value;
1603        squares += value * value;
1604        samples += number;
1605    }
1606
1607    void
1608    update(Info *info, DistData &data)
1609    {
1610        data.sum = sum;
1611        data.squares = squares;
1612        data.samples = samples;
1613    }
1614
1615    /**
1616     * Return the number of entries in this stat, 1
1617     * @return 1.
1618     */
1619    size_type size() const { return 1; }
1620
1621    /**
1622     * Return true if no samples have been added.
1623     * @return True if no samples have been added.
1624     */
1625    bool zero() const { return samples == Counter(); }
1626
1627    /**
1628     * Reset stat value to default
1629     */
1630    void
1631    reset(Info *info)
1632    {
1633        sum = Counter();
1634        squares = Counter();
1635        samples = Counter();
1636    }
1637};
1638
1639/**
1640 * Templatized storage for distribution that calculates per tick mean and
1641 * variance.
1642 */
1643class AvgFancy
1644{
1645  public:
1646    struct Params : public StorageParams {};
1647
1648  public:
1649    enum { fancy = true };
1650
1651  private:
1652    /** Current total. */
1653    Counter sum;
1654    /** Current sum of squares. */
1655    Counter squares;
1656
1657  public:
1658    /**
1659     * Create and initialize this storage.
1660     */
1661    AvgFancy(Info *info)
1662        : sum(Counter()), squares(Counter())
1663    {}
1664
1665    /**
1666     * Add a value to the distribution for the given number of times.
1667     * Update the running sum and sum of squares.
1668     * @param val The value to add.
1669     * @param number The number of times to add the value.
1670     */
1671    void
1672    sample(Counter val, int number)
1673    {
1674        Counter value = val * number;
1675        sum += value;
1676        squares += value * value;
1677    }
1678
1679    void
1680    update(Info *info, DistData &data)
1681    {
1682        data.sum = sum;
1683        data.squares = squares;
1684        data.samples = curTick;
1685    }
1686
1687    /**
1688     * Return the number of entries, in this case 1.
1689     * @return 1.
1690     */
1691    size_type size() const { return 1; }
1692
1693    /**
1694     * Return true if no samples have been added.
1695     * @return True if the sum is zero.
1696     */
1697    bool zero() const { return sum == Counter(); }
1698
1699    /**
1700     * Reset stat value to default
1701     */
1702    void
1703    reset(Info *info)
1704    {
1705        sum = Counter();
1706        squares = Counter();
1707    }
1708};
1709
1710/**
1711 * Implementation of a distribution stat. The type of distribution is
1712 * determined by the Storage template. @sa ScalarBase
1713 */
1714template <class Stor>
1715class DistBase : public InfoAccess
1716{
1717  public:
1718    typedef Stor Storage;
1719    typedef typename Stor::Params Params;
1720
1721  protected:
1722    /** The storage for this stat. */
1723    char storage[sizeof(Storage)] __attribute__ ((aligned (8)));
1724
1725  protected:
1726    /**
1727     * Retrieve the storage.
1728     * @return The storage object for this stat.
1729     */
1730    Storage *
1731    data()
1732    {
1733        return reinterpret_cast<Storage *>(storage);
1734    }
1735
1736    /**
1737     * Retrieve a const pointer to the storage.
1738     * @return A const pointer to the storage object for this stat.
1739     */
1740    const Storage *
1741    data() const
1742    {
1743        return reinterpret_cast<const Storage *>(storage);
1744    }
1745
1746    void
1747    doInit()
1748    {
1749        new (storage) Storage(info());
1750        setInit();
1751    }
1752
1753  public:
1754    DistBase() { }
1755
1756    /**
1757     * Add a value to the distribtion n times. Calls sample on the storage
1758     * class.
1759     * @param v The value to add.
1760     * @param n The number of times to add it, defaults to 1.
1761     */
1762    template <typename U>
1763    void sample(const U &v, int n = 1) { data()->sample(v, n); }
1764
1765    /**
1766     * Return the number of entries in this stat.
1767     * @return The number of entries.
1768     */
1769    size_type size() const { return data()->size(); }
1770    /**
1771     * Return true if no samples have been added.
1772     * @return True if there haven't been any samples.
1773     */
1774    bool zero() const { return data()->zero(); }
1775
1776    void
1777    update(DistInfoBase *base)
1778    {
1779        base->data.fancy = Storage::fancy;
1780        data()->update(info(), base->data);
1781    }
1782
1783    /**
1784     * Reset stat value to default
1785     */
1786    void
1787    reset()
1788    {
1789        data()->reset(info());
1790    }
1791
1792    bool
1793    check()
1794    {
1795        return true;
1796    }
1797};
1798
1799template <class Stat>
1800class DistProxy;
1801
1802template <class Stor>
1803class VectorDistBase : public InfoAccess
1804{
1805  public:
1806    typedef Stor Storage;
1807    typedef typename Stor::Params Params;
1808    typedef DistProxy<VectorDistBase<Storage> > Proxy;
1809    friend class DistProxy<VectorDistBase<Storage> >;
1810
1811  protected:
1812    Storage *storage;
1813    size_type _size;
1814
1815  protected:
1816    Storage *
1817    data(off_type index)
1818    {
1819        return &storage[index];
1820    }
1821
1822    const Storage *
1823    data(off_type index) const
1824    {
1825        return &storage[index];
1826    }
1827
1828    void
1829    doInit(size_type s)
1830    {
1831        assert(s > 0 && "size must be positive!");
1832        assert(!storage && "already initialized");
1833        _size = s;
1834
1835        char *ptr = new char[_size * sizeof(Storage)];
1836        storage = reinterpret_cast<Storage *>(ptr);
1837
1838        for (off_type i = 0; i < _size; ++i)
1839            new (&storage[i]) Storage(info());
1840
1841        setInit();
1842    }
1843
1844  public:
1845    VectorDistBase()
1846        : storage(NULL)
1847    {}
1848
1849    ~VectorDistBase()
1850    {
1851        if (!storage)
1852            return ;
1853
1854        for (off_type i = 0; i < _size; ++i)
1855            data(i)->~Storage();
1856        delete [] reinterpret_cast<char *>(storage);
1857    }
1858
1859    Proxy operator[](off_type index);
1860
1861    size_type
1862    size() const
1863    {
1864        return _size;
1865    }
1866
1867    bool
1868    zero() const
1869    {
1870        return false;
1871#if 0
1872        for (off_type i = 0; i < size(); ++i)
1873            if (!data(i)->zero())
1874                return false;
1875        return true;
1876#endif
1877    }
1878
1879    /**
1880     * Reset stat value to default
1881     */
1882    void
1883    reset()
1884    {
1885        for (off_type i = 0; i < size(); ++i)
1886            data(i)->reset(info());
1887    }
1888
1889    bool
1890    check()
1891    {
1892        return storage != NULL;
1893    }
1894
1895    void
1896    update(VectorDistInfoBase *base)
1897    {
1898        size_type size = this->size();
1899        base->data.resize(size);
1900        for (off_type i = 0; i < size; ++i) {
1901            base->data[i].fancy = Storage::fancy;
1902            data(i)->update(info(), base->data[i]);
1903        }
1904    }
1905};
1906
1907template <class Stat>
1908class DistProxy
1909{
1910  private:
1911    Stat *stat;
1912    off_type index;
1913
1914  protected:
1915    typename Stat::Storage *data() { return stat->data(index); }
1916    const typename Stat::Storage *data() const { return stat->data(index); }
1917
1918  public:
1919    DistProxy(Stat *s, off_type i)
1920        : stat(s), index(i)
1921    {}
1922
1923    DistProxy(const DistProxy &sp)
1924        : stat(sp.stat), index(sp.index)
1925    {}
1926
1927    const DistProxy &
1928    operator=(const DistProxy &sp)
1929    {
1930        stat = sp.stat;
1931        index = sp.index;
1932        return *this;
1933    }
1934
1935  public:
1936    template <typename U>
1937    void
1938    sample(const U &v, int n = 1)
1939    {
1940        data()->sample(v, n);
1941    }
1942
1943    size_type
1944    size() const
1945    {
1946        return 1;
1947    }
1948
1949    bool
1950    zero() const
1951    {
1952        return data()->zero();
1953    }
1954
1955    /**
1956     * Proxy has no state.  Nothing to reset.
1957     */
1958    void reset() { }
1959};
1960
1961template <class Storage>
1962inline typename VectorDistBase<Storage>::Proxy
1963VectorDistBase<Storage>::operator[](off_type index)
1964{
1965    assert (index >= 0 && index < size());
1966    return typename VectorDistBase<Storage>::Proxy(this, index);
1967}
1968
1969#if 0
1970template <class Storage>
1971Result
1972VectorDistBase<Storage>::total(off_type index) const
1973{
1974    Result total = 0.0;
1975    for (off_type i = 0; i < x_size(); ++i)
1976        total += data(i)->result();
1977}
1978#endif
1979
1980//////////////////////////////////////////////////////////////////////
1981//
1982//  Formula Details
1983//
1984//////////////////////////////////////////////////////////////////////
1985
1986/**
1987 * Base class for formula statistic node. These nodes are used to build a tree
1988 * that represents the formula.
1989 */
1990class Node : public RefCounted
1991{
1992  public:
1993    /**
1994     * Return the number of nodes in the subtree starting at this node.
1995     * @return the number of nodes in this subtree.
1996     */
1997    virtual size_type size() const = 0;
1998    /**
1999     * Return the result vector of this subtree.
2000     * @return The result vector of this subtree.
2001     */
2002    virtual const VResult &result() const = 0;
2003    /**
2004     * Return the total of the result vector.
2005     * @return The total of the result vector.
2006     */
2007    virtual Result total() const = 0;
2008
2009    /**
2010     *
2011     */
2012    virtual std::string str() const = 0;
2013};
2014
2015/** Reference counting pointer to a function Node. */
2016typedef RefCountingPtr<Node> NodePtr;
2017
2018class ScalarStatNode : public Node
2019{
2020  private:
2021    const ScalarInfoBase *data;
2022    mutable VResult vresult;
2023
2024  public:
2025    ScalarStatNode(const ScalarInfoBase *d) : data(d), vresult(1) {}
2026
2027    const VResult &
2028    result() const
2029    {
2030        vresult[0] = data->result();
2031        return vresult;
2032    }
2033
2034    Result total() const { return data->result(); };
2035
2036    size_type size() const { return 1; }
2037
2038    /**
2039     *
2040     */
2041    std::string str() const { return data->name; }
2042};
2043
2044template <class Stat>
2045class ScalarProxyNode : public Node
2046{
2047  private:
2048    const ScalarProxy<Stat> proxy;
2049    mutable VResult vresult;
2050
2051  public:
2052    ScalarProxyNode(const ScalarProxy<Stat> &p)
2053        : proxy(p), vresult(1)
2054    { }
2055
2056    const VResult &
2057    result() const
2058    {
2059        vresult[0] = proxy.result();
2060        return vresult;
2061    }
2062
2063    Result
2064    total() const
2065    {
2066        return proxy.result();
2067    }
2068
2069    size_type
2070    size() const
2071    {
2072        return 1;
2073    }
2074
2075    /**
2076     *
2077     */
2078    std::string
2079    str() const
2080    {
2081        return proxy.str();
2082    }
2083};
2084
2085class VectorStatNode : public Node
2086{
2087  private:
2088    const VectorInfoBase *data;
2089
2090  public:
2091    VectorStatNode(const VectorInfoBase *d) : data(d) { }
2092    const VResult &result() const { return data->result(); }
2093    Result total() const { return data->total(); };
2094
2095    size_type size() const { return data->size(); }
2096
2097    std::string str() const { return data->name; }
2098};
2099
2100template <class T>
2101class ConstNode : public Node
2102{
2103  private:
2104    VResult vresult;
2105
2106  public:
2107    ConstNode(T s) : vresult(1, (Result)s) {}
2108    const VResult &result() const { return vresult; }
2109    Result total() const { return vresult[0]; };
2110    size_type size() const { return 1; }
2111    std::string str() const { return to_string(vresult[0]); }
2112};
2113
2114template <class T>
2115class ConstVectorNode : public Node
2116{
2117  private:
2118    VResult vresult;
2119
2120  public:
2121    ConstVectorNode(const T &s) : vresult(s.begin(), s.end()) {}
2122    const VResult &result() const { return vresult; }
2123
2124    Result
2125    total() const
2126    {
2127        size_type size = this->size();
2128        Result tmp = 0;
2129        for (off_type i = 0; i < size; i++)
2130            tmp += vresult[i];
2131        return tmp;
2132    }
2133
2134    size_type size() const { return vresult.size(); }
2135    std::string
2136    str() const
2137    {
2138        size_type size = this->size();
2139        std::string tmp = "(";
2140        for (off_type i = 0; i < size; i++)
2141            tmp += csprintf("%s ",to_string(vresult[i]));
2142        tmp += ")";
2143        return tmp;
2144    }
2145};
2146
2147template <class Op>
2148struct OpString;
2149
2150template<>
2151struct OpString<std::plus<Result> >
2152{
2153    static std::string str() { return "+"; }
2154};
2155
2156template<>
2157struct OpString<std::minus<Result> >
2158{
2159    static std::string str() { return "-"; }
2160};
2161
2162template<>
2163struct OpString<std::multiplies<Result> >
2164{
2165    static std::string str() { return "*"; }
2166};
2167
2168template<>
2169struct OpString<std::divides<Result> >
2170{
2171    static std::string str() { return "/"; }
2172};
2173
2174template<>
2175struct OpString<std::modulus<Result> >
2176{
2177    static std::string str() { return "%"; }
2178};
2179
2180template<>
2181struct OpString<std::negate<Result> >
2182{
2183    static std::string str() { return "-"; }
2184};
2185
2186template <class Op>
2187class UnaryNode : public Node
2188{
2189  public:
2190    NodePtr l;
2191    mutable VResult vresult;
2192
2193  public:
2194    UnaryNode(NodePtr &p) : l(p) {}
2195
2196    const VResult &
2197    result() const
2198    {
2199        const VResult &lvec = l->result();
2200        size_type size = lvec.size();
2201
2202        assert(size > 0);
2203
2204        vresult.resize(size);
2205        Op op;
2206        for (off_type i = 0; i < size; ++i)
2207            vresult[i] = op(lvec[i]);
2208
2209        return vresult;
2210    }
2211
2212    Result
2213    total() const
2214    {
2215        const VResult &vec = this->result();
2216        Result total = 0.0;
2217        for (off_type i = 0; i < size(); i++)
2218            total += vec[i];
2219        return total;
2220    }
2221
2222    size_type size() const { return l->size(); }
2223
2224    std::string
2225    str() const
2226    {
2227        return OpString<Op>::str() + l->str();
2228    }
2229};
2230
2231template <class Op>
2232class BinaryNode : public Node
2233{
2234  public:
2235    NodePtr l;
2236    NodePtr r;
2237    mutable VResult vresult;
2238
2239  public:
2240    BinaryNode(NodePtr &a, NodePtr &b) : l(a), r(b) {}
2241
2242    const VResult &
2243    result() const
2244    {
2245        Op op;
2246        const VResult &lvec = l->result();
2247        const VResult &rvec = r->result();
2248
2249        assert(lvec.size() > 0 && rvec.size() > 0);
2250
2251        if (lvec.size() == 1 && rvec.size() == 1) {
2252            vresult.resize(1);
2253            vresult[0] = op(lvec[0], rvec[0]);
2254        } else if (lvec.size() == 1) {
2255            size_type size = rvec.size();
2256            vresult.resize(size);
2257            for (off_type i = 0; i < size; ++i)
2258                vresult[i] = op(lvec[0], rvec[i]);
2259        } else if (rvec.size() == 1) {
2260            size_type size = lvec.size();
2261            vresult.resize(size);
2262            for (off_type i = 0; i < size; ++i)
2263                vresult[i] = op(lvec[i], rvec[0]);
2264        } else if (rvec.size() == lvec.size()) {
2265            size_type size = rvec.size();
2266            vresult.resize(size);
2267            for (off_type i = 0; i < size; ++i)
2268                vresult[i] = op(lvec[i], rvec[i]);
2269        }
2270
2271        return vresult;
2272    }
2273
2274    Result
2275    total() const
2276    {
2277        const VResult &vec = this->result();
2278        Result total = 0.0;
2279        for (off_type i = 0; i < size(); i++)
2280            total += vec[i];
2281        return total;
2282    }
2283
2284    size_type
2285    size() const
2286    {
2287        size_type ls = l->size();
2288        size_type rs = r->size();
2289        if (ls == 1) {
2290            return rs;
2291        } else if (rs == 1) {
2292            return ls;
2293        } else {
2294            assert(ls == rs && "Node vector sizes are not equal");
2295            return ls;
2296        }
2297    }
2298
2299    std::string
2300    str() const
2301    {
2302        return csprintf("(%s %s %s)", l->str(), OpString<Op>::str(), r->str());
2303    }
2304};
2305
2306template <class Op>
2307class SumNode : public Node
2308{
2309  public:
2310    NodePtr l;
2311    mutable VResult vresult;
2312
2313  public:
2314    SumNode(NodePtr &p) : l(p), vresult(1) {}
2315
2316    const VResult &
2317    result() const
2318    {
2319        const VResult &lvec = l->result();
2320        size_type size = lvec.size();
2321        assert(size > 0);
2322
2323        vresult[0] = 0.0;
2324
2325        Op op;
2326        for (off_type i = 0; i < size; ++i)
2327            vresult[0] = op(vresult[0], lvec[i]);
2328
2329        return vresult;
2330    }
2331
2332    Result
2333    total() const
2334    {
2335        const VResult &lvec = l->result();
2336        size_type size = lvec.size();
2337        assert(size > 0);
2338
2339        Result vresult = 0.0;
2340
2341        Op op;
2342        for (off_type i = 0; i < size; ++i)
2343            vresult = op(vresult, lvec[i]);
2344
2345        return vresult;
2346    }
2347
2348    size_type size() const { return 1; }
2349
2350    std::string
2351    str() const
2352    {
2353        return csprintf("total(%s)", l->str());
2354    }
2355};
2356
2357
2358//////////////////////////////////////////////////////////////////////
2359//
2360// Visible Statistics Types
2361//
2362//////////////////////////////////////////////////////////////////////
2363/**
2364 * @defgroup VisibleStats "Statistic Types"
2365 * These are the statistics that are used in the simulator.
2366 * @{
2367 */
2368
2369/**
2370 * This is a simple scalar statistic, like a counter.
2371 * @sa Stat, ScalarBase, StatStor
2372 */
2373template<int N = 0>
2374class Scalar : public Wrap<Scalar<N>, ScalarBase<StatStor>, ScalarInfo>
2375{
2376  public:
2377    /** The base implementation. */
2378    typedef ScalarBase<StatStor> Base;
2379
2380    Scalar()
2381    {
2382        this->doInit();
2383    }
2384
2385    /**
2386     * Sets the stat equal to the given value. Calls the base implementation
2387     * of operator=
2388     * @param v The new value.
2389     */
2390    template <typename U>
2391    void operator=(const U &v) { Base::operator=(v); }
2392};
2393
2394class Value : public Wrap<Value, ValueBase, ScalarInfo>
2395{
2396  public:
2397    /** The base implementation. */
2398    typedef ValueBase Base;
2399
2400    template <class T>
2401    Value &
2402    scalar(T &value)
2403    {
2404        Base::scalar(value);
2405        return *this;
2406    }
2407
2408    template <class T>
2409    Value &
2410    functor(T &func)
2411    {
2412        Base::functor(func);
2413        return *this;
2414    }
2415};
2416
2417/**
2418 * A stat that calculates the per tick average of a value.
2419 * @sa Stat, ScalarBase, AvgStor
2420 */
2421template<int N = 0>
2422class Average : public Wrap<Average<N>, ScalarBase<AvgStor>, ScalarInfo>
2423{
2424  public:
2425    /** The base implementation. */
2426    typedef ScalarBase<AvgStor> Base;
2427
2428    Average()
2429    {
2430        this->doInit();
2431    }
2432
2433    /**
2434     * Sets the stat equal to the given value. Calls the base implementation
2435     * of operator=
2436     * @param v The new value.
2437     */
2438    template <typename U>
2439    void
2440    operator=(const U &v)
2441    {
2442        Base::operator=(v);
2443    }
2444};
2445
2446/**
2447 * A vector of scalar stats.
2448 * @sa Stat, VectorBase, StatStor
2449 */
2450template<int N = 0>
2451class Vector : public WrapVec<Vector<N>, VectorBase<StatStor>, VectorInfo>
2452{
2453  public:
2454    /** The base implementation. */
2455    typedef ScalarBase<StatStor> Base;
2456
2457    /**
2458     * Set this vector to have the given size.
2459     * @param size The new size.
2460     * @return A reference to this stat.
2461     */
2462    Vector &
2463    init(size_type size)
2464    {
2465        this->doInit(size);
2466        return *this;
2467    }
2468};
2469
2470/**
2471 * A vector of Average stats.
2472 * @sa Stat, VectorBase, AvgStor
2473 */
2474template<int N = 0>
2475class AverageVector
2476    : public WrapVec<AverageVector<N>, VectorBase<AvgStor>, VectorInfo>
2477{
2478  public:
2479    /**
2480     * Set this vector to have the given size.
2481     * @param size The new size.
2482     * @return A reference to this stat.
2483     */
2484    AverageVector &
2485    init(size_type size)
2486    {
2487        this->doInit(size);
2488        return *this;
2489    }
2490};
2491
2492/**
2493 * A 2-Dimensional vecto of scalar stats.
2494 * @sa Stat, Vector2dBase, StatStor
2495 */
2496template<int N = 0>
2497class Vector2d
2498    : public WrapVec2d<Vector2d<N>, Vector2dBase<StatStor>, Vector2dInfo>
2499{
2500  public:
2501    Vector2d &
2502    init(size_type x, size_type y)
2503    {
2504        this->doInit(x, y);
2505        return *this;
2506    }
2507};
2508
2509/**
2510 * A simple distribution stat.
2511 * @sa Stat, DistBase, DistStor
2512 */
2513template<int N = 0>
2514class Distribution
2515    : public Wrap<Distribution<N>, DistBase<DistStor>, DistInfo>
2516{
2517  public:
2518    /** Base implementation. */
2519    typedef DistBase<DistStor> Base;
2520
2521  public:
2522    /**
2523     * Set the parameters of this distribution. @sa DistStor::Params
2524     * @param min The minimum value of the distribution.
2525     * @param max The maximum value of the distribution.
2526     * @param bkt The number of values in each bucket.
2527     * @return A reference to this distribution.
2528     */
2529    Distribution &
2530    init(Counter min, Counter max, Counter bkt)
2531    {
2532        DistStor::Params *params = new DistStor::Params;
2533        params->min = min;
2534        params->max = max;
2535        params->bucket_size = bkt;
2536        params->buckets = (size_type)rint((max - min) / bkt + 1.0);
2537        this->setParams(params);
2538        this->doInit();
2539        return *this;
2540    }
2541};
2542
2543/**
2544 * Calculates the mean and variance of all the samples.
2545 * @sa Stat, DistBase, FancyStor
2546 */
2547template<int N = 0>
2548class StandardDeviation
2549    : public Wrap<StandardDeviation<N>, DistBase<FancyStor>, DistInfo>
2550{
2551  public:
2552    /** The base implementation */
2553    typedef DistBase<DistStor> Base;
2554
2555  public:
2556    /**
2557     * Construct and initialize this distribution.
2558     */
2559    StandardDeviation()
2560    {
2561        this->doInit();
2562    }
2563};
2564
2565/**
2566 * Calculates the per tick mean and variance of the samples.
2567 * @sa Stat, DistBase, AvgFancy
2568 */
2569template<int N = 0>
2570class AverageDeviation
2571    : public Wrap<AverageDeviation<N>, DistBase<AvgFancy>, DistInfo>
2572{
2573  public:
2574    /** The base implementation */
2575    typedef DistBase<DistStor> Base;
2576
2577  public:
2578    /**
2579     * Construct and initialize this distribution.
2580     */
2581    AverageDeviation()
2582    {
2583        this->doInit();
2584    }
2585};
2586
2587/**
2588 * A vector of distributions.
2589 * @sa Stat, VectorDistBase, DistStor
2590 */
2591template<int N = 0>
2592class VectorDistribution
2593    : public WrapVec<VectorDistribution<N>,
2594                     VectorDistBase<DistStor>,
2595                     VectorDistInfo>
2596{
2597  public:
2598    /** The base implementation */
2599    typedef VectorDistBase<DistStor> Base;
2600
2601  public:
2602    /**
2603     * Initialize storage and parameters for this distribution.
2604     * @param size The size of the vector (the number of distributions).
2605     * @param min The minimum value of the distribution.
2606     * @param max The maximum value of the distribution.
2607     * @param bkt The number of values in each bucket.
2608     * @return A reference to this distribution.
2609     */
2610    VectorDistribution &
2611    init(size_type size, Counter min, Counter max, Counter bkt)
2612    {
2613        DistStor::Params *params = new DistStor::Params;
2614        params->min = min;
2615        params->max = max;
2616        params->bucket_size = bkt;
2617        params->buckets = rint((max - min) / bkt + 1.0);
2618        this->setParams(params);
2619        this->doInit(size);
2620        return *this;
2621    }
2622};
2623
2624/**
2625 * This is a vector of StandardDeviation stats.
2626 * @sa Stat, VectorDistBase, FancyStor
2627 */
2628template<int N = 0>
2629class VectorStandardDeviation
2630    : public WrapVec<VectorStandardDeviation<N>,
2631                     VectorDistBase<FancyStor>,
2632                     VectorDistInfo>
2633{
2634  public:
2635    /** The base implementation */
2636    typedef VectorDistBase<FancyStor> Base;
2637
2638  public:
2639    /**
2640     * Initialize storage for this distribution.
2641     * @param size The size of the vector.
2642     * @return A reference to this distribution.
2643     */
2644    VectorStandardDeviation &
2645    init(size_type size)
2646    {
2647        this->doInit(size);
2648        return *this;
2649    }
2650};
2651
2652/**
2653 * This is a vector of AverageDeviation stats.
2654 * @sa Stat, VectorDistBase, AvgFancy
2655 */
2656template<int N = 0>
2657class VectorAverageDeviation
2658    : public WrapVec<VectorAverageDeviation<N>,
2659                     VectorDistBase<AvgFancy>,
2660                     VectorDistInfo>
2661{
2662  public:
2663    /** The base implementation */
2664    typedef VectorDistBase<AvgFancy> Base;
2665
2666  public:
2667    /**
2668     * Initialize storage for this distribution.
2669     * @param size The size of the vector.
2670     * @return A reference to this distribution.
2671     */
2672    VectorAverageDeviation &
2673    init(size_type size)
2674    {
2675        this->doInit(size);
2676        return *this;
2677    }
2678};
2679
2680/**
2681 * A formula for statistics that is calculated when printed. A formula is
2682 * stored as a tree of Nodes that represent the equation to calculate.
2683 * @sa Stat, ScalarStat, VectorStat, Node, Temp
2684 */
2685class FormulaBase : public InfoAccess
2686{
2687  protected:
2688    /** The root of the tree which represents the Formula */
2689    NodePtr root;
2690    friend class Temp;
2691
2692  public:
2693    /**
2694     * Return the result of the Fomula in a vector.  If there were no Vector
2695     * components to the Formula, then the vector is size 1.  If there were,
2696     * like x/y with x being a vector of size 3, then the result returned will
2697     * be x[0]/y, x[1]/y, x[2]/y, respectively.
2698     * @return The result vector.
2699     */
2700    void result(VResult &vec) const;
2701
2702    /**
2703     * Return the total Formula result.  If there is a Vector
2704     * component to this Formula, then this is the result of the
2705     * Formula if the formula is applied after summing all the
2706     * components of the Vector.  For example, if Formula is x/y where
2707     * x is size 3, then total() will return (x[1]+x[2]+x[3])/y.  If
2708     * there is no Vector component, total() returns the same value as
2709     * the first entry in the VResult val() returns.
2710     * @return The total of the result vector.
2711     */
2712    Result total() const;
2713
2714    /**
2715     * Return the number of elements in the tree.
2716     */
2717    size_type size() const;
2718
2719    bool check() const { return true; }
2720
2721    /**
2722     * Formulas don't need to be reset
2723     */
2724    void reset();
2725
2726    /**
2727     *
2728     */
2729    bool zero() const;
2730
2731    /**
2732     *
2733     */
2734    void update(Info *);
2735
2736    std::string str() const;
2737};
2738
2739class FormulaInfoBase : public VectorInfoBase
2740{
2741  public:
2742    virtual std::string str() const = 0;
2743    bool check() const { return true; }
2744};
2745
2746template <class Stat>
2747class FormulaInfo : public FormulaInfoBase
2748{
2749  protected:
2750    Stat &s;
2751    mutable VResult vec;
2752    mutable VCounter cvec;
2753
2754  public:
2755    FormulaInfo(Stat &stat) : s(stat) {}
2756
2757    bool zero() const { return s.zero(); }
2758    void reset() { s.reset(); }
2759
2760    size_type size() const { return s.size(); }
2761
2762    const VResult &
2763    result() const
2764    {
2765        s.result(vec);
2766        return vec;
2767    }
2768    Result total() const { return s.total(); }
2769    VCounter &value() const { return cvec; }
2770
2771    void
2772    visit(Visit &visitor)
2773    {
2774        update();
2775        s.update(this);
2776        visitor.visit(*this);
2777    }
2778
2779    std::string str() const { return s.str(); }
2780};
2781
2782class Temp;
2783class Formula
2784    : public WrapVec<Formula,
2785                     FormulaBase,
2786                     FormulaInfo>
2787{
2788  public:
2789    /**
2790     * Create and initialize thie formula, and register it with the database.
2791     */
2792    Formula();
2793
2794    /**
2795     * Create a formula with the given root node, register it with the
2796     * database.
2797     * @param r The root of the expression tree.
2798     */
2799    Formula(Temp r);
2800
2801    /**
2802     * Set an unitialized Formula to the given root.
2803     * @param r The root of the expression tree.
2804     * @return a reference to this formula.
2805     */
2806    const Formula &operator=(Temp r);
2807
2808    /**
2809     * Add the given tree to the existing one.
2810     * @param r The root of the expression tree.
2811     * @return a reference to this formula.
2812     */
2813    const Formula &operator+=(Temp r);
2814};
2815
2816class FormulaNode : public Node
2817{
2818  private:
2819    const Formula &formula;
2820    mutable VResult vec;
2821
2822  public:
2823    FormulaNode(const Formula &f) : formula(f) {}
2824
2825    size_type size() const { return formula.size(); }
2826    const VResult &result() const { formula.result(vec); return vec; }
2827    Result total() const { return formula.total(); }
2828
2829    std::string str() const { return formula.str(); }
2830};
2831
2832/**
2833 * Helper class to construct formula node trees.
2834 */
2835class Temp
2836{
2837  protected:
2838    /**
2839     * Pointer to a Node object.
2840     */
2841    NodePtr node;
2842
2843  public:
2844    /**
2845     * Copy the given pointer to this class.
2846     * @param n A pointer to a Node object to copy.
2847     */
2848    Temp(NodePtr n) : node(n) { }
2849
2850    /**
2851     * Return the node pointer.
2852     * @return the node pointer.
2853     */
2854    operator NodePtr&() { return node; }
2855
2856  public:
2857    /**
2858     * Create a new ScalarStatNode.
2859     * @param s The ScalarStat to place in a node.
2860     */
2861    template <int N>
2862    Temp(const Scalar<N> &s)
2863        : node(new ScalarStatNode(s.info()))
2864    { }
2865
2866    /**
2867     * Create a new ScalarStatNode.
2868     * @param s The ScalarStat to place in a node.
2869     */
2870    Temp(const Value &s)
2871        : node(new ScalarStatNode(s.info()))
2872    { }
2873
2874    /**
2875     * Create a new ScalarStatNode.
2876     * @param s The ScalarStat to place in a node.
2877     */
2878    template <int N>
2879    Temp(const Average<N> &s)
2880        : node(new ScalarStatNode(s.info()))
2881    { }
2882
2883    /**
2884     * Create a new VectorStatNode.
2885     * @param s The VectorStat to place in a node.
2886     */
2887    template <int N>
2888    Temp(const Vector<N> &s)
2889        : node(new VectorStatNode(s.info()))
2890    { }
2891
2892    /**
2893     *
2894     */
2895    Temp(const Formula &f)
2896        : node(new FormulaNode(f))
2897    { }
2898
2899    /**
2900     * Create a new ScalarProxyNode.
2901     * @param p The ScalarProxy to place in a node.
2902     */
2903    template <class Stat>
2904    Temp(const ScalarProxy<Stat> &p)
2905        : node(new ScalarProxyNode<Stat>(p))
2906    { }
2907
2908    /**
2909     * Create a ConstNode
2910     * @param value The value of the const node.
2911     */
2912    Temp(signed char value)
2913        : node(new ConstNode<signed char>(value))
2914    { }
2915
2916    /**
2917     * Create a ConstNode
2918     * @param value The value of the const node.
2919     */
2920    Temp(unsigned char value)
2921        : node(new ConstNode<unsigned char>(value))
2922    { }
2923
2924    /**
2925     * Create a ConstNode
2926     * @param value The value of the const node.
2927     */
2928    Temp(signed short value)
2929        : node(new ConstNode<signed short>(value))
2930    { }
2931
2932    /**
2933     * Create a ConstNode
2934     * @param value The value of the const node.
2935     */
2936    Temp(unsigned short value)
2937        : node(new ConstNode<unsigned short>(value))
2938    { }
2939
2940    /**
2941     * Create a ConstNode
2942     * @param value The value of the const node.
2943     */
2944    Temp(signed int value)
2945        : node(new ConstNode<signed int>(value))
2946    { }
2947
2948    /**
2949     * Create a ConstNode
2950     * @param value The value of the const node.
2951     */
2952    Temp(unsigned int value)
2953        : node(new ConstNode<unsigned int>(value))
2954    { }
2955
2956    /**
2957     * Create a ConstNode
2958     * @param value The value of the const node.
2959     */
2960    Temp(signed long value)
2961        : node(new ConstNode<signed long>(value))
2962    { }
2963
2964    /**
2965     * Create a ConstNode
2966     * @param value The value of the const node.
2967     */
2968    Temp(unsigned long value)
2969        : node(new ConstNode<unsigned long>(value))
2970    { }
2971
2972    /**
2973     * Create a ConstNode
2974     * @param value The value of the const node.
2975     */
2976    Temp(signed long long value)
2977        : node(new ConstNode<signed long long>(value))
2978    { }
2979
2980    /**
2981     * Create a ConstNode
2982     * @param value The value of the const node.
2983     */
2984    Temp(unsigned long long value)
2985        : node(new ConstNode<unsigned long long>(value))
2986    { }
2987
2988    /**
2989     * Create a ConstNode
2990     * @param value The value of the const node.
2991     */
2992    Temp(float value)
2993        : node(new ConstNode<float>(value))
2994    { }
2995
2996    /**
2997     * Create a ConstNode
2998     * @param value The value of the const node.
2999     */
3000    Temp(double value)
3001        : node(new ConstNode<double>(value))
3002    { }
3003};
3004
3005
3006/**
3007 * @}
3008 */
3009
3010void check();
3011void dump();
3012void reset();
3013void registerResetCallback(Callback *cb);
3014
3015inline Temp
3016operator+(Temp l, Temp r)
3017{
3018    return NodePtr(new BinaryNode<std::plus<Result> >(l, r));
3019}
3020
3021inline Temp
3022operator-(Temp l, Temp r)
3023{
3024    return NodePtr(new BinaryNode<std::minus<Result> >(l, r));
3025}
3026
3027inline Temp
3028operator*(Temp l, Temp r)
3029{
3030    return NodePtr(new BinaryNode<std::multiplies<Result> >(l, r));
3031}
3032
3033inline Temp
3034operator/(Temp l, Temp r)
3035{
3036    return NodePtr(new BinaryNode<std::divides<Result> >(l, r));
3037}
3038
3039inline Temp
3040operator-(Temp l)
3041{
3042    return NodePtr(new UnaryNode<std::negate<Result> >(l));
3043}
3044
3045template <typename T>
3046inline Temp
3047constant(T val)
3048{
3049    return NodePtr(new ConstNode<T>(val));
3050}
3051
3052template <typename T>
3053inline Temp
3054constantVector(T val)
3055{
3056    return NodePtr(new ConstVectorNode<T>(val));
3057}
3058
3059inline Temp
3060sum(Temp val)
3061{
3062    return NodePtr(new SumNode<std::plus<Result> >(val));
3063}
3064
3065std::list<Info *> &statsList();
3066
3067/* namespace Stats */ }
3068
3069#endif // __BASE_STATISTICS_HH__
3070