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