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