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