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