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