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