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