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