statistics.hh revision 5547:747034106af4
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->str(), index);
1013
1014    }
1015};
1016
1017/**
1018 * Implementation of a vector of stats. The type of stat is determined by the
1019 * Storage class. @sa ScalarBase
1020 */
1021template <class Stor>
1022class VectorBase : public DataAccess
1023{
1024  public:
1025    typedef Stor Storage;
1026
1027    /** Define the params of the storage class. */
1028    typedef typename Storage::Params Params;
1029
1030    /** Proxy type */
1031    typedef ScalarProxy<VectorBase<Storage> > Proxy;
1032
1033    friend class ScalarProxy<VectorBase<Storage> >;
1034
1035  protected:
1036    /** The storage of this stat. */
1037    Storage *storage;
1038    size_t _size;
1039
1040    /** The parameters for this stat. */
1041    Params params;
1042
1043  protected:
1044    /**
1045     * Retrieve the storage.
1046     * @param index The vector index to access.
1047     * @return The storage object at the given index.
1048     */
1049    Storage *data(int index) { return &storage[index]; }
1050
1051    /**
1052     * Retrieve a const pointer to the storage.
1053     * @param index The vector index to access.
1054     * @return A const pointer to the storage object at the given index.
1055     */
1056    const Storage *data(int index) const { return &storage[index]; }
1057
1058    void
1059    doInit(int s)
1060    {
1061        assert(s > 0 && "size must be positive!");
1062        assert(!storage && "already initialized");
1063        _size = s;
1064
1065        char *ptr = new char[_size * sizeof(Storage)];
1066        storage = reinterpret_cast<Storage *>(ptr);
1067
1068        for (int i = 0; i < _size; ++i)
1069            new (&storage[i]) Storage(params);
1070
1071        setInit();
1072    }
1073
1074  public:
1075    void value(VCounter &vec) const
1076    {
1077        vec.resize(size());
1078        for (int i = 0; i < size(); ++i)
1079            vec[i] = data(i)->value(params);
1080    }
1081
1082    /**
1083     * Copy the values to a local vector and return a reference to it.
1084     * @return A reference to a vector of the stat values.
1085     */
1086    void result(VResult &vec) const
1087    {
1088        vec.resize(size());
1089        for (int i = 0; i < size(); ++i)
1090            vec[i] = data(i)->result(params);
1091    }
1092
1093    /**
1094     * Return a total of all entries in this vector.
1095     * @return The total of all vector entries.
1096     */
1097    Result total() const {
1098        Result total = 0.0;
1099        for (int i = 0; i < size(); ++i)
1100            total += data(i)->result(params);
1101        return total;
1102    }
1103
1104    /**
1105     * @return the number of elements in this vector.
1106     */
1107    size_t size() const { return _size; }
1108
1109    bool
1110    zero() const
1111    {
1112        for (int i = 0; i < size(); ++i)
1113            if (data(i)->zero())
1114                return false;
1115        return true;
1116    }
1117
1118    bool
1119    check() const
1120    {
1121        return storage != NULL;
1122    }
1123
1124    void
1125    reset()
1126    {
1127        for (int i = 0; i < size(); ++i)
1128            data(i)->reset();
1129    }
1130
1131  public:
1132    VectorBase()
1133        : storage(NULL)
1134    {}
1135
1136    ~VectorBase()
1137    {
1138        if (!storage)
1139            return;
1140
1141        for (int i = 0; i < _size; ++i)
1142            data(i)->~Storage();
1143        delete [] reinterpret_cast<char *>(storage);
1144    }
1145
1146    /**
1147     * Return a reference (ScalarProxy) to the stat at the given index.
1148     * @param index The vector index to access.
1149     * @return A reference of the stat.
1150     */
1151    Proxy
1152    operator[](int index)
1153    {
1154        assert (index >= 0 && index < size());
1155        return Proxy(this, index);
1156    }
1157
1158    void update(StatData *data) {}
1159};
1160
1161template <class Stat>
1162class VectorProxy
1163{
1164  private:
1165    Stat *stat;
1166    int offset;
1167    int len;
1168
1169  private:
1170    mutable VResult vec;
1171
1172    typename Stat::Storage *
1173    data(int index)
1174    {
1175        assert(index < len);
1176        return stat->data(offset + index);
1177    }
1178
1179    const typename Stat::Storage *
1180    data(int index) const
1181    {
1182        assert(index < len);
1183        return const_cast<Stat *>(stat)->data(offset + index);
1184    }
1185
1186  public:
1187    const VResult &
1188    result() const
1189    {
1190        vec.resize(size());
1191
1192        for (int i = 0; i < size(); ++i)
1193            vec[i] = data(i)->result(stat->params);
1194
1195        return vec;
1196    }
1197
1198    Result
1199    total() const
1200    {
1201        Result total = 0;
1202        for (int i = 0; i < size(); ++i)
1203            total += data(i)->result(stat->params);
1204        return total;
1205    }
1206
1207  public:
1208    VectorProxy(Stat *s, int o, int l)
1209        : stat(s), offset(o), len(l)
1210    {
1211    }
1212
1213    VectorProxy(const VectorProxy &sp)
1214        : stat(sp.stat), offset(sp.offset), len(sp.len)
1215    {
1216    }
1217
1218    const VectorProxy &
1219    operator=(const VectorProxy &sp)
1220    {
1221        stat = sp.stat;
1222        offset = sp.offset;
1223        len = sp.len;
1224        return *this;
1225    }
1226
1227    ScalarProxy<Stat> operator[](int index)
1228    {
1229        assert (index >= 0 && index < size());
1230        return ScalarProxy<Stat>(stat, offset + index);
1231    }
1232
1233    size_t size() const { return len; }
1234
1235    /**
1236     * This stat has no state.  Nothing to reset.
1237     */
1238    void reset() { }
1239};
1240
1241template <class Stor>
1242class Vector2dBase : public DataAccess
1243{
1244  public:
1245    typedef Stor Storage;
1246    typedef typename Storage::Params Params;
1247    typedef VectorProxy<Vector2dBase<Storage> > Proxy;
1248    friend class ScalarProxy<Vector2dBase<Storage> >;
1249    friend class VectorProxy<Vector2dBase<Storage> >;
1250
1251  protected:
1252    size_t x;
1253    size_t y;
1254    size_t _size;
1255    Storage *storage;
1256    Params params;
1257
1258  protected:
1259    Storage *data(int index) { return &storage[index]; }
1260    const Storage *data(int index) const { return &storage[index]; }
1261
1262    void
1263    doInit(int _x, int _y)
1264    {
1265        assert(_x > 0 && _y > 0 && "sizes must be positive!");
1266        assert(!storage && "already initialized");
1267
1268        Vector2dData *statdata = dynamic_cast<Vector2dData *>(find());
1269
1270        x = _x;
1271        y = _y;
1272        statdata->x = _x;
1273        statdata->y = _y;
1274        _size = x * y;
1275
1276        char *ptr = new char[_size * sizeof(Storage)];
1277        storage = reinterpret_cast<Storage *>(ptr);
1278
1279        for (int i = 0; i < _size; ++i)
1280            new (&storage[i]) Storage(params);
1281
1282        setInit();
1283    }
1284
1285  public:
1286    Vector2dBase()
1287        : storage(NULL)
1288    {}
1289
1290    ~Vector2dBase()
1291    {
1292        if (!storage)
1293            return;
1294
1295        for (int i = 0; i < _size; ++i)
1296            data(i)->~Storage();
1297        delete [] reinterpret_cast<char *>(storage);
1298    }
1299
1300    void
1301    update(Vector2dData *newdata)
1302    {
1303        int size = this->size();
1304        newdata->cvec.resize(size);
1305        for (int i = 0; i < size; ++i)
1306            newdata->cvec[i] = data(i)->value(params);
1307    }
1308
1309    std::string ysubname(int i) const { return (*this->y_subnames)[i]; }
1310
1311    Proxy
1312    operator[](int index)
1313    {
1314        int offset = index * y;
1315        assert (index >= 0 && offset + index < size());
1316        return Proxy(this, offset, y);
1317    }
1318
1319
1320    size_t
1321    size() const
1322    {
1323        return _size;
1324    }
1325
1326    bool
1327    zero() const
1328    {
1329        return data(0)->zero();
1330#if 0
1331        for (int i = 0; i < size(); ++i)
1332            if (!data(i)->zero())
1333                return false;
1334        return true;
1335#endif
1336    }
1337
1338    /**
1339     * Reset stat value to default
1340     */
1341    void
1342    reset()
1343    {
1344        for (int i = 0; i < size(); ++i)
1345            data(i)->reset();
1346    }
1347
1348    bool
1349    check()
1350    {
1351        return storage != NULL;
1352    }
1353};
1354
1355//////////////////////////////////////////////////////////////////////
1356//
1357// Non formula statistics
1358//
1359//////////////////////////////////////////////////////////////////////
1360
1361/**
1362 * Templatized storage and interface for a distrbution stat.
1363 */
1364struct DistStor
1365{
1366  public:
1367    /** The parameters for a distribution stat. */
1368    struct Params
1369    {
1370        /** The minimum value to track. */
1371        Counter min;
1372        /** The maximum value to track. */
1373        Counter max;
1374        /** The number of entries in each bucket. */
1375        Counter bucket_size;
1376        /** The number of buckets. Equal to (max-min)/bucket_size. */
1377        int size;
1378    };
1379    enum { fancy = false };
1380
1381  private:
1382    /** The smallest value sampled. */
1383    Counter min_val;
1384    /** The largest value sampled. */
1385    Counter max_val;
1386    /** The number of values sampled less than min. */
1387    Counter underflow;
1388    /** The number of values sampled more than max. */
1389    Counter overflow;
1390    /** The current sum. */
1391    Counter sum;
1392    /** The sum of squares. */
1393    Counter squares;
1394    /** The number of samples. */
1395    Counter samples;
1396    /** Counter for each bucket. */
1397    VCounter cvec;
1398
1399  public:
1400    DistStor(const Params &params)
1401        : cvec(params.size)
1402    {
1403        reset();
1404    }
1405
1406    /**
1407     * Add a value to the distribution for the given number of times.
1408     * @param val The value to add.
1409     * @param number The number of times to add the value.
1410     * @param params The paramters of the distribution.
1411     */
1412    void sample(Counter val, int number, const Params &params)
1413    {
1414        if (val < params.min)
1415            underflow += number;
1416        else if (val > params.max)
1417            overflow += number;
1418        else {
1419            int index = (int)std::floor((val - params.min) / params.bucket_size);
1420            assert(index < size(params));
1421            cvec[index] += number;
1422        }
1423
1424        if (val < min_val)
1425            min_val = val;
1426
1427        if (val > max_val)
1428            max_val = val;
1429
1430        Counter sample = val * number;
1431        sum += sample;
1432        squares += sample * sample;
1433        samples += number;
1434    }
1435
1436    /**
1437     * Return the number of buckets in this distribution.
1438     * @return the number of buckets.
1439     * @todo Is it faster to return the size from the parameters?
1440     */
1441    size_t size(const Params &) const { return cvec.size(); }
1442
1443    /**
1444     * Returns true if any calls to sample have been made.
1445     * @param params The paramters of the distribution.
1446     * @return True if any values have been sampled.
1447     */
1448    bool zero(const Params &params) const
1449    {
1450        return samples == Counter();
1451    }
1452
1453    void update(DistDataData *data, const Params &params)
1454    {
1455        data->min = params.min;
1456        data->max = params.max;
1457        data->bucket_size = params.bucket_size;
1458        data->size = params.size;
1459
1460        data->min_val = (min_val == CounterLimits::max()) ? 0 : min_val;
1461        data->max_val = (max_val == CounterLimits::min()) ? 0 : max_val;
1462        data->underflow = underflow;
1463        data->overflow = overflow;
1464        data->cvec.resize(params.size);
1465        for (int i = 0; i < params.size; ++i)
1466            data->cvec[i] = cvec[i];
1467
1468        data->sum = sum;
1469        data->squares = squares;
1470        data->samples = samples;
1471    }
1472
1473    /**
1474     * Reset stat value to default
1475     */
1476    void reset()
1477    {
1478        min_val = CounterLimits::max();
1479        max_val = CounterLimits::min();
1480        underflow = 0;
1481        overflow = 0;
1482
1483        int size = cvec.size();
1484        for (int i = 0; i < size; ++i)
1485            cvec[i] = Counter();
1486
1487        sum = Counter();
1488        squares = Counter();
1489        samples = Counter();
1490    }
1491};
1492
1493/**
1494 * Templatized storage and interface for a distribution that calculates mean
1495 * and variance.
1496 */
1497struct FancyStor
1498{
1499  public:
1500    /**
1501     * No paramters for this storage.
1502     */
1503    struct Params {};
1504    enum { fancy = true };
1505
1506  private:
1507    /** The current sum. */
1508    Counter sum;
1509    /** The sum of squares. */
1510    Counter squares;
1511    /** The number of samples. */
1512    Counter samples;
1513
1514  public:
1515    /**
1516     * Create and initialize this storage.
1517     */
1518    FancyStor(const Params &)
1519        : sum(Counter()), squares(Counter()), samples(Counter())
1520    { }
1521
1522    /**
1523     * Add a value the given number of times to this running average.
1524     * Update the running sum and sum of squares, increment the number of
1525     * values seen by the given number.
1526     * @param val The value to add.
1527     * @param number The number of times to add the value.
1528     * @param p The parameters of this stat.
1529     */
1530    void sample(Counter val, int number, const Params &p)
1531    {
1532        Counter value = val * number;
1533        sum += value;
1534        squares += value * value;
1535        samples += number;
1536    }
1537
1538    void update(DistDataData *data, const Params &params)
1539    {
1540        data->sum = sum;
1541        data->squares = squares;
1542        data->samples = samples;
1543    }
1544
1545    /**
1546     * Return the number of entries in this stat, 1
1547     * @return 1.
1548     */
1549    size_t size(const Params &) const { return 1; }
1550
1551    /**
1552     * Return true if no samples have been added.
1553     * @return True if no samples have been added.
1554     */
1555    bool zero(const Params &) const { return samples == Counter(); }
1556
1557    /**
1558     * Reset stat value to default
1559     */
1560    void reset()
1561    {
1562        sum = Counter();
1563        squares = Counter();
1564        samples = Counter();
1565    }
1566};
1567
1568/**
1569 * Templatized storage for distribution that calculates per tick mean and
1570 * variance.
1571 */
1572struct AvgFancy
1573{
1574  public:
1575    /** No parameters for this storage. */
1576    struct Params {};
1577    enum { fancy = true };
1578
1579  private:
1580    /** Current total. */
1581    Counter sum;
1582    /** Current sum of squares. */
1583    Counter squares;
1584
1585  public:
1586    /**
1587     * Create and initialize this storage.
1588     */
1589    AvgFancy(const Params &) : sum(Counter()), squares(Counter()) {}
1590
1591    /**
1592     * Add a value to the distribution for the given number of times.
1593     * Update the running sum and sum of squares.
1594     * @param val The value to add.
1595     * @param number The number of times to add the value.
1596     * @param p The paramters of the distribution.
1597     */
1598    void sample(Counter val, int number, const Params &p)
1599    {
1600        Counter value = val * number;
1601        sum += value;
1602        squares += value * value;
1603    }
1604
1605    void update(DistDataData *data, const Params &params)
1606    {
1607        data->sum = sum;
1608        data->squares = squares;
1609        data->samples = curTick;
1610    }
1611
1612    /**
1613     * Return the number of entries, in this case 1.
1614     * @return 1.
1615     */
1616    size_t size(const Params &params) const { return 1; }
1617    /**
1618     * Return true if no samples have been added.
1619     * @return True if the sum is zero.
1620     */
1621    bool zero(const Params &params) const { return sum == Counter(); }
1622    /**
1623     * Reset stat value to default
1624     */
1625    void reset()
1626    {
1627        sum = Counter();
1628        squares = Counter();
1629    }
1630};
1631
1632/**
1633 * Implementation of a distribution stat. The type of distribution is
1634 * determined by the Storage template. @sa ScalarBase
1635 */
1636template <class Stor>
1637class DistBase : public DataAccess
1638{
1639  public:
1640    typedef Stor Storage;
1641    /** Define the params of the storage class. */
1642    typedef typename Storage::Params Params;
1643
1644  protected:
1645    /** The storage for this stat. */
1646    char storage[sizeof(Storage)] __attribute__ ((aligned (8)));
1647
1648    /** The parameters for this stat. */
1649    Params params;
1650
1651  protected:
1652    /**
1653     * Retrieve the storage.
1654     * @return The storage object for this stat.
1655     */
1656    Storage *data()
1657    {
1658        return reinterpret_cast<Storage *>(storage);
1659    }
1660
1661    /**
1662     * Retrieve a const pointer to the storage.
1663     * @return A const pointer to the storage object for this stat.
1664     */
1665    const Storage *
1666    data() const
1667    {
1668        return reinterpret_cast<const Storage *>(storage);
1669    }
1670
1671    void
1672    doInit()
1673    {
1674        new (storage) Storage(params);
1675        setInit();
1676    }
1677
1678  public:
1679    DistBase() { }
1680
1681    /**
1682     * Add a value to the distribtion n times. Calls sample on the storage
1683     * class.
1684     * @param v The value to add.
1685     * @param n The number of times to add it, defaults to 1.
1686     */
1687    template <typename U>
1688    void sample(const U &v, int n = 1) { data()->sample(v, n, params); }
1689
1690    /**
1691     * Return the number of entries in this stat.
1692     * @return The number of entries.
1693     */
1694    size_t size() const { return data()->size(params); }
1695    /**
1696     * Return true if no samples have been added.
1697     * @return True if there haven't been any samples.
1698     */
1699    bool zero() const { return data()->zero(params); }
1700
1701    void update(DistData *base)
1702    {
1703        base->data.fancy = Storage::fancy;
1704        data()->update(&(base->data), params);
1705    }
1706
1707    /**
1708     * Reset stat value to default
1709     */
1710    void
1711    reset()
1712    {
1713        data()->reset();
1714    }
1715
1716    bool
1717    check()
1718    {
1719        return true;
1720    }
1721};
1722
1723template <class Stat>
1724class DistProxy;
1725
1726template <class Stor>
1727class VectorDistBase : public DataAccess
1728{
1729  public:
1730    typedef Stor Storage;
1731    typedef typename Storage::Params Params;
1732    typedef DistProxy<VectorDistBase<Storage> > Proxy;
1733    friend class DistProxy<VectorDistBase<Storage> >;
1734
1735  protected:
1736    Storage *storage;
1737    size_t _size;
1738    Params params;
1739
1740  protected:
1741    Storage *
1742    data(int index)
1743    {
1744        return &storage[index];
1745    }
1746
1747    const Storage *
1748    data(int index) const
1749    {
1750        return &storage[index];
1751    }
1752
1753    void
1754    doInit(int s)
1755    {
1756        assert(s > 0 && "size must be positive!");
1757        assert(!storage && "already initialized");
1758        _size = s;
1759
1760        char *ptr = new char[_size * sizeof(Storage)];
1761        storage = reinterpret_cast<Storage *>(ptr);
1762
1763        for (int i = 0; i < _size; ++i)
1764            new (&storage[i]) Storage(params);
1765
1766        setInit();
1767    }
1768
1769  public:
1770    VectorDistBase()
1771        : storage(NULL)
1772    {}
1773
1774    ~VectorDistBase()
1775    {
1776        if (!storage)
1777            return ;
1778
1779        for (int i = 0; i < _size; ++i)
1780            data(i)->~Storage();
1781        delete [] reinterpret_cast<char *>(storage);
1782    }
1783
1784    Proxy operator[](int index);
1785
1786    size_t
1787    size() const
1788    {
1789        return _size;
1790    }
1791
1792    bool
1793    zero() const
1794    {
1795        return false;
1796#if 0
1797        for (int i = 0; i < size(); ++i)
1798            if (!data(i)->zero(params))
1799                return false;
1800        return true;
1801#endif
1802    }
1803
1804    /**
1805     * Reset stat value to default
1806     */
1807    void
1808    reset()
1809    {
1810        for (int i = 0; i < size(); ++i)
1811            data(i)->reset();
1812    }
1813
1814    bool
1815    check()
1816    {
1817        return storage != NULL;
1818    }
1819
1820    void
1821    update(VectorDistData *base)
1822    {
1823        int size = this->size();
1824        base->data.resize(size);
1825        for (int i = 0; i < size; ++i) {
1826            base->data[i].fancy = Storage::fancy;
1827            data(i)->update(&(base->data[i]), params);
1828        }
1829    }
1830};
1831
1832template <class Stat>
1833class DistProxy
1834{
1835  private:
1836    Stat *stat;
1837    int index;
1838
1839  protected:
1840    typename Stat::Storage *data() { return stat->data(index); }
1841    const typename Stat::Storage *data() const { return stat->data(index); }
1842
1843  public:
1844    DistProxy(Stat *s, int i)
1845        : stat(s), index(i)
1846    {}
1847
1848    DistProxy(const DistProxy &sp)
1849        : stat(sp.stat), index(sp.index)
1850    {}
1851
1852    const DistProxy &operator=(const DistProxy &sp)
1853    {
1854        stat = sp.stat;
1855        index = sp.index;
1856        return *this;
1857    }
1858
1859  public:
1860    template <typename U>
1861    void
1862    sample(const U &v, int n = 1)
1863    {
1864        data()->sample(v, n, stat->params);
1865    }
1866
1867    size_t
1868    size() const
1869    {
1870        return 1;
1871    }
1872
1873    bool
1874    zero() const
1875    {
1876        return data()->zero(stat->params);
1877    }
1878
1879    /**
1880     * Proxy has no state.  Nothing to reset.
1881     */
1882    void reset() { }
1883};
1884
1885template <class Storage>
1886inline typename VectorDistBase<Storage>::Proxy
1887VectorDistBase<Storage>::operator[](int index)
1888{
1889    assert (index >= 0 && index < size());
1890    return typename VectorDistBase<Storage>::Proxy(this, index);
1891}
1892
1893#if 0
1894template <class Storage>
1895Result
1896VectorDistBase<Storage>::total(int index) const
1897{
1898    int total = 0;
1899    for (int i = 0; i < x_size(); ++i) {
1900        total += data(i)->result(stat->params);
1901    }
1902}
1903#endif
1904
1905//////////////////////////////////////////////////////////////////////
1906//
1907//  Formula Details
1908//
1909//////////////////////////////////////////////////////////////////////
1910
1911/**
1912 * Base class for formula statistic node. These nodes are used to build a tree
1913 * that represents the formula.
1914 */
1915class Node : public RefCounted
1916{
1917  public:
1918    /**
1919     * Return the number of nodes in the subtree starting at this node.
1920     * @return the number of nodes in this subtree.
1921     */
1922    virtual size_t size() const = 0;
1923    /**
1924     * Return the result vector of this subtree.
1925     * @return The result vector of this subtree.
1926     */
1927    virtual const VResult &result() const = 0;
1928    /**
1929     * Return the total of the result vector.
1930     * @return The total of the result vector.
1931     */
1932    virtual Result total() const = 0;
1933
1934    /**
1935     *
1936     */
1937    virtual std::string str() const = 0;
1938};
1939
1940/** Reference counting pointer to a function Node. */
1941typedef RefCountingPtr<Node> NodePtr;
1942
1943class ScalarStatNode : public Node
1944{
1945  private:
1946    const ScalarData *data;
1947    mutable VResult vresult;
1948
1949  public:
1950    ScalarStatNode(const ScalarData *d) : data(d), vresult(1) {}
1951    virtual const VResult &result() const
1952    {
1953        vresult[0] = data->result();
1954        return vresult;
1955    }
1956    virtual Result total() const { return data->result(); };
1957
1958    virtual size_t size() const { return 1; }
1959
1960    /**
1961     *
1962     */
1963    virtual std::string str() const { return data->name; }
1964};
1965
1966template <class Stat>
1967class ScalarProxyNode : public Node
1968{
1969  private:
1970    const ScalarProxy<Stat> proxy;
1971    mutable VResult vresult;
1972
1973  public:
1974    ScalarProxyNode(const ScalarProxy<Stat> &p)
1975        : proxy(p), vresult(1)
1976    { }
1977
1978    virtual const VResult &
1979    result() const
1980    {
1981        vresult[0] = proxy.result();
1982        return vresult;
1983    }
1984
1985    virtual Result
1986    total() const
1987    {
1988        return proxy.result();
1989    }
1990
1991    virtual size_t
1992    size() const
1993    {
1994        return 1;
1995    }
1996
1997    /**
1998     *
1999     */
2000    virtual std::string
2001    str() const
2002    {
2003        return proxy.str();
2004    }
2005};
2006
2007class VectorStatNode : public Node
2008{
2009  private:
2010    const VectorData *data;
2011
2012  public:
2013    VectorStatNode(const VectorData *d) : data(d) { }
2014    virtual const VResult &result() const { return data->result(); }
2015    virtual Result total() const { return data->total(); };
2016
2017    virtual size_t size() const { return data->size(); }
2018
2019    virtual std::string str() const { return data->name; }
2020};
2021
2022template <class T>
2023class ConstNode : public Node
2024{
2025  private:
2026    VResult vresult;
2027
2028  public:
2029    ConstNode(T s) : vresult(1, (Result)s) {}
2030    const VResult &result() const { return vresult; }
2031    virtual Result total() const { return vresult[0]; };
2032    virtual size_t size() const { return 1; }
2033    virtual std::string str() const { return to_string(vresult[0]); }
2034};
2035
2036template <class T>
2037class ConstVectorNode : public Node
2038{
2039  private:
2040    VResult vresult;
2041
2042  public:
2043    ConstVectorNode(const T &s) : vresult(s.begin(), s.end()) {}
2044    const VResult &result() const { return vresult; }
2045    virtual Result total() const
2046    {
2047        int size = this->size();
2048        Result tmp = 0;
2049        for (int i = 0; i < size; i++)
2050        {
2051            tmp += vresult[i];
2052        }
2053        return tmp;
2054    }
2055    virtual size_t size() const { return vresult.size(); }
2056    virtual std::string str() const
2057    {
2058        int size = this->size();
2059        std::string tmp = "(";
2060        for (int i = 0; i < size; i++)
2061        {
2062            tmp += csprintf("%s ",to_string(vresult[i]));
2063        }
2064        tmp += ")";
2065        return tmp;
2066    }
2067};
2068
2069template <class Op>
2070struct OpString;
2071
2072template<>
2073struct OpString<std::plus<Result> >
2074{
2075    static std::string str() { return "+"; }
2076};
2077
2078template<>
2079struct OpString<std::minus<Result> >
2080{
2081    static std::string str() { return "-"; }
2082};
2083
2084template<>
2085struct OpString<std::multiplies<Result> >
2086{
2087    static std::string str() { return "*"; }
2088};
2089
2090template<>
2091struct OpString<std::divides<Result> >
2092{
2093    static std::string str() { return "/"; }
2094};
2095
2096template<>
2097struct OpString<std::modulus<Result> >
2098{
2099    static std::string str() { return "%"; }
2100};
2101
2102template<>
2103struct OpString<std::negate<Result> >
2104{
2105    static std::string str() { return "-"; }
2106};
2107
2108template <class Op>
2109class UnaryNode : public Node
2110{
2111  public:
2112    NodePtr l;
2113    mutable VResult vresult;
2114
2115  public:
2116    UnaryNode(NodePtr &p) : l(p) {}
2117
2118    const VResult &result() const
2119    {
2120        const VResult &lvec = l->result();
2121        int size = lvec.size();
2122
2123        assert(size > 0);
2124
2125        vresult.resize(size);
2126        Op op;
2127        for (int i = 0; i < size; ++i)
2128            vresult[i] = op(lvec[i]);
2129
2130        return vresult;
2131    }
2132
2133    Result total() const
2134    {
2135        const VResult &vec = this->result();
2136        Result total = 0;
2137        for (int i = 0; i < size(); i++)
2138            total += vec[i];
2139        return total;
2140    }
2141
2142    virtual size_t size() const { return l->size(); }
2143
2144    virtual std::string str() const
2145    {
2146        return OpString<Op>::str() + l->str();
2147    }
2148};
2149
2150template <class Op>
2151class BinaryNode : public Node
2152{
2153  public:
2154    NodePtr l;
2155    NodePtr r;
2156    mutable VResult vresult;
2157
2158  public:
2159    BinaryNode(NodePtr &a, NodePtr &b) : l(a), r(b) {}
2160
2161    const VResult &result() const
2162    {
2163        Op op;
2164        const VResult &lvec = l->result();
2165        const VResult &rvec = r->result();
2166
2167        assert(lvec.size() > 0 && rvec.size() > 0);
2168
2169        if (lvec.size() == 1 && rvec.size() == 1) {
2170            vresult.resize(1);
2171            vresult[0] = op(lvec[0], rvec[0]);
2172        } else if (lvec.size() == 1) {
2173            int size = rvec.size();
2174            vresult.resize(size);
2175            for (int i = 0; i < size; ++i)
2176                vresult[i] = op(lvec[0], rvec[i]);
2177        } else if (rvec.size() == 1) {
2178            int size = lvec.size();
2179            vresult.resize(size);
2180            for (int i = 0; i < size; ++i)
2181                vresult[i] = op(lvec[i], rvec[0]);
2182        } else if (rvec.size() == lvec.size()) {
2183            int size = rvec.size();
2184            vresult.resize(size);
2185            for (int i = 0; i < size; ++i)
2186                vresult[i] = op(lvec[i], rvec[i]);
2187        }
2188
2189        return vresult;
2190    }
2191
2192    Result total() const
2193    {
2194        const VResult &vec = this->result();
2195        Result total = 0;
2196        for (int i = 0; i < size(); i++)
2197            total += vec[i];
2198        return total;
2199    }
2200
2201    virtual size_t size() const {
2202        int ls = l->size();
2203        int rs = r->size();
2204        if (ls == 1)
2205            return rs;
2206        else if (rs == 1)
2207            return ls;
2208        else {
2209            assert(ls == rs && "Node vector sizes are not equal");
2210            return ls;
2211        }
2212    }
2213
2214    virtual std::string str() const
2215    {
2216        return csprintf("(%s %s %s)", l->str(), OpString<Op>::str(), r->str());
2217    }
2218};
2219
2220template <class Op>
2221class SumNode : public Node
2222{
2223  public:
2224    NodePtr l;
2225    mutable VResult vresult;
2226
2227  public:
2228    SumNode(NodePtr &p) : l(p), vresult(1) {}
2229
2230    const VResult &result() const
2231    {
2232        const VResult &lvec = l->result();
2233        int size = lvec.size();
2234        assert(size > 0);
2235
2236        vresult[0] = 0.0;
2237
2238        Op op;
2239        for (int i = 0; i < size; ++i)
2240            vresult[0] = op(vresult[0], lvec[i]);
2241
2242        return vresult;
2243    }
2244
2245    Result total() const
2246    {
2247        const VResult &lvec = l->result();
2248        int size = lvec.size();
2249        assert(size > 0);
2250
2251        Result vresult = 0.0;
2252
2253        Op op;
2254        for (int i = 0; i < size; ++i)
2255            vresult = op(vresult, lvec[i]);
2256
2257        return vresult;
2258    }
2259
2260    virtual size_t size() const { return 1; }
2261
2262    virtual std::string str() const
2263    {
2264        return csprintf("total(%s)", l->str());
2265    }
2266};
2267
2268
2269//////////////////////////////////////////////////////////////////////
2270//
2271// Visible Statistics Types
2272//
2273//////////////////////////////////////////////////////////////////////
2274/**
2275 * @defgroup VisibleStats "Statistic Types"
2276 * These are the statistics that are used in the simulator.
2277 * @{
2278 */
2279
2280/**
2281 * This is a simple scalar statistic, like a counter.
2282 * @sa Stat, ScalarBase, StatStor
2283 */
2284template<int N = 0>
2285class Scalar : public Wrap<Scalar<N>, ScalarBase<StatStor>, ScalarStatData>
2286{
2287  public:
2288    /** The base implementation. */
2289    typedef ScalarBase<StatStor> Base;
2290
2291    Scalar()
2292    {
2293        this->doInit();
2294    }
2295
2296    /**
2297     * Sets the stat equal to the given value. Calls the base implementation
2298     * of operator=
2299     * @param v The new value.
2300     */
2301    template <typename U>
2302    void operator=(const U &v) { Base::operator=(v); }
2303};
2304
2305class Value : public Wrap<Value, ValueBase, ScalarStatData>
2306{
2307  public:
2308    /** The base implementation. */
2309    typedef ValueBase Base;
2310
2311    template <class T>
2312    Value &scalar(T &value)
2313    {
2314        Base::scalar(value);
2315        return *this;
2316    }
2317
2318    template <class T>
2319    Value &functor(T &func)
2320    {
2321        Base::functor(func);
2322        return *this;
2323    }
2324};
2325
2326/**
2327 * A stat that calculates the per tick average of a value.
2328 * @sa Stat, ScalarBase, AvgStor
2329 */
2330template<int N = 0>
2331class Average : public Wrap<Average<N>, ScalarBase<AvgStor>, ScalarStatData>
2332{
2333  public:
2334    /** The base implementation. */
2335    typedef ScalarBase<AvgStor> Base;
2336
2337    Average()
2338    {
2339        this->doInit();
2340    }
2341
2342    /**
2343     * Sets the stat equal to the given value. Calls the base implementation
2344     * of operator=
2345     * @param v The new value.
2346     */
2347    template <typename U>
2348    void operator=(const U &v) { Base::operator=(v); }
2349};
2350
2351/**
2352 * A vector of scalar stats.
2353 * @sa Stat, VectorBase, StatStor
2354 */
2355template<int N = 0>
2356class Vector : public WrapVec<Vector<N>, VectorBase<StatStor>, VectorStatData>
2357{
2358  public:
2359    /** The base implementation. */
2360    typedef ScalarBase<StatStor> Base;
2361
2362    /**
2363     * Set this vector to have the given size.
2364     * @param size The new size.
2365     * @return A reference to this stat.
2366     */
2367    Vector &init(size_t size) {
2368        this->doInit(size);
2369        return *this;
2370    }
2371};
2372
2373/**
2374 * A vector of Average stats.
2375 * @sa Stat, VectorBase, AvgStor
2376 */
2377template<int N = 0>
2378class AverageVector
2379    : public WrapVec<AverageVector<N>, VectorBase<AvgStor>, VectorStatData>
2380{
2381  public:
2382    /**
2383     * Set this vector to have the given size.
2384     * @param size The new size.
2385     * @return A reference to this stat.
2386     */
2387    AverageVector &init(size_t size) {
2388        this->doInit(size);
2389        return *this;
2390    }
2391};
2392
2393/**
2394 * A 2-Dimensional vecto of scalar stats.
2395 * @sa Stat, Vector2dBase, StatStor
2396 */
2397template<int N = 0>
2398class Vector2d
2399    : public WrapVec2d<Vector2d<N>, Vector2dBase<StatStor>, Vector2dStatData>
2400{
2401  public:
2402    Vector2d &init(size_t x, size_t y) {
2403        this->doInit(x, y);
2404        return *this;
2405    }
2406};
2407
2408/**
2409 * A simple distribution stat.
2410 * @sa Stat, DistBase, DistStor
2411 */
2412template<int N = 0>
2413class Distribution
2414    : public Wrap<Distribution<N>, DistBase<DistStor>, DistStatData>
2415{
2416  public:
2417    /** Base implementation. */
2418    typedef DistBase<DistStor> Base;
2419    /** The Parameter type. */
2420    typedef DistStor::Params Params;
2421
2422  public:
2423    /**
2424     * Set the parameters of this distribution. @sa DistStor::Params
2425     * @param min The minimum value of the distribution.
2426     * @param max The maximum value of the distribution.
2427     * @param bkt The number of values in each bucket.
2428     * @return A reference to this distribution.
2429     */
2430    Distribution &init(Counter min, Counter max, Counter bkt) {
2431        this->params.min = min;
2432        this->params.max = max;
2433        this->params.bucket_size = bkt;
2434        this->params.size = (int)rint((max - min) / bkt + 1.0);
2435        this->doInit();
2436        return *this;
2437    }
2438};
2439
2440/**
2441 * Calculates the mean and variance of all the samples.
2442 * @sa Stat, DistBase, FancyStor
2443 */
2444template<int N = 0>
2445class StandardDeviation
2446    : public Wrap<StandardDeviation<N>, DistBase<FancyStor>, DistStatData>
2447{
2448  public:
2449    /** The base implementation */
2450    typedef DistBase<DistStor> Base;
2451    /** The parameter type. */
2452    typedef DistStor::Params Params;
2453
2454  public:
2455    /**
2456     * Construct and initialize this distribution.
2457     */
2458    StandardDeviation() {
2459        this->doInit();
2460    }
2461};
2462
2463/**
2464 * Calculates the per tick mean and variance of the samples.
2465 * @sa Stat, DistBase, AvgFancy
2466 */
2467template<int N = 0>
2468class AverageDeviation
2469    : public Wrap<AverageDeviation<N>, DistBase<AvgFancy>, DistStatData>
2470{
2471  public:
2472    /** The base implementation */
2473    typedef DistBase<DistStor> Base;
2474    /** The parameter type. */
2475    typedef DistStor::Params Params;
2476
2477  public:
2478    /**
2479     * Construct and initialize this distribution.
2480     */
2481    AverageDeviation()
2482    {
2483        this->doInit();
2484    }
2485};
2486
2487/**
2488 * A vector of distributions.
2489 * @sa Stat, VectorDistBase, DistStor
2490 */
2491template<int N = 0>
2492class VectorDistribution
2493    : public WrapVec<VectorDistribution<N>,
2494                     VectorDistBase<DistStor>,
2495                     VectorDistStatData>
2496{
2497  public:
2498    /** The base implementation */
2499    typedef VectorDistBase<DistStor> Base;
2500    /** The parameter type. */
2501    typedef DistStor::Params Params;
2502
2503  public:
2504    /**
2505     * Initialize storage and parameters for this distribution.
2506     * @param size The size of the vector (the number of distributions).
2507     * @param min The minimum value of the distribution.
2508     * @param max The maximum value of the distribution.
2509     * @param bkt The number of values in each bucket.
2510     * @return A reference to this distribution.
2511     */
2512    VectorDistribution &init(int size, Counter min, Counter max, Counter bkt) {
2513        this->params.min = min;
2514        this->params.max = max;
2515        this->params.bucket_size = bkt;
2516        this->params.size = (int)rint((max - min) / bkt + 1.0);
2517        this->doInit(size);
2518        return *this;
2519    }
2520};
2521
2522/**
2523 * This is a vector of StandardDeviation stats.
2524 * @sa Stat, VectorDistBase, FancyStor
2525 */
2526template<int N = 0>
2527class VectorStandardDeviation
2528    : public WrapVec<VectorStandardDeviation<N>,
2529                     VectorDistBase<FancyStor>,
2530                     VectorDistStatData>
2531{
2532  public:
2533    /** The base implementation */
2534    typedef VectorDistBase<FancyStor> Base;
2535    /** The parameter type. */
2536    typedef DistStor::Params Params;
2537
2538  public:
2539    /**
2540     * Initialize storage for this distribution.
2541     * @param size The size of the vector.
2542     * @return A reference to this distribution.
2543     */
2544    VectorStandardDeviation &init(int size) {
2545        this->doInit(size);
2546        return *this;
2547    }
2548};
2549
2550/**
2551 * This is a vector of AverageDeviation stats.
2552 * @sa Stat, VectorDistBase, AvgFancy
2553 */
2554template<int N = 0>
2555class VectorAverageDeviation
2556    : public WrapVec<VectorAverageDeviation<N>,
2557                     VectorDistBase<AvgFancy>,
2558                     VectorDistStatData>
2559{
2560  public:
2561    /** The base implementation */
2562    typedef VectorDistBase<AvgFancy> Base;
2563    /** The parameter type. */
2564    typedef DistStor::Params Params;
2565
2566  public:
2567    /**
2568     * Initialize storage for this distribution.
2569     * @param size The size of the vector.
2570     * @return A reference to this distribution.
2571     */
2572    VectorAverageDeviation &init(int size) {
2573        this->doInit(size);
2574        return *this;
2575    }
2576};
2577
2578/**
2579 * A formula for statistics that is calculated when printed. A formula is
2580 * stored as a tree of Nodes that represent the equation to calculate.
2581 * @sa Stat, ScalarStat, VectorStat, Node, Temp
2582 */
2583class FormulaBase : public DataAccess
2584{
2585  protected:
2586    /** The root of the tree which represents the Formula */
2587    NodePtr root;
2588    friend class Temp;
2589
2590  public:
2591    /**
2592     * Return the result of the Fomula in a vector.  If there were no Vector
2593     * components to the Formula, then the vector is size 1.  If there were,
2594     * like x/y with x being a vector of size 3, then the result returned will
2595     * be x[0]/y, x[1]/y, x[2]/y, respectively.
2596     * @return The result vector.
2597     */
2598    void result(VResult &vec) const;
2599
2600    /**
2601     * Return the total Formula result.  If there is a Vector
2602     * component to this Formula, then this is the result of the
2603     * Formula if the formula is applied after summing all the
2604     * components of the Vector.  For example, if Formula is x/y where
2605     * x is size 3, then total() will return (x[1]+x[2]+x[3])/y.  If
2606     * there is no Vector component, total() returns the same value as
2607     * the first entry in the VResult val() returns.
2608     * @return The total of the result vector.
2609     */
2610    Result total() const;
2611
2612    /**
2613     * Return the number of elements in the tree.
2614     */
2615    size_t size() const;
2616
2617    bool check() const { return true; }
2618
2619    /**
2620     * Formulas don't need to be reset
2621     */
2622    void reset();
2623
2624    /**
2625     *
2626     */
2627    bool zero() const;
2628
2629    /**
2630     *
2631     */
2632    void update(StatData *);
2633
2634    std::string str() const;
2635};
2636
2637class FormulaData : public VectorData
2638{
2639  public:
2640    virtual std::string str() const = 0;
2641    virtual bool check() const { return true; }
2642};
2643
2644template <class Stat>
2645class FormulaStatData : public FormulaData
2646{
2647  protected:
2648    Stat &s;
2649    mutable VResult vec;
2650    mutable VCounter cvec;
2651
2652  public:
2653    FormulaStatData(Stat &stat) : s(stat) {}
2654
2655    virtual bool zero() const { return s.zero(); }
2656    virtual void reset() { s.reset(); }
2657
2658    virtual size_t size() const { return s.size(); }
2659    virtual const VResult &result() const
2660    {
2661        s.result(vec);
2662        return vec;
2663    }
2664    virtual Result total() const { return s.total(); }
2665    virtual VCounter &value() const { return cvec; }
2666    virtual void visit(Visit &visitor)
2667    {
2668        update();
2669        s.update(this);
2670        visitor.visit(*this);
2671    }
2672    virtual std::string str() const { return s.str(); }
2673};
2674
2675class Temp;
2676class Formula
2677    : public WrapVec<Formula,
2678                     FormulaBase,
2679                     FormulaStatData>
2680{
2681  public:
2682    /**
2683     * Create and initialize thie formula, and register it with the database.
2684     */
2685    Formula();
2686
2687    /**
2688     * Create a formula with the given root node, register it with the
2689     * database.
2690     * @param r The root of the expression tree.
2691     */
2692    Formula(Temp r);
2693
2694    /**
2695     * Set an unitialized Formula to the given root.
2696     * @param r The root of the expression tree.
2697     * @return a reference to this formula.
2698     */
2699    const Formula &operator=(Temp r);
2700
2701    /**
2702     * Add the given tree to the existing one.
2703     * @param r The root of the expression tree.
2704     * @return a reference to this formula.
2705     */
2706    const Formula &operator+=(Temp r);
2707};
2708
2709class FormulaNode : public Node
2710{
2711  private:
2712    const Formula &formula;
2713    mutable VResult vec;
2714
2715  public:
2716    FormulaNode(const Formula &f) : formula(f) {}
2717
2718    virtual size_t size() const { return formula.size(); }
2719    virtual const VResult &result() const { formula.result(vec); return vec; }
2720    virtual Result total() const { return formula.total(); }
2721
2722    virtual std::string str() const { return formula.str(); }
2723};
2724
2725/**
2726 * Helper class to construct formula node trees.
2727 */
2728class Temp
2729{
2730  protected:
2731    /**
2732     * Pointer to a Node object.
2733     */
2734    NodePtr node;
2735
2736  public:
2737    /**
2738     * Copy the given pointer to this class.
2739     * @param n A pointer to a Node object to copy.
2740     */
2741    Temp(NodePtr n) : node(n) { }
2742
2743    /**
2744     * Return the node pointer.
2745     * @return the node pointer.
2746     */
2747    operator NodePtr&() { return node;}
2748
2749  public:
2750    /**
2751     * Create a new ScalarStatNode.
2752     * @param s The ScalarStat to place in a node.
2753     */
2754    template <int N>
2755    Temp(const Scalar<N> &s)
2756        : node(new ScalarStatNode(s.statData())) { }
2757
2758    /**
2759     * Create a new ScalarStatNode.
2760     * @param s The ScalarStat to place in a node.
2761     */
2762    Temp(const Value &s)
2763        : node(new ScalarStatNode(s.statData())) { }
2764
2765    /**
2766     * Create a new ScalarStatNode.
2767     * @param s The ScalarStat to place in a node.
2768     */
2769    template <int N>
2770    Temp(const Average<N> &s)
2771        : node(new ScalarStatNode(s.statData())) { }
2772
2773    /**
2774     * Create a new VectorStatNode.
2775     * @param s The VectorStat to place in a node.
2776     */
2777    template <int N>
2778    Temp(const Vector<N> &s)
2779        : node(new VectorStatNode(s.statData())) { }
2780
2781    /**
2782     *
2783     */
2784    Temp(const Formula &f)
2785        : node(new FormulaNode(f)) { }
2786
2787    /**
2788     * Create a new ScalarProxyNode.
2789     * @param p The ScalarProxy to place in a node.
2790     */
2791    template <class Stat>
2792    Temp(const ScalarProxy<Stat> &p)
2793        : node(new ScalarProxyNode<Stat>(p)) { }
2794
2795    /**
2796     * Create a ConstNode
2797     * @param value The value of the const node.
2798     */
2799    Temp(signed char value)
2800        : node(new ConstNode<signed char>(value)) {}
2801
2802    /**
2803     * Create a ConstNode
2804     * @param value The value of the const node.
2805     */
2806    Temp(unsigned char value)
2807        : node(new ConstNode<unsigned char>(value)) {}
2808
2809    /**
2810     * Create a ConstNode
2811     * @param value The value of the const node.
2812     */
2813    Temp(signed short value)
2814        : node(new ConstNode<signed short>(value)) {}
2815
2816    /**
2817     * Create a ConstNode
2818     * @param value The value of the const node.
2819     */
2820    Temp(unsigned short value)
2821        : node(new ConstNode<unsigned short>(value)) {}
2822
2823    /**
2824     * Create a ConstNode
2825     * @param value The value of the const node.
2826     */
2827    Temp(signed int value)
2828        : node(new ConstNode<signed int>(value)) {}
2829
2830    /**
2831     * Create a ConstNode
2832     * @param value The value of the const node.
2833     */
2834    Temp(unsigned int value)
2835        : node(new ConstNode<unsigned int>(value)) {}
2836
2837    /**
2838     * Create a ConstNode
2839     * @param value The value of the const node.
2840     */
2841    Temp(signed long value)
2842        : node(new ConstNode<signed long>(value)) {}
2843
2844    /**
2845     * Create a ConstNode
2846     * @param value The value of the const node.
2847     */
2848    Temp(unsigned long value)
2849        : node(new ConstNode<unsigned long>(value)) {}
2850
2851    /**
2852     * Create a ConstNode
2853     * @param value The value of the const node.
2854     */
2855    Temp(signed long long value)
2856        : node(new ConstNode<signed long long>(value)) {}
2857
2858    /**
2859     * Create a ConstNode
2860     * @param value The value of the const node.
2861     */
2862    Temp(unsigned long long value)
2863        : node(new ConstNode<unsigned long long>(value)) {}
2864
2865    /**
2866     * Create a ConstNode
2867     * @param value The value of the const node.
2868     */
2869    Temp(float value)
2870        : node(new ConstNode<float>(value)) {}
2871
2872    /**
2873     * Create a ConstNode
2874     * @param value The value of the const node.
2875     */
2876    Temp(double value)
2877        : node(new ConstNode<double>(value)) {}
2878};
2879
2880
2881/**
2882 * @}
2883 */
2884
2885void check();
2886void dump();
2887void reset();
2888void registerResetCallback(Callback *cb);
2889
2890inline Temp
2891operator+(Temp l, Temp r)
2892{
2893    return NodePtr(new BinaryNode<std::plus<Result> >(l, r));
2894}
2895
2896inline Temp
2897operator-(Temp l, Temp r)
2898{
2899    return NodePtr(new BinaryNode<std::minus<Result> >(l, r));
2900}
2901
2902inline Temp
2903operator*(Temp l, Temp r)
2904{
2905    return NodePtr(new BinaryNode<std::multiplies<Result> >(l, r));
2906}
2907
2908inline Temp
2909operator/(Temp l, Temp r)
2910{
2911    return NodePtr(new BinaryNode<std::divides<Result> >(l, r));
2912}
2913
2914inline Temp
2915operator-(Temp l)
2916{
2917    return NodePtr(new UnaryNode<std::negate<Result> >(l));
2918}
2919
2920template <typename T>
2921inline Temp
2922constant(T val)
2923{
2924    return NodePtr(new ConstNode<T>(val));
2925}
2926
2927template <typename T>
2928inline Temp
2929constantVector(T val)
2930{
2931    return NodePtr(new ConstVectorNode<T>(val));
2932}
2933
2934inline Temp
2935sum(Temp val)
2936{
2937    return NodePtr(new SumNode<std::plus<Result> >(val));
2938}
2939
2940/* namespace Stats */ }
2941
2942#endif // __BASE_STATISTICS_HH__
2943