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