statistics.hh revision 6977:039202aafc0d
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(print);
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    size_type
1704    size() const
1705    {
1706        return _size;
1707    }
1708
1709    bool
1710    zero() const
1711    {
1712        return false;
1713#if 0
1714        for (off_type i = 0; i < size(); ++i)
1715            if (!data(i)->zero())
1716                return false;
1717        return true;
1718#endif
1719    }
1720
1721    void
1722    prepare()
1723    {
1724        Info *info = this->info();
1725        size_type size = this->size();
1726        info->data.resize(size);
1727        for (off_type i = 0; i < size; ++i)
1728            data(i)->prepare(info, info->data[i]);
1729    }
1730
1731    bool
1732    check() const
1733    {
1734        return storage != NULL;
1735    }
1736};
1737
1738template <class Stat>
1739class DistProxy
1740{
1741  private:
1742    Stat *stat;
1743    off_type index;
1744
1745  protected:
1746    typename Stat::Storage *data() { return stat->data(index); }
1747    const typename Stat::Storage *data() const { return stat->data(index); }
1748
1749  public:
1750    DistProxy(Stat *s, off_type i)
1751        : stat(s), index(i)
1752    {}
1753
1754    DistProxy(const DistProxy &sp)
1755        : stat(sp.stat), index(sp.index)
1756    {}
1757
1758    const DistProxy &
1759    operator=(const DistProxy &sp)
1760    {
1761        stat = sp.stat;
1762        index = sp.index;
1763        return *this;
1764    }
1765
1766  public:
1767    template <typename U>
1768    void
1769    sample(const U &v, int n = 1)
1770    {
1771        data()->sample(v, n);
1772    }
1773
1774    size_type
1775    size() const
1776    {
1777        return 1;
1778    }
1779
1780    bool
1781    zero() const
1782    {
1783        return data()->zero();
1784    }
1785
1786    /**
1787     * Proxy has no state.  Nothing to reset.
1788     */
1789    void reset() { }
1790};
1791
1792template <class Derived, class Stor>
1793inline typename VectorDistBase<Derived, Stor>::Proxy
1794VectorDistBase<Derived, Stor>::operator[](off_type index)
1795{
1796    assert (index >= 0 && index < size());
1797    typedef typename VectorDistBase<Derived, Stor>::Proxy Proxy;
1798    return Proxy(this, index);
1799}
1800
1801#if 0
1802template <class Storage>
1803Result
1804VectorDistBase<Storage>::total(off_type index) const
1805{
1806    Result total = 0.0;
1807    for (off_type i = 0; i < x_size(); ++i)
1808        total += data(i)->result();
1809}
1810#endif
1811
1812//////////////////////////////////////////////////////////////////////
1813//
1814//  Formula Details
1815//
1816//////////////////////////////////////////////////////////////////////
1817
1818/**
1819 * Base class for formula statistic node. These nodes are used to build a tree
1820 * that represents the formula.
1821 */
1822class Node : public RefCounted
1823{
1824  public:
1825    /**
1826     * Return the number of nodes in the subtree starting at this node.
1827     * @return the number of nodes in this subtree.
1828     */
1829    virtual size_type size() const = 0;
1830    /**
1831     * Return the result vector of this subtree.
1832     * @return The result vector of this subtree.
1833     */
1834    virtual const VResult &result() const = 0;
1835    /**
1836     * Return the total of the result vector.
1837     * @return The total of the result vector.
1838     */
1839    virtual Result total() const = 0;
1840
1841    /**
1842     *
1843     */
1844    virtual std::string str() const = 0;
1845};
1846
1847/** Reference counting pointer to a function Node. */
1848typedef RefCountingPtr<Node> NodePtr;
1849
1850class ScalarStatNode : public Node
1851{
1852  private:
1853    const ScalarInfo *data;
1854    mutable VResult vresult;
1855
1856  public:
1857    ScalarStatNode(const ScalarInfo *d) : data(d), vresult(1) {}
1858
1859    const VResult &
1860    result() const
1861    {
1862        vresult[0] = data->result();
1863        return vresult;
1864    }
1865
1866    Result total() const { return data->result(); };
1867
1868    size_type size() const { return 1; }
1869
1870    /**
1871     *
1872     */
1873    std::string str() const { return data->name; }
1874};
1875
1876template <class Stat>
1877class ScalarProxyNode : public Node
1878{
1879  private:
1880    const ScalarProxy<Stat> proxy;
1881    mutable VResult vresult;
1882
1883  public:
1884    ScalarProxyNode(const ScalarProxy<Stat> &p)
1885        : proxy(p), vresult(1)
1886    { }
1887
1888    const VResult &
1889    result() const
1890    {
1891        vresult[0] = proxy.result();
1892        return vresult;
1893    }
1894
1895    Result
1896    total() const
1897    {
1898        return proxy.result();
1899    }
1900
1901    size_type
1902    size() const
1903    {
1904        return 1;
1905    }
1906
1907    /**
1908     *
1909     */
1910    std::string
1911    str() const
1912    {
1913        return proxy.str();
1914    }
1915};
1916
1917class VectorStatNode : public Node
1918{
1919  private:
1920    const VectorInfo *data;
1921
1922  public:
1923    VectorStatNode(const VectorInfo *d) : data(d) { }
1924    const VResult &result() const { return data->result(); }
1925    Result total() const { return data->total(); };
1926
1927    size_type size() const { return data->size(); }
1928
1929    std::string str() const { return data->name; }
1930};
1931
1932template <class T>
1933class ConstNode : public Node
1934{
1935  private:
1936    VResult vresult;
1937
1938  public:
1939    ConstNode(T s) : vresult(1, (Result)s) {}
1940    const VResult &result() const { return vresult; }
1941    Result total() const { return vresult[0]; };
1942    size_type size() const { return 1; }
1943    std::string str() const { return to_string(vresult[0]); }
1944};
1945
1946template <class T>
1947class ConstVectorNode : public Node
1948{
1949  private:
1950    VResult vresult;
1951
1952  public:
1953    ConstVectorNode(const T &s) : vresult(s.begin(), s.end()) {}
1954    const VResult &result() const { return vresult; }
1955
1956    Result
1957    total() const
1958    {
1959        size_type size = this->size();
1960        Result tmp = 0;
1961        for (off_type i = 0; i < size; i++)
1962            tmp += vresult[i];
1963        return tmp;
1964    }
1965
1966    size_type size() const { return vresult.size(); }
1967    std::string
1968    str() const
1969    {
1970        size_type size = this->size();
1971        std::string tmp = "(";
1972        for (off_type i = 0; i < size; i++)
1973            tmp += csprintf("%s ",to_string(vresult[i]));
1974        tmp += ")";
1975        return tmp;
1976    }
1977};
1978
1979template <class Op>
1980struct OpString;
1981
1982template<>
1983struct OpString<std::plus<Result> >
1984{
1985    static std::string str() { return "+"; }
1986};
1987
1988template<>
1989struct OpString<std::minus<Result> >
1990{
1991    static std::string str() { return "-"; }
1992};
1993
1994template<>
1995struct OpString<std::multiplies<Result> >
1996{
1997    static std::string str() { return "*"; }
1998};
1999
2000template<>
2001struct OpString<std::divides<Result> >
2002{
2003    static std::string str() { return "/"; }
2004};
2005
2006template<>
2007struct OpString<std::modulus<Result> >
2008{
2009    static std::string str() { return "%"; }
2010};
2011
2012template<>
2013struct OpString<std::negate<Result> >
2014{
2015    static std::string str() { return "-"; }
2016};
2017
2018template <class Op>
2019class UnaryNode : public Node
2020{
2021  public:
2022    NodePtr l;
2023    mutable VResult vresult;
2024
2025  public:
2026    UnaryNode(NodePtr &p) : l(p) {}
2027
2028    const VResult &
2029    result() const
2030    {
2031        const VResult &lvec = l->result();
2032        size_type size = lvec.size();
2033
2034        assert(size > 0);
2035
2036        vresult.resize(size);
2037        Op op;
2038        for (off_type i = 0; i < size; ++i)
2039            vresult[i] = op(lvec[i]);
2040
2041        return vresult;
2042    }
2043
2044    Result
2045    total() const
2046    {
2047        const VResult &vec = this->result();
2048        Result total = 0.0;
2049        for (off_type i = 0; i < size(); i++)
2050            total += vec[i];
2051        return total;
2052    }
2053
2054    size_type size() const { return l->size(); }
2055
2056    std::string
2057    str() const
2058    {
2059        return OpString<Op>::str() + l->str();
2060    }
2061};
2062
2063template <class Op>
2064class BinaryNode : public Node
2065{
2066  public:
2067    NodePtr l;
2068    NodePtr r;
2069    mutable VResult vresult;
2070
2071  public:
2072    BinaryNode(NodePtr &a, NodePtr &b) : l(a), r(b) {}
2073
2074    const VResult &
2075    result() const
2076    {
2077        Op op;
2078        const VResult &lvec = l->result();
2079        const VResult &rvec = r->result();
2080
2081        assert(lvec.size() > 0 && rvec.size() > 0);
2082
2083        if (lvec.size() == 1 && rvec.size() == 1) {
2084            vresult.resize(1);
2085            vresult[0] = op(lvec[0], rvec[0]);
2086        } else if (lvec.size() == 1) {
2087            size_type size = rvec.size();
2088            vresult.resize(size);
2089            for (off_type i = 0; i < size; ++i)
2090                vresult[i] = op(lvec[0], rvec[i]);
2091        } else if (rvec.size() == 1) {
2092            size_type size = lvec.size();
2093            vresult.resize(size);
2094            for (off_type i = 0; i < size; ++i)
2095                vresult[i] = op(lvec[i], rvec[0]);
2096        } else if (rvec.size() == lvec.size()) {
2097            size_type size = rvec.size();
2098            vresult.resize(size);
2099            for (off_type i = 0; i < size; ++i)
2100                vresult[i] = op(lvec[i], rvec[i]);
2101        }
2102
2103        return vresult;
2104    }
2105
2106    Result
2107    total() const
2108    {
2109        const VResult &vec = this->result();
2110        Result total = 0.0;
2111        for (off_type i = 0; i < size(); i++)
2112            total += vec[i];
2113        return total;
2114    }
2115
2116    size_type
2117    size() const
2118    {
2119        size_type ls = l->size();
2120        size_type rs = r->size();
2121        if (ls == 1) {
2122            return rs;
2123        } else if (rs == 1) {
2124            return ls;
2125        } else {
2126            assert(ls == rs && "Node vector sizes are not equal");
2127            return ls;
2128        }
2129    }
2130
2131    std::string
2132    str() const
2133    {
2134        return csprintf("(%s %s %s)", l->str(), OpString<Op>::str(), r->str());
2135    }
2136};
2137
2138template <class Op>
2139class SumNode : public Node
2140{
2141  public:
2142    NodePtr l;
2143    mutable VResult vresult;
2144
2145  public:
2146    SumNode(NodePtr &p) : l(p), vresult(1) {}
2147
2148    const VResult &
2149    result() const
2150    {
2151        const VResult &lvec = l->result();
2152        size_type size = lvec.size();
2153        assert(size > 0);
2154
2155        vresult[0] = 0.0;
2156
2157        Op op;
2158        for (off_type i = 0; i < size; ++i)
2159            vresult[0] = op(vresult[0], lvec[i]);
2160
2161        return vresult;
2162    }
2163
2164    Result
2165    total() const
2166    {
2167        const VResult &lvec = l->result();
2168        size_type size = lvec.size();
2169        assert(size > 0);
2170
2171        Result vresult = 0.0;
2172
2173        Op op;
2174        for (off_type i = 0; i < size; ++i)
2175            vresult = op(vresult, lvec[i]);
2176
2177        return vresult;
2178    }
2179
2180    size_type size() const { return 1; }
2181
2182    std::string
2183    str() const
2184    {
2185        return csprintf("total(%s)", l->str());
2186    }
2187};
2188
2189
2190//////////////////////////////////////////////////////////////////////
2191//
2192// Visible Statistics Types
2193//
2194//////////////////////////////////////////////////////////////////////
2195/**
2196 * @defgroup VisibleStats "Statistic Types"
2197 * These are the statistics that are used in the simulator.
2198 * @{
2199 */
2200
2201/**
2202 * This is a simple scalar statistic, like a counter.
2203 * @sa Stat, ScalarBase, StatStor
2204 */
2205class Scalar : public ScalarBase<Scalar, StatStor>
2206{
2207  public:
2208    using ScalarBase<Scalar, StatStor>::operator=;
2209};
2210
2211/**
2212 * A stat that calculates the per tick average of a value.
2213 * @sa Stat, ScalarBase, AvgStor
2214 */
2215class Average : public ScalarBase<Average, AvgStor>
2216{
2217  public:
2218    using ScalarBase<Average, AvgStor>::operator=;
2219};
2220
2221class Value : public ValueBase<Value>
2222{
2223};
2224
2225/**
2226 * A vector of scalar stats.
2227 * @sa Stat, VectorBase, StatStor
2228 */
2229class Vector : public VectorBase<Vector, StatStor>
2230{
2231};
2232
2233/**
2234 * A vector of Average stats.
2235 * @sa Stat, VectorBase, AvgStor
2236 */
2237class AverageVector : public VectorBase<AverageVector, AvgStor>
2238{
2239};
2240
2241/**
2242 * A 2-Dimensional vecto of scalar stats.
2243 * @sa Stat, Vector2dBase, StatStor
2244 */
2245class Vector2d : public Vector2dBase<Vector2d, StatStor>
2246{
2247};
2248
2249/**
2250 * A simple distribution stat.
2251 * @sa Stat, DistBase, DistStor
2252 */
2253class Distribution : public DistBase<Distribution, DistStor>
2254{
2255  public:
2256    /**
2257     * Set the parameters of this distribution. @sa DistStor::Params
2258     * @param min The minimum value of the distribution.
2259     * @param max The maximum value of the distribution.
2260     * @param bkt The number of values in each bucket.
2261     * @return A reference to this distribution.
2262     */
2263    Distribution &
2264    init(Counter min, Counter max, Counter bkt)
2265    {
2266        DistStor::Params *params = new DistStor::Params;
2267        params->min = min;
2268        params->max = max;
2269        params->bucket_size = bkt;
2270        params->buckets = (size_type)rint((max - min) / bkt + 1.0);
2271        this->setParams(params);
2272        this->doInit();
2273        return this->self();
2274    }
2275};
2276
2277/**
2278 * Calculates the mean and variance of all the samples.
2279 * @sa DistBase, SampleStor
2280 */
2281class StandardDeviation : public DistBase<StandardDeviation, SampleStor>
2282{
2283  public:
2284    /**
2285     * Construct and initialize this distribution.
2286     */
2287    StandardDeviation()
2288    {
2289        this->doInit();
2290    }
2291};
2292
2293/**
2294 * Calculates the per tick mean and variance of the samples.
2295 * @sa DistBase, AvgSampleStor
2296 */
2297class AverageDeviation : public DistBase<AverageDeviation, AvgSampleStor>
2298{
2299  public:
2300    /**
2301     * Construct and initialize this distribution.
2302     */
2303    AverageDeviation()
2304    {
2305        this->doInit();
2306    }
2307};
2308
2309/**
2310 * A vector of distributions.
2311 * @sa VectorDistBase, DistStor
2312 */
2313class VectorDistribution : public VectorDistBase<VectorDistribution, DistStor>
2314{
2315  public:
2316    /**
2317     * Initialize storage and parameters for this distribution.
2318     * @param size The size of the vector (the number of distributions).
2319     * @param min The minimum value of the distribution.
2320     * @param max The maximum value of the distribution.
2321     * @param bkt The number of values in each bucket.
2322     * @return A reference to this distribution.
2323     */
2324    VectorDistribution &
2325    init(size_type size, Counter min, Counter max, Counter bkt)
2326    {
2327        DistStor::Params *params = new DistStor::Params;
2328        params->min = min;
2329        params->max = max;
2330        params->bucket_size = bkt;
2331        params->buckets = (size_type)rint((max - min) / bkt + 1.0);
2332        this->setParams(params);
2333        this->doInit(size);
2334        return this->self();
2335    }
2336};
2337
2338/**
2339 * This is a vector of StandardDeviation stats.
2340 * @sa VectorDistBase, SampleStor
2341 */
2342class VectorStandardDeviation
2343    : public VectorDistBase<VectorStandardDeviation, SampleStor>
2344{
2345  public:
2346    /**
2347     * Initialize storage for this distribution.
2348     * @param size The size of the vector.
2349     * @return A reference to this distribution.
2350     */
2351    VectorStandardDeviation &
2352    init(size_type size)
2353    {
2354        this->doInit(size);
2355        return this->self();
2356    }
2357};
2358
2359/**
2360 * This is a vector of AverageDeviation stats.
2361 * @sa VectorDistBase, AvgSampleStor
2362 */
2363class VectorAverageDeviation
2364    : public VectorDistBase<VectorAverageDeviation, AvgSampleStor>
2365{
2366  public:
2367    /**
2368     * Initialize storage for this distribution.
2369     * @param size The size of the vector.
2370     * @return A reference to this distribution.
2371     */
2372    VectorAverageDeviation &
2373    init(size_type size)
2374    {
2375        this->doInit(size);
2376        return this->self();
2377    }
2378};
2379
2380template <class Stat>
2381class FormulaInfoProxy : public InfoProxy<Stat, FormulaInfo>
2382{
2383  protected:
2384    mutable VResult vec;
2385    mutable VCounter cvec;
2386
2387  public:
2388    FormulaInfoProxy(Stat &stat) : InfoProxy<Stat, FormulaInfo>(stat) {}
2389
2390    size_type size() const { return this->s.size(); }
2391
2392    const VResult &
2393    result() const
2394    {
2395        this->s.result(vec);
2396        return vec;
2397    }
2398    Result total() const { return this->s.total(); }
2399    VCounter &value() const { return cvec; }
2400
2401    std::string str() const { return this->s.str(); }
2402};
2403
2404class Temp;
2405/**
2406 * A formula for statistics that is calculated when printed. A formula is
2407 * stored as a tree of Nodes that represent the equation to calculate.
2408 * @sa Stat, ScalarStat, VectorStat, Node, Temp
2409 */
2410class Formula : public DataWrapVec<Formula, FormulaInfoProxy>
2411{
2412  protected:
2413    /** The root of the tree which represents the Formula */
2414    NodePtr root;
2415    friend class Temp;
2416
2417  public:
2418    /**
2419     * Create and initialize thie formula, and register it with the database.
2420     */
2421    Formula();
2422
2423    /**
2424     * Create a formula with the given root node, register it with the
2425     * database.
2426     * @param r The root of the expression tree.
2427     */
2428    Formula(Temp r);
2429
2430    /**
2431     * Set an unitialized Formula to the given root.
2432     * @param r The root of the expression tree.
2433     * @return a reference to this formula.
2434     */
2435    const Formula &operator=(Temp r);
2436
2437    /**
2438     * Add the given tree to the existing one.
2439     * @param r The root of the expression tree.
2440     * @return a reference to this formula.
2441     */
2442    const Formula &operator+=(Temp r);
2443    /**
2444     * Return the result of the Fomula in a vector.  If there were no Vector
2445     * components to the Formula, then the vector is size 1.  If there were,
2446     * like x/y with x being a vector of size 3, then the result returned will
2447     * be x[0]/y, x[1]/y, x[2]/y, respectively.
2448     * @return The result vector.
2449     */
2450    void result(VResult &vec) const;
2451
2452    /**
2453     * Return the total Formula result.  If there is a Vector
2454     * component to this Formula, then this is the result of the
2455     * Formula if the formula is applied after summing all the
2456     * components of the Vector.  For example, if Formula is x/y where
2457     * x is size 3, then total() will return (x[1]+x[2]+x[3])/y.  If
2458     * there is no Vector component, total() returns the same value as
2459     * the first entry in the VResult val() returns.
2460     * @return The total of the result vector.
2461     */
2462    Result total() const;
2463
2464    /**
2465     * Return the number of elements in the tree.
2466     */
2467    size_type size() const;
2468
2469    void prepare() { }
2470
2471    /**
2472     * Formulas don't need to be reset
2473     */
2474    void reset();
2475
2476    /**
2477     *
2478     */
2479    bool zero() const;
2480
2481    std::string str() const;
2482};
2483
2484class FormulaNode : public Node
2485{
2486  private:
2487    const Formula &formula;
2488    mutable VResult vec;
2489
2490  public:
2491    FormulaNode(const Formula &f) : formula(f) {}
2492
2493    size_type size() const { return formula.size(); }
2494    const VResult &result() const { formula.result(vec); return vec; }
2495    Result total() const { return formula.total(); }
2496
2497    std::string str() const { return formula.str(); }
2498};
2499
2500/**
2501 * Helper class to construct formula node trees.
2502 */
2503class Temp
2504{
2505  protected:
2506    /**
2507     * Pointer to a Node object.
2508     */
2509    NodePtr node;
2510
2511  public:
2512    /**
2513     * Copy the given pointer to this class.
2514     * @param n A pointer to a Node object to copy.
2515     */
2516    Temp(NodePtr n) : node(n) { }
2517
2518    /**
2519     * Return the node pointer.
2520     * @return the node pointer.
2521     */
2522    operator NodePtr&() { return node; }
2523
2524  public:
2525    /**
2526     * Create a new ScalarStatNode.
2527     * @param s The ScalarStat to place in a node.
2528     */
2529    Temp(const Scalar &s)
2530        : node(new ScalarStatNode(s.info()))
2531    { }
2532
2533    /**
2534     * Create a new ScalarStatNode.
2535     * @param s The ScalarStat to place in a node.
2536     */
2537    Temp(const Value &s)
2538        : node(new ScalarStatNode(s.info()))
2539    { }
2540
2541    /**
2542     * Create a new ScalarStatNode.
2543     * @param s The ScalarStat to place in a node.
2544     */
2545    Temp(const Average &s)
2546        : node(new ScalarStatNode(s.info()))
2547    { }
2548
2549    /**
2550     * Create a new VectorStatNode.
2551     * @param s The VectorStat to place in a node.
2552     */
2553    Temp(const Vector &s)
2554        : node(new VectorStatNode(s.info()))
2555    { }
2556
2557    Temp(const AverageVector &s)
2558        : node(new VectorStatNode(s.info()))
2559    { }
2560
2561    /**
2562     *
2563     */
2564    Temp(const Formula &f)
2565        : node(new FormulaNode(f))
2566    { }
2567
2568    /**
2569     * Create a new ScalarProxyNode.
2570     * @param p The ScalarProxy to place in a node.
2571     */
2572    template <class Stat>
2573    Temp(const ScalarProxy<Stat> &p)
2574        : node(new ScalarProxyNode<Stat>(p))
2575    { }
2576
2577    /**
2578     * Create a ConstNode
2579     * @param value The value of the const node.
2580     */
2581    Temp(signed char value)
2582        : node(new ConstNode<signed char>(value))
2583    { }
2584
2585    /**
2586     * Create a ConstNode
2587     * @param value The value of the const node.
2588     */
2589    Temp(unsigned char value)
2590        : node(new ConstNode<unsigned char>(value))
2591    { }
2592
2593    /**
2594     * Create a ConstNode
2595     * @param value The value of the const node.
2596     */
2597    Temp(signed short value)
2598        : node(new ConstNode<signed short>(value))
2599    { }
2600
2601    /**
2602     * Create a ConstNode
2603     * @param value The value of the const node.
2604     */
2605    Temp(unsigned short value)
2606        : node(new ConstNode<unsigned short>(value))
2607    { }
2608
2609    /**
2610     * Create a ConstNode
2611     * @param value The value of the const node.
2612     */
2613    Temp(signed int value)
2614        : node(new ConstNode<signed int>(value))
2615    { }
2616
2617    /**
2618     * Create a ConstNode
2619     * @param value The value of the const node.
2620     */
2621    Temp(unsigned int value)
2622        : node(new ConstNode<unsigned int>(value))
2623    { }
2624
2625    /**
2626     * Create a ConstNode
2627     * @param value The value of the const node.
2628     */
2629    Temp(signed long value)
2630        : node(new ConstNode<signed long>(value))
2631    { }
2632
2633    /**
2634     * Create a ConstNode
2635     * @param value The value of the const node.
2636     */
2637    Temp(unsigned long value)
2638        : node(new ConstNode<unsigned long>(value))
2639    { }
2640
2641    /**
2642     * Create a ConstNode
2643     * @param value The value of the const node.
2644     */
2645    Temp(signed long long value)
2646        : node(new ConstNode<signed long long>(value))
2647    { }
2648
2649    /**
2650     * Create a ConstNode
2651     * @param value The value of the const node.
2652     */
2653    Temp(unsigned long long value)
2654        : node(new ConstNode<unsigned long long>(value))
2655    { }
2656
2657    /**
2658     * Create a ConstNode
2659     * @param value The value of the const node.
2660     */
2661    Temp(float value)
2662        : node(new ConstNode<float>(value))
2663    { }
2664
2665    /**
2666     * Create a ConstNode
2667     * @param value The value of the const node.
2668     */
2669    Temp(double value)
2670        : node(new ConstNode<double>(value))
2671    { }
2672};
2673
2674
2675/**
2676 * @}
2677 */
2678
2679inline Temp
2680operator+(Temp l, Temp r)
2681{
2682    return NodePtr(new BinaryNode<std::plus<Result> >(l, r));
2683}
2684
2685inline Temp
2686operator-(Temp l, Temp r)
2687{
2688    return NodePtr(new BinaryNode<std::minus<Result> >(l, r));
2689}
2690
2691inline Temp
2692operator*(Temp l, Temp r)
2693{
2694    return NodePtr(new BinaryNode<std::multiplies<Result> >(l, r));
2695}
2696
2697inline Temp
2698operator/(Temp l, Temp r)
2699{
2700    return NodePtr(new BinaryNode<std::divides<Result> >(l, r));
2701}
2702
2703inline Temp
2704operator-(Temp l)
2705{
2706    return NodePtr(new UnaryNode<std::negate<Result> >(l));
2707}
2708
2709template <typename T>
2710inline Temp
2711constant(T val)
2712{
2713    return NodePtr(new ConstNode<T>(val));
2714}
2715
2716template <typename T>
2717inline Temp
2718constantVector(T val)
2719{
2720    return NodePtr(new ConstVectorNode<T>(val));
2721}
2722
2723inline Temp
2724sum(Temp val)
2725{
2726    return NodePtr(new SumNode<std::plus<Result> >(val));
2727}
2728
2729/**
2730 * Enable the statistics package.  Before the statistics package is
2731 * enabled, all statistics must be created and initialized and once
2732 * the package is enabled, no more statistics can be created.
2733 */
2734void enable();
2735
2736/**
2737 * Prepare all stats for data access.  This must be done before
2738 * dumping and serialization.
2739 */
2740void prepare();
2741
2742/**
2743 * Dump all statistics data to the registered outputs
2744 */
2745void dump();
2746
2747/**
2748 * Reset all statistics to the base state
2749 */
2750void reset();
2751/**
2752 * Register a callback that should be called whenever statistics are
2753 * reset
2754 */
2755void registerResetCallback(Callback *cb);
2756
2757std::list<Info *> &statsList();
2758
2759/* namespace Stats */ }
2760
2761#endif // __BASE_STATISTICS_HH__
2762