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