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