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