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