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