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