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