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