statistics.hh revision 5997:471090ec173e
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 */
2353template<int N = 0>
2354class Scalar : public DataWrap<Scalar<N>, ScalarBase<StatStor>, ScalarInfo>
2355{
2356  public:
2357    /** The base implementation. */
2358    typedef ScalarBase<StatStor> Base;
2359
2360    Scalar()
2361    {
2362        this->doInit();
2363    }
2364
2365    /**
2366     * Sets the stat equal to the given value. Calls the base implementation
2367     * of operator=
2368     * @param v The new value.
2369     */
2370    template <typename U>
2371    void operator=(const U &v) { Base::operator=(v); }
2372};
2373
2374class Value : public DataWrap<Value, ValueBase, ScalarInfo>
2375{
2376  public:
2377    /** The base implementation. */
2378    typedef ValueBase Base;
2379
2380    template <class T>
2381    Value &
2382    scalar(T &value)
2383    {
2384        Base::scalar(value);
2385        return *this;
2386    }
2387
2388    template <class T>
2389    Value &
2390    functor(T &func)
2391    {
2392        Base::functor(func);
2393        return *this;
2394    }
2395};
2396
2397/**
2398 * A stat that calculates the per tick average of a value.
2399 * @sa Stat, ScalarBase, AvgStor
2400 */
2401template<int N = 0>
2402class Average : public DataWrap<Average<N>, ScalarBase<AvgStor>, ScalarInfo>
2403{
2404  public:
2405    /** The base implementation. */
2406    typedef ScalarBase<AvgStor> Base;
2407
2408    Average()
2409    {
2410        this->doInit();
2411    }
2412
2413    /**
2414     * Sets the stat equal to the given value. Calls the base implementation
2415     * of operator=
2416     * @param v The new value.
2417     */
2418    template <typename U>
2419    void
2420    operator=(const U &v)
2421    {
2422        Base::operator=(v);
2423    }
2424};
2425
2426/**
2427 * A vector of scalar stats.
2428 * @sa Stat, VectorBase, StatStor
2429 */
2430template<int N = 0>
2431class Vector : public DataWrapVec<Vector<N>, VectorBase<StatStor>, VectorInfo>
2432{
2433  public:
2434    /** The base implementation. */
2435    typedef ScalarBase<StatStor> Base;
2436
2437    /**
2438     * Set this vector to have the given size.
2439     * @param size The new size.
2440     * @return A reference to this stat.
2441     */
2442    Vector &
2443    init(size_type size)
2444    {
2445        this->doInit(size);
2446        return *this;
2447    }
2448};
2449
2450/**
2451 * A vector of Average stats.
2452 * @sa Stat, VectorBase, AvgStor
2453 */
2454template<int N = 0>
2455class AverageVector
2456    : public DataWrapVec<AverageVector<N>, VectorBase<AvgStor>, VectorInfo>
2457{
2458  public:
2459    /**
2460     * Set this vector to have the given size.
2461     * @param size The new size.
2462     * @return A reference to this stat.
2463     */
2464    AverageVector &
2465    init(size_type size)
2466    {
2467        this->doInit(size);
2468        return *this;
2469    }
2470};
2471
2472/**
2473 * A 2-Dimensional vecto of scalar stats.
2474 * @sa Stat, Vector2dBase, StatStor
2475 */
2476template<int N = 0>
2477class Vector2d
2478    : public DataWrapVec2d<Vector2d<N>, Vector2dBase<StatStor>, Vector2dInfo>
2479{
2480  public:
2481    Vector2d &
2482    init(size_type x, size_type y)
2483    {
2484        this->doInit(x, y);
2485        return *this;
2486    }
2487};
2488
2489/**
2490 * A simple distribution stat.
2491 * @sa Stat, DistBase, DistStor
2492 */
2493template<int N = 0>
2494class Distribution
2495    : public DataWrap<Distribution<N>, DistBase<DistStor>, DistInfo>
2496{
2497  public:
2498    /** Base implementation. */
2499    typedef DistBase<DistStor> Base;
2500
2501  public:
2502    /**
2503     * Set the parameters of this distribution. @sa DistStor::Params
2504     * @param min The minimum value of the distribution.
2505     * @param max The maximum value of the distribution.
2506     * @param bkt The number of values in each bucket.
2507     * @return A reference to this distribution.
2508     */
2509    Distribution &
2510    init(Counter min, Counter max, Counter bkt)
2511    {
2512        DistStor::Params *params = new DistStor::Params;
2513        params->min = min;
2514        params->max = max;
2515        params->bucket_size = bkt;
2516        params->buckets = (size_type)rint((max - min) / bkt + 1.0);
2517        this->setParams(params);
2518        this->doInit();
2519        return *this;
2520    }
2521};
2522
2523/**
2524 * Calculates the mean and variance of all the samples.
2525 * @sa Stat, DistBase, FancyStor
2526 */
2527template<int N = 0>
2528class StandardDeviation
2529    : public DataWrap<StandardDeviation<N>, DistBase<FancyStor>, DistInfo>
2530{
2531  public:
2532    /** The base implementation */
2533    typedef DistBase<DistStor> Base;
2534
2535  public:
2536    /**
2537     * Construct and initialize this distribution.
2538     */
2539    StandardDeviation()
2540    {
2541        this->doInit();
2542    }
2543};
2544
2545/**
2546 * Calculates the per tick mean and variance of the samples.
2547 * @sa Stat, DistBase, AvgFancy
2548 */
2549template<int N = 0>
2550class AverageDeviation
2551    : public DataWrap<AverageDeviation<N>, DistBase<AvgFancy>, DistInfo>
2552{
2553  public:
2554    /** The base implementation */
2555    typedef DistBase<DistStor> Base;
2556
2557  public:
2558    /**
2559     * Construct and initialize this distribution.
2560     */
2561    AverageDeviation()
2562    {
2563        this->doInit();
2564    }
2565};
2566
2567/**
2568 * A vector of distributions.
2569 * @sa Stat, VectorDistBase, DistStor
2570 */
2571template<int N = 0>
2572class VectorDistribution
2573    : public DataWrapVec<VectorDistribution<N>,
2574                         VectorDistBase<DistStor>,
2575                         VectorDistInfo>
2576{
2577  public:
2578    /** The base implementation */
2579    typedef VectorDistBase<DistStor> Base;
2580
2581  public:
2582    /**
2583     * Initialize storage and parameters for this distribution.
2584     * @param size The size of the vector (the number of distributions).
2585     * @param min The minimum value of the distribution.
2586     * @param max The maximum value of the distribution.
2587     * @param bkt The number of values in each bucket.
2588     * @return A reference to this distribution.
2589     */
2590    VectorDistribution &
2591    init(size_type size, Counter min, Counter max, Counter bkt)
2592    {
2593        DistStor::Params *params = new DistStor::Params;
2594        params->min = min;
2595        params->max = max;
2596        params->bucket_size = bkt;
2597        params->buckets = rint((max - min) / bkt + 1.0);
2598        this->setParams(params);
2599        this->doInit(size);
2600        return *this;
2601    }
2602};
2603
2604/**
2605 * This is a vector of StandardDeviation stats.
2606 * @sa Stat, VectorDistBase, FancyStor
2607 */
2608template<int N = 0>
2609class VectorStandardDeviation
2610    : public DataWrapVec<VectorStandardDeviation<N>,
2611                         VectorDistBase<FancyStor>,
2612                         VectorDistInfo>
2613{
2614  public:
2615    /** The base implementation */
2616    typedef VectorDistBase<FancyStor> Base;
2617
2618  public:
2619    /**
2620     * Initialize storage for this distribution.
2621     * @param size The size of the vector.
2622     * @return A reference to this distribution.
2623     */
2624    VectorStandardDeviation &
2625    init(size_type size)
2626    {
2627        this->doInit(size);
2628        return *this;
2629    }
2630};
2631
2632/**
2633 * This is a vector of AverageDeviation stats.
2634 * @sa Stat, VectorDistBase, AvgFancy
2635 */
2636template<int N = 0>
2637class VectorAverageDeviation
2638    : public DataWrapVec<VectorAverageDeviation<N>,
2639                         VectorDistBase<AvgFancy>,
2640                         VectorDistInfo>
2641{
2642  public:
2643    /** The base implementation */
2644    typedef VectorDistBase<AvgFancy> Base;
2645
2646  public:
2647    /**
2648     * Initialize storage for this distribution.
2649     * @param size The size of the vector.
2650     * @return A reference to this distribution.
2651     */
2652    VectorAverageDeviation &
2653    init(size_type size)
2654    {
2655        this->doInit(size);
2656        return *this;
2657    }
2658};
2659
2660/**
2661 * A formula for statistics that is calculated when printed. A formula is
2662 * stored as a tree of Nodes that represent the equation to calculate.
2663 * @sa Stat, ScalarStat, VectorStat, Node, Temp
2664 */
2665class FormulaBase : public InfoAccess
2666{
2667  protected:
2668    /** The root of the tree which represents the Formula */
2669    NodePtr root;
2670    friend class Temp;
2671
2672  public:
2673    /**
2674     * Return the result of the Fomula in a vector.  If there were no Vector
2675     * components to the Formula, then the vector is size 1.  If there were,
2676     * like x/y with x being a vector of size 3, then the result returned will
2677     * be x[0]/y, x[1]/y, x[2]/y, respectively.
2678     * @return The result vector.
2679     */
2680    void result(VResult &vec) const;
2681
2682    /**
2683     * Return the total Formula result.  If there is a Vector
2684     * component to this Formula, then this is the result of the
2685     * Formula if the formula is applied after summing all the
2686     * components of the Vector.  For example, if Formula is x/y where
2687     * x is size 3, then total() will return (x[1]+x[2]+x[3])/y.  If
2688     * there is no Vector component, total() returns the same value as
2689     * the first entry in the VResult val() returns.
2690     * @return The total of the result vector.
2691     */
2692    Result total() const;
2693
2694    /**
2695     * Return the number of elements in the tree.
2696     */
2697    size_type size() const;
2698
2699    /**
2700     * Formulas don't need to be reset
2701     */
2702    void reset();
2703
2704    /**
2705     *
2706     */
2707    bool zero() const;
2708
2709    /**
2710     *
2711     */
2712    void update(Info *);
2713
2714    std::string str() const;
2715};
2716
2717class FormulaInfoBase : public VectorInfoBase
2718{
2719  public:
2720    virtual std::string str() const = 0;
2721};
2722
2723template <class Stat>
2724class FormulaInfo : public InfoWrap<Stat, FormulaInfoBase>
2725{
2726  protected:
2727    mutable VResult vec;
2728    mutable VCounter cvec;
2729
2730  public:
2731    FormulaInfo(Stat &stat) : InfoWrap<Stat, FormulaInfoBase>(stat) {}
2732
2733    size_type size() const { return this->s.size(); }
2734
2735    const VResult &
2736    result() const
2737    {
2738        this->s.result(vec);
2739        return vec;
2740    }
2741    Result total() const { return this->s.total(); }
2742    VCounter &value() const { return cvec; }
2743
2744    void
2745    visit(Visit &visitor)
2746    {
2747        this->update();
2748        this->s.update(this);
2749        visitor.visit(*this);
2750    }
2751
2752    std::string str() const { return this->s.str(); }
2753};
2754
2755class Temp;
2756class Formula : public DataWrapVec<Formula, FormulaBase, FormulaInfo>
2757{
2758  public:
2759    /**
2760     * Create and initialize thie formula, and register it with the database.
2761     */
2762    Formula();
2763
2764    /**
2765     * Create a formula with the given root node, register it with the
2766     * database.
2767     * @param r The root of the expression tree.
2768     */
2769    Formula(Temp r);
2770
2771    /**
2772     * Set an unitialized Formula to the given root.
2773     * @param r The root of the expression tree.
2774     * @return a reference to this formula.
2775     */
2776    const Formula &operator=(Temp r);
2777
2778    /**
2779     * Add the given tree to the existing one.
2780     * @param r The root of the expression tree.
2781     * @return a reference to this formula.
2782     */
2783    const Formula &operator+=(Temp r);
2784};
2785
2786class FormulaNode : public Node
2787{
2788  private:
2789    const Formula &formula;
2790    mutable VResult vec;
2791
2792  public:
2793    FormulaNode(const Formula &f) : formula(f) {}
2794
2795    size_type size() const { return formula.size(); }
2796    const VResult &result() const { formula.result(vec); return vec; }
2797    Result total() const { return formula.total(); }
2798
2799    std::string str() const { return formula.str(); }
2800};
2801
2802/**
2803 * Helper class to construct formula node trees.
2804 */
2805class Temp
2806{
2807  protected:
2808    /**
2809     * Pointer to a Node object.
2810     */
2811    NodePtr node;
2812
2813  public:
2814    /**
2815     * Copy the given pointer to this class.
2816     * @param n A pointer to a Node object to copy.
2817     */
2818    Temp(NodePtr n) : node(n) { }
2819
2820    /**
2821     * Return the node pointer.
2822     * @return the node pointer.
2823     */
2824    operator NodePtr&() { return node; }
2825
2826  public:
2827    /**
2828     * Create a new ScalarStatNode.
2829     * @param s The ScalarStat to place in a node.
2830     */
2831    template <int N>
2832    Temp(const Scalar<N> &s)
2833        : node(new ScalarStatNode(s.info()))
2834    { }
2835
2836    /**
2837     * Create a new ScalarStatNode.
2838     * @param s The ScalarStat to place in a node.
2839     */
2840    Temp(const Value &s)
2841        : node(new ScalarStatNode(s.info()))
2842    { }
2843
2844    /**
2845     * Create a new ScalarStatNode.
2846     * @param s The ScalarStat to place in a node.
2847     */
2848    template <int N>
2849    Temp(const Average<N> &s)
2850        : node(new ScalarStatNode(s.info()))
2851    { }
2852
2853    /**
2854     * Create a new VectorStatNode.
2855     * @param s The VectorStat to place in a node.
2856     */
2857    template <int N>
2858    Temp(const Vector<N> &s)
2859        : node(new VectorStatNode(s.info()))
2860    { }
2861
2862    /**
2863     *
2864     */
2865    Temp(const Formula &f)
2866        : node(new FormulaNode(f))
2867    { }
2868
2869    /**
2870     * Create a new ScalarProxyNode.
2871     * @param p The ScalarProxy to place in a node.
2872     */
2873    template <class Stat>
2874    Temp(const ScalarProxy<Stat> &p)
2875        : node(new ScalarProxyNode<Stat>(p))
2876    { }
2877
2878    /**
2879     * Create a ConstNode
2880     * @param value The value of the const node.
2881     */
2882    Temp(signed char value)
2883        : node(new ConstNode<signed char>(value))
2884    { }
2885
2886    /**
2887     * Create a ConstNode
2888     * @param value The value of the const node.
2889     */
2890    Temp(unsigned char value)
2891        : node(new ConstNode<unsigned char>(value))
2892    { }
2893
2894    /**
2895     * Create a ConstNode
2896     * @param value The value of the const node.
2897     */
2898    Temp(signed short value)
2899        : node(new ConstNode<signed short>(value))
2900    { }
2901
2902    /**
2903     * Create a ConstNode
2904     * @param value The value of the const node.
2905     */
2906    Temp(unsigned short value)
2907        : node(new ConstNode<unsigned short>(value))
2908    { }
2909
2910    /**
2911     * Create a ConstNode
2912     * @param value The value of the const node.
2913     */
2914    Temp(signed int value)
2915        : node(new ConstNode<signed int>(value))
2916    { }
2917
2918    /**
2919     * Create a ConstNode
2920     * @param value The value of the const node.
2921     */
2922    Temp(unsigned int value)
2923        : node(new ConstNode<unsigned int>(value))
2924    { }
2925
2926    /**
2927     * Create a ConstNode
2928     * @param value The value of the const node.
2929     */
2930    Temp(signed long value)
2931        : node(new ConstNode<signed long>(value))
2932    { }
2933
2934    /**
2935     * Create a ConstNode
2936     * @param value The value of the const node.
2937     */
2938    Temp(unsigned long value)
2939        : node(new ConstNode<unsigned long>(value))
2940    { }
2941
2942    /**
2943     * Create a ConstNode
2944     * @param value The value of the const node.
2945     */
2946    Temp(signed long long value)
2947        : node(new ConstNode<signed long long>(value))
2948    { }
2949
2950    /**
2951     * Create a ConstNode
2952     * @param value The value of the const node.
2953     */
2954    Temp(unsigned long long value)
2955        : node(new ConstNode<unsigned long long>(value))
2956    { }
2957
2958    /**
2959     * Create a ConstNode
2960     * @param value The value of the const node.
2961     */
2962    Temp(float value)
2963        : node(new ConstNode<float>(value))
2964    { }
2965
2966    /**
2967     * Create a ConstNode
2968     * @param value The value of the const node.
2969     */
2970    Temp(double value)
2971        : node(new ConstNode<double>(value))
2972    { }
2973};
2974
2975
2976/**
2977 * @}
2978 */
2979
2980void check();
2981void dump();
2982void reset();
2983void registerResetCallback(Callback *cb);
2984
2985inline Temp
2986operator+(Temp l, Temp r)
2987{
2988    return NodePtr(new BinaryNode<std::plus<Result> >(l, r));
2989}
2990
2991inline Temp
2992operator-(Temp l, Temp r)
2993{
2994    return NodePtr(new BinaryNode<std::minus<Result> >(l, r));
2995}
2996
2997inline Temp
2998operator*(Temp l, Temp r)
2999{
3000    return NodePtr(new BinaryNode<std::multiplies<Result> >(l, r));
3001}
3002
3003inline Temp
3004operator/(Temp l, Temp r)
3005{
3006    return NodePtr(new BinaryNode<std::divides<Result> >(l, r));
3007}
3008
3009inline Temp
3010operator-(Temp l)
3011{
3012    return NodePtr(new UnaryNode<std::negate<Result> >(l));
3013}
3014
3015template <typename T>
3016inline Temp
3017constant(T val)
3018{
3019    return NodePtr(new ConstNode<T>(val));
3020}
3021
3022template <typename T>
3023inline Temp
3024constantVector(T val)
3025{
3026    return NodePtr(new ConstVectorNode<T>(val));
3027}
3028
3029inline Temp
3030sum(Temp val)
3031{
3032    return NodePtr(new SumNode<std::plus<Result> >(val));
3033}
3034
3035std::list<Info *> &statsList();
3036
3037/* namespace Stats */ }
3038
3039#endif // __BASE_STATISTICS_HH__
3040