statistics.hh revision 10422:148b96b7bc77
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 std::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
780/**
781 * A proxy similar to the FunctorProxy, but allows calling a method of a bound
782 * object, instead of a global free-standing function.
783 */
784template <class T, class V>
785class MethodProxy : public ProxyInfo
786{
787  private:
788    T *object;
789    typedef V (T::*MethodPointer) () const;
790    MethodPointer method;
791
792  public:
793    MethodProxy(T *obj, MethodPointer meth) : object(obj), method(meth) {}
794    Counter value() const { return (object->*method)(); }
795    Result result() const { return (object->*method)(); }
796    Result total() const { return (object->*method)(); }
797};
798
799template <class Derived>
800class ValueBase : public DataWrap<Derived, ScalarInfoProxy>
801{
802  private:
803    ProxyInfo *proxy;
804
805  public:
806    ValueBase() : proxy(NULL) { }
807    ~ValueBase() { if (proxy) delete proxy; }
808
809    template <class T>
810    Derived &
811    scalar(T &value)
812    {
813        proxy = new ValueProxy<T>(value);
814        this->setInit();
815        return this->self();
816    }
817
818    template <class T>
819    Derived &
820    functor(T &func)
821    {
822        proxy = new FunctorProxy<T>(func);
823        this->setInit();
824        return this->self();
825    }
826
827    /**
828     * Extended functor that calls the specified method of the provided object.
829     *
830     * @param obj Pointer to the object whose method should be called.
831     * @param method Pointer of the function / method of the object.
832     * @return Updated stats item.
833     */
834    template <class T, class V>
835    Derived &
836    method(T *obj,  V (T::*method)() const)
837    {
838        proxy = new MethodProxy<T,V>(obj, method);
839        this->setInit();
840        return this->self();
841    }
842
843    Counter value() { return proxy->value(); }
844    Result result() const { return proxy->result(); }
845    Result total() const { return proxy->total(); };
846    size_type size() const { return proxy->size(); }
847
848    std::string str() const { return proxy->str(); }
849    bool zero() const { return proxy->zero(); }
850    bool check() const { return proxy != NULL; }
851    void prepare() { }
852    void reset() { }
853};
854
855//////////////////////////////////////////////////////////////////////
856//
857// Vector Statistics
858//
859//////////////////////////////////////////////////////////////////////
860
861/**
862 * A proxy class to access the stat at a given index in a VectorBase stat.
863 * Behaves like a ScalarBase.
864 */
865template <class Stat>
866class ScalarProxy
867{
868  private:
869    /** Pointer to the parent Vector. */
870    Stat &stat;
871
872    /** The index to access in the parent VectorBase. */
873    off_type index;
874
875  public:
876    /**
877     * Return the current value of this stat as its base type.
878     * @return The current value.
879     */
880    Counter value() const { return stat.data(index)->value(); }
881
882    /**
883     * Return the current value of this statas a result type.
884     * @return The current value.
885     */
886    Result result() const { return stat.data(index)->result(); }
887
888  public:
889    /**
890     * Create and initialize this proxy, do not register it with the database.
891     * @param i The index to access.
892     */
893    ScalarProxy(Stat &s, off_type i)
894        : stat(s), index(i)
895    {
896    }
897
898    /**
899     * Create a copy of the provided ScalarProxy.
900     * @param sp The proxy to copy.
901     */
902    ScalarProxy(const ScalarProxy &sp)
903        : stat(sp.stat), index(sp.index)
904    {}
905
906    /**
907     * Set this proxy equal to the provided one.
908     * @param sp The proxy to copy.
909     * @return A reference to this proxy.
910     */
911    const ScalarProxy &
912    operator=(const ScalarProxy &sp)
913    {
914        stat = sp.stat;
915        index = sp.index;
916        return *this;
917    }
918
919  public:
920    // Common operators for stats
921    /**
922     * Increment the stat by 1. This calls the associated storage object inc
923     * function.
924     */
925    void operator++() { stat.data(index)->inc(1); }
926    /**
927     * Decrement the stat by 1. This calls the associated storage object dec
928     * function.
929     */
930    void operator--() { stat.data(index)->dec(1); }
931
932    /** Increment the stat by 1. */
933    void operator++(int) { ++*this; }
934    /** Decrement the stat by 1. */
935    void operator--(int) { --*this; }
936
937    /**
938     * Set the data value to the given value. This calls the associated storage
939     * object set function.
940     * @param v The new value.
941     */
942    template <typename U>
943    void
944    operator=(const U &v)
945    {
946        stat.data(index)->set(v);
947    }
948
949    /**
950     * Increment the stat by the given value. This calls the associated
951     * storage object inc function.
952     * @param v The value to add.
953     */
954    template <typename U>
955    void
956    operator+=(const U &v)
957    {
958        stat.data(index)->inc(v);
959    }
960
961    /**
962     * Decrement the stat by the given value. This calls the associated
963     * storage object dec function.
964     * @param v The value to substract.
965     */
966    template <typename U>
967    void
968    operator-=(const U &v)
969    {
970        stat.data(index)->dec(v);
971    }
972
973    /**
974     * Return the number of elements, always 1 for a scalar.
975     * @return 1.
976     */
977    size_type size() const { return 1; }
978
979  public:
980    std::string
981    str() const
982    {
983        return csprintf("%s[%d]", stat.info()->name, index);
984    }
985};
986
987/**
988 * Implementation of a vector of stats. The type of stat is determined by the
989 * Storage class. @sa ScalarBase
990 */
991template <class Derived, class Stor>
992class VectorBase : public DataWrapVec<Derived, VectorInfoProxy>
993{
994  public:
995    typedef Stor Storage;
996    typedef typename Stor::Params Params;
997
998    /** Proxy type */
999    typedef ScalarProxy<Derived> Proxy;
1000    friend class ScalarProxy<Derived>;
1001    friend class DataWrapVec<Derived, VectorInfoProxy>;
1002
1003  protected:
1004    /** The storage of this stat. */
1005    Storage *storage;
1006    size_type _size;
1007
1008  protected:
1009    /**
1010     * Retrieve the storage.
1011     * @param index The vector index to access.
1012     * @return The storage object at the given index.
1013     */
1014    Storage *data(off_type index) { return &storage[index]; }
1015
1016    /**
1017     * Retrieve a const pointer to the storage.
1018     * @param index The vector index to access.
1019     * @return A const pointer to the storage object at the given index.
1020     */
1021    const Storage *data(off_type index) const { return &storage[index]; }
1022
1023    void
1024    doInit(size_type s)
1025    {
1026        assert(s > 0 && "size must be positive!");
1027        assert(!storage && "already initialized");
1028        _size = s;
1029
1030        char *ptr = new char[_size * sizeof(Storage)];
1031        storage = reinterpret_cast<Storage *>(ptr);
1032
1033        for (off_type i = 0; i < _size; ++i)
1034            new (&storage[i]) Storage(this->info());
1035
1036        this->setInit();
1037    }
1038
1039  public:
1040    void
1041    value(VCounter &vec) const
1042    {
1043        vec.resize(size());
1044        for (off_type i = 0; i < size(); ++i)
1045            vec[i] = data(i)->value();
1046    }
1047
1048    /**
1049     * Copy the values to a local vector and return a reference to it.
1050     * @return A reference to a vector of the stat values.
1051     */
1052    void
1053    result(VResult &vec) const
1054    {
1055        vec.resize(size());
1056        for (off_type i = 0; i < size(); ++i)
1057            vec[i] = data(i)->result();
1058    }
1059
1060    /**
1061     * Return a total of all entries in this vector.
1062     * @return The total of all vector entries.
1063     */
1064    Result
1065    total() const
1066    {
1067        Result total = 0.0;
1068        for (off_type i = 0; i < size(); ++i)
1069            total += data(i)->result();
1070        return total;
1071    }
1072
1073    /**
1074     * @return the number of elements in this vector.
1075     */
1076    size_type size() const { return _size; }
1077
1078    bool
1079    zero() const
1080    {
1081        for (off_type i = 0; i < size(); ++i)
1082            if (data(i)->zero())
1083                return false;
1084        return true;
1085    }
1086
1087    bool
1088    check() const
1089    {
1090        return storage != NULL;
1091    }
1092
1093  public:
1094    VectorBase()
1095        : storage(nullptr), _size(0)
1096    {}
1097
1098    ~VectorBase()
1099    {
1100        if (!storage)
1101            return;
1102
1103        for (off_type i = 0; i < _size; ++i)
1104            data(i)->~Storage();
1105        delete [] reinterpret_cast<char *>(storage);
1106    }
1107
1108    /**
1109     * Set this vector to have the given size.
1110     * @param size The new size.
1111     * @return A reference to this stat.
1112     */
1113    Derived &
1114    init(size_type size)
1115    {
1116        Derived &self = this->self();
1117        self.doInit(size);
1118        return self;
1119    }
1120
1121    /**
1122     * Return a reference (ScalarProxy) to the stat at the given index.
1123     * @param index The vector index to access.
1124     * @return A reference of the stat.
1125     */
1126    Proxy
1127    operator[](off_type index)
1128    {
1129        assert (index >= 0 && index < size());
1130        return Proxy(this->self(), index);
1131    }
1132};
1133
1134template <class Stat>
1135class VectorProxy
1136{
1137  private:
1138    Stat &stat;
1139    off_type offset;
1140    size_type len;
1141
1142  private:
1143    mutable VResult vec;
1144
1145    typename Stat::Storage *
1146    data(off_type index)
1147    {
1148        assert(index < len);
1149        return stat.data(offset + index);
1150    }
1151
1152    const typename Stat::Storage *
1153    data(off_type index) const
1154    {
1155        assert(index < len);
1156        return stat.data(offset + index);
1157    }
1158
1159  public:
1160    const VResult &
1161    result() const
1162    {
1163        vec.resize(size());
1164
1165        for (off_type i = 0; i < size(); ++i)
1166            vec[i] = data(i)->result();
1167
1168        return vec;
1169    }
1170
1171    Result
1172    total() const
1173    {
1174        Result total = 0.0;
1175        for (off_type i = 0; i < size(); ++i)
1176            total += data(i)->result();
1177        return total;
1178    }
1179
1180  public:
1181    VectorProxy(Stat &s, off_type o, size_type l)
1182        : stat(s), offset(o), len(l)
1183    {
1184    }
1185
1186    VectorProxy(const VectorProxy &sp)
1187        : stat(sp.stat), offset(sp.offset), len(sp.len)
1188    {
1189    }
1190
1191    const VectorProxy &
1192    operator=(const VectorProxy &sp)
1193    {
1194        stat = sp.stat;
1195        offset = sp.offset;
1196        len = sp.len;
1197        return *this;
1198    }
1199
1200    ScalarProxy<Stat>
1201    operator[](off_type index)
1202    {
1203        assert (index >= 0 && index < size());
1204        return ScalarProxy<Stat>(stat, offset + index);
1205    }
1206
1207    size_type size() const { return len; }
1208};
1209
1210template <class Derived, class Stor>
1211class Vector2dBase : public DataWrapVec2d<Derived, Vector2dInfoProxy>
1212{
1213  public:
1214    typedef Vector2dInfoProxy<Derived> Info;
1215    typedef Stor Storage;
1216    typedef typename Stor::Params Params;
1217    typedef VectorProxy<Derived> Proxy;
1218    friend class ScalarProxy<Derived>;
1219    friend class VectorProxy<Derived>;
1220    friend class DataWrapVec<Derived, Vector2dInfoProxy>;
1221    friend class DataWrapVec2d<Derived, Vector2dInfoProxy>;
1222
1223  protected:
1224    size_type x;
1225    size_type y;
1226    size_type _size;
1227    Storage *storage;
1228
1229  protected:
1230    Storage *data(off_type index) { return &storage[index]; }
1231    const Storage *data(off_type index) const { return &storage[index]; }
1232
1233  public:
1234    Vector2dBase()
1235        : x(0), y(0), _size(0), storage(nullptr)
1236    {}
1237
1238    ~Vector2dBase()
1239    {
1240        if (!storage)
1241            return;
1242
1243        for (off_type i = 0; i < _size; ++i)
1244            data(i)->~Storage();
1245        delete [] reinterpret_cast<char *>(storage);
1246    }
1247
1248    Derived &
1249    init(size_type _x, size_type _y)
1250    {
1251        assert(_x > 0 && _y > 0 && "sizes must be positive!");
1252        assert(!storage && "already initialized");
1253
1254        Derived &self = this->self();
1255        Info *info = this->info();
1256
1257        x = _x;
1258        y = _y;
1259        info->x = _x;
1260        info->y = _y;
1261        _size = x * y;
1262
1263        char *ptr = new char[_size * sizeof(Storage)];
1264        storage = reinterpret_cast<Storage *>(ptr);
1265
1266        for (off_type i = 0; i < _size; ++i)
1267            new (&storage[i]) Storage(info);
1268
1269        this->setInit();
1270
1271        return self;
1272    }
1273
1274    Proxy
1275    operator[](off_type index)
1276    {
1277        off_type offset = index * y;
1278        assert (index >= 0 && offset + y <= size());
1279        return Proxy(this->self(), offset, y);
1280    }
1281
1282
1283    size_type
1284    size() const
1285    {
1286        return _size;
1287    }
1288
1289    bool
1290    zero() const
1291    {
1292        return data(0)->zero();
1293#if 0
1294        for (off_type i = 0; i < size(); ++i)
1295            if (!data(i)->zero())
1296                return false;
1297        return true;
1298#endif
1299    }
1300
1301    void
1302    prepare()
1303    {
1304        Info *info = this->info();
1305        size_type size = this->size();
1306
1307        for (off_type i = 0; i < size; ++i)
1308            data(i)->prepare(info);
1309
1310        info->cvec.resize(size);
1311        for (off_type i = 0; i < size; ++i)
1312            info->cvec[i] = data(i)->value();
1313    }
1314
1315    /**
1316     * Reset stat value to default
1317     */
1318    void
1319    reset()
1320    {
1321        Info *info = this->info();
1322        size_type size = this->size();
1323        for (off_type i = 0; i < size; ++i)
1324            data(i)->reset(info);
1325    }
1326
1327    bool
1328    check() const
1329    {
1330        return storage != NULL;
1331    }
1332};
1333
1334//////////////////////////////////////////////////////////////////////
1335//
1336// Non formula statistics
1337//
1338//////////////////////////////////////////////////////////////////////
1339/** The parameters for a distribution stat. */
1340struct DistParams : public StorageParams
1341{
1342    const DistType type;
1343    DistParams(DistType t) : type(t) {}
1344};
1345
1346/**
1347 * Templatized storage and interface for a distrbution stat.
1348 */
1349class DistStor
1350{
1351  public:
1352    /** The parameters for a distribution stat. */
1353    struct Params : public DistParams
1354    {
1355        /** The minimum value to track. */
1356        Counter min;
1357        /** The maximum value to track. */
1358        Counter max;
1359        /** The number of entries in each bucket. */
1360        Counter bucket_size;
1361        /** The number of buckets. Equal to (max-min)/bucket_size. */
1362        size_type buckets;
1363
1364        Params() : DistParams(Dist), min(0), max(0), bucket_size(0),
1365                   buckets(0) {}
1366    };
1367
1368  private:
1369    /** The minimum value to track. */
1370    Counter min_track;
1371    /** The maximum value to track. */
1372    Counter max_track;
1373    /** The number of entries in each bucket. */
1374    Counter bucket_size;
1375
1376    /** The smallest value sampled. */
1377    Counter min_val;
1378    /** The largest value sampled. */
1379    Counter max_val;
1380    /** The number of values sampled less than min. */
1381    Counter underflow;
1382    /** The number of values sampled more than max. */
1383    Counter overflow;
1384    /** The current sum. */
1385    Counter sum;
1386    /** The sum of squares. */
1387    Counter squares;
1388    /** The number of samples. */
1389    Counter samples;
1390    /** Counter for each bucket. */
1391    VCounter cvec;
1392
1393  public:
1394    DistStor(Info *info)
1395        : cvec(safe_cast<const Params *>(info->storageParams)->buckets)
1396    {
1397        reset(info);
1398    }
1399
1400    /**
1401     * Add a value to the distribution for the given number of times.
1402     * @param val The value to add.
1403     * @param number The number of times to add the value.
1404     */
1405    void
1406    sample(Counter val, int number)
1407    {
1408        if (val < min_track)
1409            underflow += number;
1410        else if (val > max_track)
1411            overflow += number;
1412        else {
1413            size_type index =
1414                (size_type)std::floor((val - min_track) / bucket_size);
1415            assert(index < size());
1416            cvec[index] += number;
1417        }
1418
1419        if (val < min_val)
1420            min_val = val;
1421
1422        if (val > max_val)
1423            max_val = val;
1424
1425        sum += val * number;
1426        squares += val * val * number;
1427        samples += number;
1428    }
1429
1430    /**
1431     * Return the number of buckets in this distribution.
1432     * @return the number of buckets.
1433     */
1434    size_type size() const { return cvec.size(); }
1435
1436    /**
1437     * Returns true if any calls to sample have been made.
1438     * @return True if any values have been sampled.
1439     */
1440    bool
1441    zero() const
1442    {
1443        return samples == Counter();
1444    }
1445
1446    void
1447    prepare(Info *info, DistData &data)
1448    {
1449        const Params *params = safe_cast<const Params *>(info->storageParams);
1450
1451        assert(params->type == Dist);
1452        data.type = params->type;
1453        data.min = params->min;
1454        data.max = params->max;
1455        data.bucket_size = params->bucket_size;
1456
1457        data.min_val = (min_val == CounterLimits::max()) ? 0 : min_val;
1458        data.max_val = (max_val == CounterLimits::min()) ? 0 : max_val;
1459        data.underflow = underflow;
1460        data.overflow = overflow;
1461
1462        data.cvec.resize(params->buckets);
1463        for (off_type i = 0; i < params->buckets; ++i)
1464            data.cvec[i] = cvec[i];
1465
1466        data.sum = sum;
1467        data.squares = squares;
1468        data.samples = samples;
1469    }
1470
1471    /**
1472     * Reset stat value to default
1473     */
1474    void
1475    reset(Info *info)
1476    {
1477        const Params *params = safe_cast<const Params *>(info->storageParams);
1478        min_track = params->min;
1479        max_track = params->max;
1480        bucket_size = params->bucket_size;
1481
1482        min_val = CounterLimits::max();
1483        max_val = CounterLimits::min();
1484        underflow = Counter();
1485        overflow = Counter();
1486
1487        size_type size = cvec.size();
1488        for (off_type i = 0; i < size; ++i)
1489            cvec[i] = Counter();
1490
1491        sum = Counter();
1492        squares = Counter();
1493        samples = Counter();
1494    }
1495};
1496
1497/**
1498 * Templatized storage and interface for a histogram stat.
1499 */
1500class HistStor
1501{
1502  public:
1503    /** The parameters for a distribution stat. */
1504    struct Params : public DistParams
1505    {
1506        /** The number of buckets.. */
1507        size_type buckets;
1508
1509        Params() : DistParams(Hist), buckets(0) {}
1510    };
1511
1512  private:
1513    /** The minimum value to track. */
1514    Counter min_bucket;
1515    /** The maximum value to track. */
1516    Counter max_bucket;
1517    /** The number of entries in each bucket. */
1518    Counter bucket_size;
1519
1520    /** The current sum. */
1521    Counter sum;
1522    /** The sum of logarithm of each sample, used to compute geometric mean. */
1523    Counter logs;
1524    /** The sum of squares. */
1525    Counter squares;
1526    /** The number of samples. */
1527    Counter samples;
1528    /** Counter for each bucket. */
1529    VCounter cvec;
1530
1531  public:
1532    HistStor(Info *info)
1533        : cvec(safe_cast<const Params *>(info->storageParams)->buckets)
1534    {
1535        reset(info);
1536    }
1537
1538    void grow_up();
1539    void grow_out();
1540    void grow_convert();
1541    void add(HistStor *);
1542
1543    /**
1544     * Add a value to the distribution for the given number of times.
1545     * @param val The value to add.
1546     * @param number The number of times to add the value.
1547     */
1548    void
1549    sample(Counter val, int number)
1550    {
1551        assert(min_bucket < max_bucket);
1552        if (val < min_bucket) {
1553            if (min_bucket == 0)
1554                grow_convert();
1555
1556            while (val < min_bucket)
1557                grow_out();
1558        } else if (val >= max_bucket + bucket_size) {
1559            if (min_bucket == 0) {
1560                while (val >= max_bucket + bucket_size)
1561                    grow_up();
1562            } else {
1563                while (val >= max_bucket + bucket_size)
1564                    grow_out();
1565            }
1566        }
1567
1568        size_type index =
1569            (int64_t)std::floor((val - min_bucket) / bucket_size);
1570
1571        assert(index < size());
1572        cvec[index] += number;
1573
1574        sum += val * number;
1575        squares += val * val * number;
1576        logs += log(val) * number;
1577        samples += number;
1578    }
1579
1580    /**
1581     * Return the number of buckets in this distribution.
1582     * @return the number of buckets.
1583     */
1584    size_type size() const { return cvec.size(); }
1585
1586    /**
1587     * Returns true if any calls to sample have been made.
1588     * @return True if any values have been sampled.
1589     */
1590    bool
1591    zero() const
1592    {
1593        return samples == Counter();
1594    }
1595
1596    void
1597    prepare(Info *info, DistData &data)
1598    {
1599        const Params *params = safe_cast<const Params *>(info->storageParams);
1600
1601        assert(params->type == Hist);
1602        data.type = params->type;
1603        data.min = min_bucket;
1604        data.max = max_bucket + bucket_size - 1;
1605        data.bucket_size = bucket_size;
1606
1607        data.min_val = min_bucket;
1608        data.max_val = max_bucket;
1609
1610        int buckets = params->buckets;
1611        data.cvec.resize(buckets);
1612        for (off_type i = 0; i < buckets; ++i)
1613            data.cvec[i] = cvec[i];
1614
1615        data.sum = sum;
1616        data.logs = logs;
1617        data.squares = squares;
1618        data.samples = samples;
1619    }
1620
1621    /**
1622     * Reset stat value to default
1623     */
1624    void
1625    reset(Info *info)
1626    {
1627        const Params *params = safe_cast<const Params *>(info->storageParams);
1628        min_bucket = 0;
1629        max_bucket = params->buckets - 1;
1630        bucket_size = 1;
1631
1632        size_type size = cvec.size();
1633        for (off_type i = 0; i < size; ++i)
1634            cvec[i] = Counter();
1635
1636        sum = Counter();
1637        squares = Counter();
1638        samples = Counter();
1639        logs = Counter();
1640    }
1641};
1642
1643/**
1644 * Templatized storage and interface for a distribution that calculates mean
1645 * and variance.
1646 */
1647class SampleStor
1648{
1649  public:
1650    struct Params : public DistParams
1651    {
1652        Params() : DistParams(Deviation) {}
1653    };
1654
1655  private:
1656    /** The current sum. */
1657    Counter sum;
1658    /** The sum of squares. */
1659    Counter squares;
1660    /** The number of samples. */
1661    Counter samples;
1662
1663  public:
1664    /**
1665     * Create and initialize this storage.
1666     */
1667    SampleStor(Info *info)
1668        : sum(Counter()), squares(Counter()), samples(Counter())
1669    { }
1670
1671    /**
1672     * Add a value the given number of times to this running average.
1673     * Update the running sum and sum of squares, increment the number of
1674     * values seen by the given number.
1675     * @param val The value to add.
1676     * @param number The number of times to add the value.
1677     */
1678    void
1679    sample(Counter val, int number)
1680    {
1681        Counter value = val * number;
1682        sum += value;
1683        squares += value * value;
1684        samples += number;
1685    }
1686
1687    /**
1688     * Return the number of entries in this stat, 1
1689     * @return 1.
1690     */
1691    size_type size() const { return 1; }
1692
1693    /**
1694     * Return true if no samples have been added.
1695     * @return True if no samples have been added.
1696     */
1697    bool zero() const { return samples == Counter(); }
1698
1699    void
1700    prepare(Info *info, DistData &data)
1701    {
1702        const Params *params = safe_cast<const Params *>(info->storageParams);
1703
1704        assert(params->type == Deviation);
1705        data.type = params->type;
1706        data.sum = sum;
1707        data.squares = squares;
1708        data.samples = samples;
1709    }
1710
1711    /**
1712     * Reset stat value to default
1713     */
1714    void
1715    reset(Info *info)
1716    {
1717        sum = Counter();
1718        squares = Counter();
1719        samples = Counter();
1720    }
1721};
1722
1723/**
1724 * Templatized storage for distribution that calculates per tick mean and
1725 * variance.
1726 */
1727class AvgSampleStor
1728{
1729  public:
1730    struct Params : public DistParams
1731    {
1732        Params() : DistParams(Deviation) {}
1733    };
1734
1735  private:
1736    /** Current total. */
1737    Counter sum;
1738    /** Current sum of squares. */
1739    Counter squares;
1740
1741  public:
1742    /**
1743     * Create and initialize this storage.
1744     */
1745    AvgSampleStor(Info *info)
1746        : sum(Counter()), squares(Counter())
1747    {}
1748
1749    /**
1750     * Add a value to the distribution for the given number of times.
1751     * Update the running sum and sum of squares.
1752     * @param val The value to add.
1753     * @param number The number of times to add the value.
1754     */
1755    void
1756    sample(Counter val, int number)
1757    {
1758        Counter value = val * number;
1759        sum += value;
1760        squares += value * value;
1761    }
1762
1763    /**
1764     * Return the number of entries, in this case 1.
1765     * @return 1.
1766     */
1767    size_type size() const { return 1; }
1768
1769    /**
1770     * Return true if no samples have been added.
1771     * @return True if the sum is zero.
1772     */
1773    bool zero() const { return sum == Counter(); }
1774
1775    void
1776    prepare(Info *info, DistData &data)
1777    {
1778        const Params *params = safe_cast<const Params *>(info->storageParams);
1779
1780        assert(params->type == Deviation);
1781        data.type = params->type;
1782        data.sum = sum;
1783        data.squares = squares;
1784        data.samples = curTick();
1785    }
1786
1787    /**
1788     * Reset stat value to default
1789     */
1790    void
1791    reset(Info *info)
1792    {
1793        sum = Counter();
1794        squares = Counter();
1795    }
1796};
1797
1798/**
1799 * Implementation of a distribution stat. The type of distribution is
1800 * determined by the Storage template. @sa ScalarBase
1801 */
1802template <class Derived, class Stor>
1803class DistBase : public DataWrap<Derived, DistInfoProxy>
1804{
1805  public:
1806    typedef DistInfoProxy<Derived> Info;
1807    typedef Stor Storage;
1808    typedef typename Stor::Params Params;
1809
1810  protected:
1811    /** The storage for this stat. */
1812    char storage[sizeof(Storage)] __attribute__ ((aligned (8)));
1813
1814  protected:
1815    /**
1816     * Retrieve the storage.
1817     * @return The storage object for this stat.
1818     */
1819    Storage *
1820    data()
1821    {
1822        return reinterpret_cast<Storage *>(storage);
1823    }
1824
1825    /**
1826     * Retrieve a const pointer to the storage.
1827     * @return A const pointer to the storage object for this stat.
1828     */
1829    const Storage *
1830    data() const
1831    {
1832        return reinterpret_cast<const Storage *>(storage);
1833    }
1834
1835    void
1836    doInit()
1837    {
1838        new (storage) Storage(this->info());
1839        this->setInit();
1840    }
1841
1842  public:
1843    DistBase() { }
1844
1845    /**
1846     * Add a value to the distribtion n times. Calls sample on the storage
1847     * class.
1848     * @param v The value to add.
1849     * @param n The number of times to add it, defaults to 1.
1850     */
1851    template <typename U>
1852    void sample(const U &v, int n = 1) { data()->sample(v, n); }
1853
1854    /**
1855     * Return the number of entries in this stat.
1856     * @return The number of entries.
1857     */
1858    size_type size() const { return data()->size(); }
1859    /**
1860     * Return true if no samples have been added.
1861     * @return True if there haven't been any samples.
1862     */
1863    bool zero() const { return data()->zero(); }
1864
1865    void
1866    prepare()
1867    {
1868        Info *info = this->info();
1869        data()->prepare(info, info->data);
1870    }
1871
1872    /**
1873     * Reset stat value to default
1874     */
1875    void
1876    reset()
1877    {
1878        data()->reset(this->info());
1879    }
1880
1881    /**
1882     *  Add the argument distribution to the this distibution.
1883     */
1884    void add(DistBase &d) { data()->add(d.data()); }
1885
1886};
1887
1888template <class Stat>
1889class DistProxy;
1890
1891template <class Derived, class Stor>
1892class VectorDistBase : public DataWrapVec<Derived, VectorDistInfoProxy>
1893{
1894  public:
1895    typedef VectorDistInfoProxy<Derived> Info;
1896    typedef Stor Storage;
1897    typedef typename Stor::Params Params;
1898    typedef DistProxy<Derived> Proxy;
1899    friend class DistProxy<Derived>;
1900    friend class DataWrapVec<Derived, VectorDistInfoProxy>;
1901
1902  protected:
1903    Storage *storage;
1904    size_type _size;
1905
1906  protected:
1907    Storage *
1908    data(off_type index)
1909    {
1910        return &storage[index];
1911    }
1912
1913    const Storage *
1914    data(off_type index) const
1915    {
1916        return &storage[index];
1917    }
1918
1919    void
1920    doInit(size_type s)
1921    {
1922        assert(s > 0 && "size must be positive!");
1923        assert(!storage && "already initialized");
1924        _size = s;
1925
1926        char *ptr = new char[_size * sizeof(Storage)];
1927        storage = reinterpret_cast<Storage *>(ptr);
1928
1929        Info *info = this->info();
1930        for (off_type i = 0; i < _size; ++i)
1931            new (&storage[i]) Storage(info);
1932
1933        this->setInit();
1934    }
1935
1936  public:
1937    VectorDistBase()
1938        : storage(NULL)
1939    {}
1940
1941    ~VectorDistBase()
1942    {
1943        if (!storage)
1944            return ;
1945
1946        for (off_type i = 0; i < _size; ++i)
1947            data(i)->~Storage();
1948        delete [] reinterpret_cast<char *>(storage);
1949    }
1950
1951    Proxy operator[](off_type index)
1952    {
1953        assert(index >= 0 && index < size());
1954        return Proxy(this->self(), index);
1955    }
1956
1957    size_type
1958    size() const
1959    {
1960        return _size;
1961    }
1962
1963    bool
1964    zero() const
1965    {
1966        for (off_type i = 0; i < size(); ++i)
1967            if (!data(i)->zero())
1968                return false;
1969        return true;
1970    }
1971
1972    void
1973    prepare()
1974    {
1975        Info *info = this->info();
1976        size_type size = this->size();
1977        info->data.resize(size);
1978        for (off_type i = 0; i < size; ++i)
1979            data(i)->prepare(info, info->data[i]);
1980    }
1981
1982    bool
1983    check() const
1984    {
1985        return storage != NULL;
1986    }
1987};
1988
1989template <class Stat>
1990class DistProxy
1991{
1992  private:
1993    Stat &stat;
1994    off_type index;
1995
1996  protected:
1997    typename Stat::Storage *data() { return stat.data(index); }
1998    const typename Stat::Storage *data() const { return stat.data(index); }
1999
2000  public:
2001    DistProxy(Stat &s, off_type i)
2002        : stat(s), index(i)
2003    {}
2004
2005    DistProxy(const DistProxy &sp)
2006        : stat(sp.stat), index(sp.index)
2007    {}
2008
2009    const DistProxy &
2010    operator=(const DistProxy &sp)
2011    {
2012        stat = sp.stat;
2013        index = sp.index;
2014        return *this;
2015    }
2016
2017  public:
2018    template <typename U>
2019    void
2020    sample(const U &v, int n = 1)
2021    {
2022        data()->sample(v, n);
2023    }
2024
2025    size_type
2026    size() const
2027    {
2028        return 1;
2029    }
2030
2031    bool
2032    zero() const
2033    {
2034        return data()->zero();
2035    }
2036
2037    /**
2038     * Proxy has no state.  Nothing to reset.
2039     */
2040    void reset() { }
2041};
2042
2043//////////////////////////////////////////////////////////////////////
2044//
2045//  Formula Details
2046//
2047//////////////////////////////////////////////////////////////////////
2048
2049/**
2050 * Base class for formula statistic node. These nodes are used to build a tree
2051 * that represents the formula.
2052 */
2053class Node : public RefCounted
2054{
2055  public:
2056    /**
2057     * Return the number of nodes in the subtree starting at this node.
2058     * @return the number of nodes in this subtree.
2059     */
2060    virtual size_type size() const = 0;
2061    /**
2062     * Return the result vector of this subtree.
2063     * @return The result vector of this subtree.
2064     */
2065    virtual const VResult &result() const = 0;
2066    /**
2067     * Return the total of the result vector.
2068     * @return The total of the result vector.
2069     */
2070    virtual Result total() const = 0;
2071
2072    /**
2073     *
2074     */
2075    virtual std::string str() const = 0;
2076};
2077
2078/** Reference counting pointer to a function Node. */
2079typedef RefCountingPtr<Node> NodePtr;
2080
2081class ScalarStatNode : public Node
2082{
2083  private:
2084    const ScalarInfo *data;
2085    mutable VResult vresult;
2086
2087  public:
2088    ScalarStatNode(const ScalarInfo *d) : data(d), vresult(1) {}
2089
2090    const VResult &
2091    result() const
2092    {
2093        vresult[0] = data->result();
2094        return vresult;
2095    }
2096
2097    Result total() const { return data->result(); };
2098
2099    size_type size() const { return 1; }
2100
2101    /**
2102     *
2103     */
2104    std::string str() const { return data->name; }
2105};
2106
2107template <class Stat>
2108class ScalarProxyNode : public Node
2109{
2110  private:
2111    const ScalarProxy<Stat> proxy;
2112    mutable VResult vresult;
2113
2114  public:
2115    ScalarProxyNode(const ScalarProxy<Stat> &p)
2116        : proxy(p), vresult(1)
2117    { }
2118
2119    const VResult &
2120    result() const
2121    {
2122        vresult[0] = proxy.result();
2123        return vresult;
2124    }
2125
2126    Result
2127    total() const
2128    {
2129        return proxy.result();
2130    }
2131
2132    size_type
2133    size() const
2134    {
2135        return 1;
2136    }
2137
2138    /**
2139     *
2140     */
2141    std::string
2142    str() const
2143    {
2144        return proxy.str();
2145    }
2146};
2147
2148class VectorStatNode : public Node
2149{
2150  private:
2151    const VectorInfo *data;
2152
2153  public:
2154    VectorStatNode(const VectorInfo *d) : data(d) { }
2155    const VResult &result() const { return data->result(); }
2156    Result total() const { return data->total(); };
2157
2158    size_type size() const { return data->size(); }
2159
2160    std::string str() const { return data->name; }
2161};
2162
2163template <class T>
2164class ConstNode : public Node
2165{
2166  private:
2167    VResult vresult;
2168
2169  public:
2170    ConstNode(T s) : vresult(1, (Result)s) {}
2171    const VResult &result() const { return vresult; }
2172    Result total() const { return vresult[0]; };
2173    size_type size() const { return 1; }
2174    std::string str() const { return std::to_string(vresult[0]); }
2175};
2176
2177template <class T>
2178class ConstVectorNode : public Node
2179{
2180  private:
2181    VResult vresult;
2182
2183  public:
2184    ConstVectorNode(const T &s) : vresult(s.begin(), s.end()) {}
2185    const VResult &result() const { return vresult; }
2186
2187    Result
2188    total() const
2189    {
2190        size_type size = this->size();
2191        Result tmp = 0;
2192        for (off_type i = 0; i < size; i++)
2193            tmp += vresult[i];
2194        return tmp;
2195    }
2196
2197    size_type size() const { return vresult.size(); }
2198    std::string
2199    str() const
2200    {
2201        size_type size = this->size();
2202        std::string tmp = "(";
2203        for (off_type i = 0; i < size; i++)
2204            tmp += csprintf("%s ", std::to_string(vresult[i]));
2205        tmp += ")";
2206        return tmp;
2207    }
2208};
2209
2210template <class Op>
2211struct OpString;
2212
2213template<>
2214struct OpString<std::plus<Result> >
2215{
2216    static std::string str() { return "+"; }
2217};
2218
2219template<>
2220struct OpString<std::minus<Result> >
2221{
2222    static std::string str() { return "-"; }
2223};
2224
2225template<>
2226struct OpString<std::multiplies<Result> >
2227{
2228    static std::string str() { return "*"; }
2229};
2230
2231template<>
2232struct OpString<std::divides<Result> >
2233{
2234    static std::string str() { return "/"; }
2235};
2236
2237template<>
2238struct OpString<std::modulus<Result> >
2239{
2240    static std::string str() { return "%"; }
2241};
2242
2243template<>
2244struct OpString<std::negate<Result> >
2245{
2246    static std::string str() { return "-"; }
2247};
2248
2249template <class Op>
2250class UnaryNode : public Node
2251{
2252  public:
2253    NodePtr l;
2254    mutable VResult vresult;
2255
2256  public:
2257    UnaryNode(NodePtr &p) : l(p) {}
2258
2259    const VResult &
2260    result() const
2261    {
2262        const VResult &lvec = l->result();
2263        size_type size = lvec.size();
2264
2265        assert(size > 0);
2266
2267        vresult.resize(size);
2268        Op op;
2269        for (off_type i = 0; i < size; ++i)
2270            vresult[i] = op(lvec[i]);
2271
2272        return vresult;
2273    }
2274
2275    Result
2276    total() const
2277    {
2278        const VResult &vec = this->result();
2279        Result total = 0.0;
2280        for (off_type i = 0; i < size(); i++)
2281            total += vec[i];
2282        return total;
2283    }
2284
2285    size_type size() const { return l->size(); }
2286
2287    std::string
2288    str() const
2289    {
2290        return OpString<Op>::str() + l->str();
2291    }
2292};
2293
2294template <class Op>
2295class BinaryNode : public Node
2296{
2297  public:
2298    NodePtr l;
2299    NodePtr r;
2300    mutable VResult vresult;
2301
2302  public:
2303    BinaryNode(NodePtr &a, NodePtr &b) : l(a), r(b) {}
2304
2305    const VResult &
2306    result() const
2307    {
2308        Op op;
2309        const VResult &lvec = l->result();
2310        const VResult &rvec = r->result();
2311
2312        assert(lvec.size() > 0 && rvec.size() > 0);
2313
2314        if (lvec.size() == 1 && rvec.size() == 1) {
2315            vresult.resize(1);
2316            vresult[0] = op(lvec[0], rvec[0]);
2317        } else if (lvec.size() == 1) {
2318            size_type size = rvec.size();
2319            vresult.resize(size);
2320            for (off_type i = 0; i < size; ++i)
2321                vresult[i] = op(lvec[0], rvec[i]);
2322        } else if (rvec.size() == 1) {
2323            size_type size = lvec.size();
2324            vresult.resize(size);
2325            for (off_type i = 0; i < size; ++i)
2326                vresult[i] = op(lvec[i], rvec[0]);
2327        } else if (rvec.size() == lvec.size()) {
2328            size_type size = rvec.size();
2329            vresult.resize(size);
2330            for (off_type i = 0; i < size; ++i)
2331                vresult[i] = op(lvec[i], rvec[i]);
2332        }
2333
2334        return vresult;
2335    }
2336
2337    Result
2338    total() const
2339    {
2340        const VResult &vec = this->result();
2341        const VResult &lvec = l->result();
2342        const VResult &rvec = r->result();
2343        Result total = 0.0;
2344        Result lsum = 0.0;
2345        Result rsum = 0.0;
2346        Op op;
2347
2348        assert(lvec.size() > 0 && rvec.size() > 0);
2349        assert(lvec.size() == rvec.size() ||
2350               lvec.size() == 1 || rvec.size() == 1);
2351
2352        /** If vectors are the same divide their sums (x0+x1)/(y0+y1) */
2353        if (lvec.size() == rvec.size() && lvec.size() > 1) {
2354            for (off_type i = 0; i < size(); ++i) {
2355                lsum += lvec[i];
2356                rsum += rvec[i];
2357            }
2358            return op(lsum, rsum);
2359        }
2360
2361        /** Otherwise divide each item by the divisor */
2362        for (off_type i = 0; i < size(); ++i) {
2363            total += vec[i];
2364        }
2365
2366        return total;
2367    }
2368
2369    size_type
2370    size() const
2371    {
2372        size_type ls = l->size();
2373        size_type rs = r->size();
2374        if (ls == 1) {
2375            return rs;
2376        } else if (rs == 1) {
2377            return ls;
2378        } else {
2379            assert(ls == rs && "Node vector sizes are not equal");
2380            return ls;
2381        }
2382    }
2383
2384    std::string
2385    str() const
2386    {
2387        return csprintf("(%s %s %s)", l->str(), OpString<Op>::str(), r->str());
2388    }
2389};
2390
2391template <class Op>
2392class SumNode : public Node
2393{
2394  public:
2395    NodePtr l;
2396    mutable VResult vresult;
2397
2398  public:
2399    SumNode(NodePtr &p) : l(p), vresult(1) {}
2400
2401    const VResult &
2402    result() const
2403    {
2404        const VResult &lvec = l->result();
2405        size_type size = lvec.size();
2406        assert(size > 0);
2407
2408        vresult[0] = 0.0;
2409
2410        Op op;
2411        for (off_type i = 0; i < size; ++i)
2412            vresult[0] = op(vresult[0], lvec[i]);
2413
2414        return vresult;
2415    }
2416
2417    Result
2418    total() const
2419    {
2420        const VResult &lvec = l->result();
2421        size_type size = lvec.size();
2422        assert(size > 0);
2423
2424        Result result = 0.0;
2425
2426        Op op;
2427        for (off_type i = 0; i < size; ++i)
2428            result = op(result, lvec[i]);
2429
2430        return result;
2431    }
2432
2433    size_type size() const { return 1; }
2434
2435    std::string
2436    str() const
2437    {
2438        return csprintf("total(%s)", l->str());
2439    }
2440};
2441
2442
2443//////////////////////////////////////////////////////////////////////
2444//
2445// Visible Statistics Types
2446//
2447//////////////////////////////////////////////////////////////////////
2448/**
2449 * @defgroup VisibleStats "Statistic Types"
2450 * These are the statistics that are used in the simulator.
2451 * @{
2452 */
2453
2454/**
2455 * This is a simple scalar statistic, like a counter.
2456 * @sa Stat, ScalarBase, StatStor
2457 */
2458class Scalar : public ScalarBase<Scalar, StatStor>
2459{
2460  public:
2461    using ScalarBase<Scalar, StatStor>::operator=;
2462};
2463
2464/**
2465 * A stat that calculates the per tick average of a value.
2466 * @sa Stat, ScalarBase, AvgStor
2467 */
2468class Average : public ScalarBase<Average, AvgStor>
2469{
2470  public:
2471    using ScalarBase<Average, AvgStor>::operator=;
2472};
2473
2474class Value : public ValueBase<Value>
2475{
2476};
2477
2478/**
2479 * A vector of scalar stats.
2480 * @sa Stat, VectorBase, StatStor
2481 */
2482class Vector : public VectorBase<Vector, StatStor>
2483{
2484};
2485
2486/**
2487 * A vector of Average stats.
2488 * @sa Stat, VectorBase, AvgStor
2489 */
2490class AverageVector : public VectorBase<AverageVector, AvgStor>
2491{
2492};
2493
2494/**
2495 * A 2-Dimensional vecto of scalar stats.
2496 * @sa Stat, Vector2dBase, StatStor
2497 */
2498class Vector2d : public Vector2dBase<Vector2d, StatStor>
2499{
2500};
2501
2502/**
2503 * A simple distribution stat.
2504 * @sa Stat, DistBase, DistStor
2505 */
2506class Distribution : public DistBase<Distribution, DistStor>
2507{
2508  public:
2509    /**
2510     * Set the parameters of this distribution. @sa DistStor::Params
2511     * @param min The minimum value of the distribution.
2512     * @param max The maximum value of the distribution.
2513     * @param bkt The number of values in each bucket.
2514     * @return A reference to this distribution.
2515     */
2516    Distribution &
2517    init(Counter min, Counter max, Counter bkt)
2518    {
2519        DistStor::Params *params = new DistStor::Params;
2520        params->min = min;
2521        params->max = max;
2522        params->bucket_size = bkt;
2523        params->buckets = (size_type)ceil((max - min + 1.0) / bkt);
2524        this->setParams(params);
2525        this->doInit();
2526        return this->self();
2527    }
2528};
2529
2530/**
2531 * A simple histogram stat.
2532 * @sa Stat, DistBase, HistStor
2533 */
2534class Histogram : public DistBase<Histogram, HistStor>
2535{
2536  public:
2537    /**
2538     * Set the parameters of this histogram. @sa HistStor::Params
2539     * @param size The number of buckets in the histogram
2540     * @return A reference to this histogram.
2541     */
2542    Histogram &
2543    init(size_type size)
2544    {
2545        HistStor::Params *params = new HistStor::Params;
2546        params->buckets = size;
2547        this->setParams(params);
2548        this->doInit();
2549        return this->self();
2550    }
2551};
2552
2553/**
2554 * Calculates the mean and variance of all the samples.
2555 * @sa DistBase, SampleStor
2556 */
2557class StandardDeviation : public DistBase<StandardDeviation, SampleStor>
2558{
2559  public:
2560    /**
2561     * Construct and initialize this distribution.
2562     */
2563    StandardDeviation()
2564    {
2565        SampleStor::Params *params = new SampleStor::Params;
2566        this->doInit();
2567        this->setParams(params);
2568    }
2569};
2570
2571/**
2572 * Calculates the per tick mean and variance of the samples.
2573 * @sa DistBase, AvgSampleStor
2574 */
2575class AverageDeviation : public DistBase<AverageDeviation, AvgSampleStor>
2576{
2577  public:
2578    /**
2579     * Construct and initialize this distribution.
2580     */
2581    AverageDeviation()
2582    {
2583        AvgSampleStor::Params *params = new AvgSampleStor::Params;
2584        this->doInit();
2585        this->setParams(params);
2586    }
2587};
2588
2589/**
2590 * A vector of distributions.
2591 * @sa VectorDistBase, DistStor
2592 */
2593class VectorDistribution : public VectorDistBase<VectorDistribution, DistStor>
2594{
2595  public:
2596    /**
2597     * Initialize storage and parameters for this distribution.
2598     * @param size The size of the vector (the number of distributions).
2599     * @param min The minimum value of the distribution.
2600     * @param max The maximum value of the distribution.
2601     * @param bkt The number of values in each bucket.
2602     * @return A reference to this distribution.
2603     */
2604    VectorDistribution &
2605    init(size_type size, Counter min, Counter max, Counter bkt)
2606    {
2607        DistStor::Params *params = new DistStor::Params;
2608        params->min = min;
2609        params->max = max;
2610        params->bucket_size = bkt;
2611        params->buckets = (size_type)ceil((max - min + 1.0) / bkt);
2612        this->setParams(params);
2613        this->doInit(size);
2614        return this->self();
2615    }
2616};
2617
2618/**
2619 * This is a vector of StandardDeviation stats.
2620 * @sa VectorDistBase, SampleStor
2621 */
2622class VectorStandardDeviation
2623    : public VectorDistBase<VectorStandardDeviation, SampleStor>
2624{
2625  public:
2626    /**
2627     * Initialize storage for this distribution.
2628     * @param size The size of the vector.
2629     * @return A reference to this distribution.
2630     */
2631    VectorStandardDeviation &
2632    init(size_type size)
2633    {
2634        SampleStor::Params *params = new SampleStor::Params;
2635        this->doInit(size);
2636        this->setParams(params);
2637        return this->self();
2638    }
2639};
2640
2641/**
2642 * This is a vector of AverageDeviation stats.
2643 * @sa VectorDistBase, AvgSampleStor
2644 */
2645class VectorAverageDeviation
2646    : public VectorDistBase<VectorAverageDeviation, AvgSampleStor>
2647{
2648  public:
2649    /**
2650     * Initialize storage for this distribution.
2651     * @param size The size of the vector.
2652     * @return A reference to this distribution.
2653     */
2654    VectorAverageDeviation &
2655    init(size_type size)
2656    {
2657        AvgSampleStor::Params *params = new AvgSampleStor::Params;
2658        this->doInit(size);
2659        this->setParams(params);
2660        return this->self();
2661    }
2662};
2663
2664template <class Stat>
2665class FormulaInfoProxy : public InfoProxy<Stat, FormulaInfo>
2666{
2667  protected:
2668    mutable VResult vec;
2669    mutable VCounter cvec;
2670
2671  public:
2672    FormulaInfoProxy(Stat &stat) : InfoProxy<Stat, FormulaInfo>(stat) {}
2673
2674    size_type size() const { return this->s.size(); }
2675
2676    const VResult &
2677    result() const
2678    {
2679        this->s.result(vec);
2680        return vec;
2681    }
2682    Result total() const { return this->s.total(); }
2683    VCounter &value() const { return cvec; }
2684
2685    std::string str() const { return this->s.str(); }
2686};
2687
2688template <class Stat>
2689class SparseHistInfoProxy : public InfoProxy<Stat, SparseHistInfo>
2690{
2691  public:
2692    SparseHistInfoProxy(Stat &stat) : InfoProxy<Stat, SparseHistInfo>(stat) {}
2693};
2694
2695/**
2696 * Implementation of a sparse histogram stat. The storage class is
2697 * determined by the Storage template.
2698 */
2699template <class Derived, class Stor>
2700class SparseHistBase : public DataWrap<Derived, SparseHistInfoProxy>
2701{
2702  public:
2703    typedef SparseHistInfoProxy<Derived> Info;
2704    typedef Stor Storage;
2705    typedef typename Stor::Params Params;
2706
2707  protected:
2708    /** The storage for this stat. */
2709    char storage[sizeof(Storage)];
2710
2711  protected:
2712    /**
2713     * Retrieve the storage.
2714     * @return The storage object for this stat.
2715     */
2716    Storage *
2717    data()
2718    {
2719        return reinterpret_cast<Storage *>(storage);
2720    }
2721
2722    /**
2723     * Retrieve a const pointer to the storage.
2724     * @return A const pointer to the storage object for this stat.
2725     */
2726    const Storage *
2727    data() const
2728    {
2729        return reinterpret_cast<const Storage *>(storage);
2730    }
2731
2732    void
2733    doInit()
2734    {
2735        new (storage) Storage(this->info());
2736        this->setInit();
2737    }
2738
2739  public:
2740    SparseHistBase() { }
2741
2742    /**
2743     * Add a value to the distribtion n times. Calls sample on the storage
2744     * class.
2745     * @param v The value to add.
2746     * @param n The number of times to add it, defaults to 1.
2747     */
2748    template <typename U>
2749    void sample(const U &v, int n = 1) { data()->sample(v, n); }
2750
2751    /**
2752     * Return the number of entries in this stat.
2753     * @return The number of entries.
2754     */
2755    size_type size() const { return data()->size(); }
2756    /**
2757     * Return true if no samples have been added.
2758     * @return True if there haven't been any samples.
2759     */
2760    bool zero() const { return data()->zero(); }
2761
2762    void
2763    prepare()
2764    {
2765        Info *info = this->info();
2766        data()->prepare(info, info->data);
2767    }
2768
2769    /**
2770     * Reset stat value to default
2771     */
2772    void
2773    reset()
2774    {
2775        data()->reset(this->info());
2776    }
2777};
2778
2779/**
2780 * Templatized storage and interface for a sparse histogram stat.
2781 */
2782class SparseHistStor
2783{
2784  public:
2785    /** The parameters for a sparse histogram stat. */
2786    struct Params : public DistParams
2787    {
2788        Params() : DistParams(Hist) {}
2789    };
2790
2791  private:
2792    /** Counter for number of samples */
2793    Counter samples;
2794    /** Counter for each bucket. */
2795    MCounter cmap;
2796
2797  public:
2798    SparseHistStor(Info *info)
2799    {
2800        reset(info);
2801    }
2802
2803    /**
2804     * Add a value to the distribution for the given number of times.
2805     * @param val The value to add.
2806     * @param number The number of times to add the value.
2807     */
2808    void
2809    sample(Counter val, int number)
2810    {
2811        cmap[val] += number;
2812        samples += number;
2813    }
2814
2815    /**
2816     * Return the number of buckets in this distribution.
2817     * @return the number of buckets.
2818     */
2819    size_type size() const { return cmap.size(); }
2820
2821    /**
2822     * Returns true if any calls to sample have been made.
2823     * @return True if any values have been sampled.
2824     */
2825    bool
2826    zero() const
2827    {
2828        return samples == Counter();
2829    }
2830
2831    void
2832    prepare(Info *info, SparseHistData &data)
2833    {
2834        MCounter::iterator it;
2835        data.cmap.clear();
2836        for (it = cmap.begin(); it != cmap.end(); it++) {
2837            data.cmap[(*it).first] = (*it).second;
2838        }
2839
2840        data.samples = samples;
2841    }
2842
2843    /**
2844     * Reset stat value to default
2845     */
2846    void
2847    reset(Info *info)
2848    {
2849        cmap.clear();
2850        samples = 0;
2851    }
2852};
2853
2854class SparseHistogram : public SparseHistBase<SparseHistogram, SparseHistStor>
2855{
2856  public:
2857    /**
2858     * Set the parameters of this histogram. @sa HistStor::Params
2859     * @param size The number of buckets in the histogram
2860     * @return A reference to this histogram.
2861     */
2862    SparseHistogram &
2863    init(size_type size)
2864    {
2865        SparseHistStor::Params *params = new SparseHistStor::Params;
2866        this->setParams(params);
2867        this->doInit();
2868        return this->self();
2869    }
2870};
2871
2872class Temp;
2873/**
2874 * A formula for statistics that is calculated when printed. A formula is
2875 * stored as a tree of Nodes that represent the equation to calculate.
2876 * @sa Stat, ScalarStat, VectorStat, Node, Temp
2877 */
2878class Formula : public DataWrapVec<Formula, FormulaInfoProxy>
2879{
2880  protected:
2881    /** The root of the tree which represents the Formula */
2882    NodePtr root;
2883    friend class Temp;
2884
2885  public:
2886    /**
2887     * Create and initialize thie formula, and register it with the database.
2888     */
2889    Formula();
2890
2891    /**
2892     * Create a formula with the given root node, register it with the
2893     * database.
2894     * @param r The root of the expression tree.
2895     */
2896    Formula(Temp r);
2897
2898    /**
2899     * Set an unitialized Formula to the given root.
2900     * @param r The root of the expression tree.
2901     * @return a reference to this formula.
2902     */
2903    const Formula &operator=(Temp r);
2904
2905    /**
2906     * Add the given tree to the existing one.
2907     * @param r The root of the expression tree.
2908     * @return a reference to this formula.
2909     */
2910    const Formula &operator+=(Temp r);
2911
2912    /**
2913     * Divide the existing tree by the given one.
2914     * @param r The root of the expression tree.
2915     * @return a reference to this formula.
2916     */
2917    const Formula &operator/=(Temp r);
2918
2919    /**
2920     * Return the result of the Fomula in a vector.  If there were no Vector
2921     * components to the Formula, then the vector is size 1.  If there were,
2922     * like x/y with x being a vector of size 3, then the result returned will
2923     * be x[0]/y, x[1]/y, x[2]/y, respectively.
2924     * @return The result vector.
2925     */
2926    void result(VResult &vec) const;
2927
2928    /**
2929     * Return the total Formula result.  If there is a Vector
2930     * component to this Formula, then this is the result of the
2931     * Formula if the formula is applied after summing all the
2932     * components of the Vector.  For example, if Formula is x/y where
2933     * x is size 3, then total() will return (x[1]+x[2]+x[3])/y.  If
2934     * there is no Vector component, total() returns the same value as
2935     * the first entry in the VResult val() returns.
2936     * @return The total of the result vector.
2937     */
2938    Result total() const;
2939
2940    /**
2941     * Return the number of elements in the tree.
2942     */
2943    size_type size() const;
2944
2945    void prepare() { }
2946
2947    /**
2948     * Formulas don't need to be reset
2949     */
2950    void reset();
2951
2952    /**
2953     *
2954     */
2955    bool zero() const;
2956
2957    std::string str() const;
2958};
2959
2960class FormulaNode : public Node
2961{
2962  private:
2963    const Formula &formula;
2964    mutable VResult vec;
2965
2966  public:
2967    FormulaNode(const Formula &f) : formula(f) {}
2968
2969    size_type size() const { return formula.size(); }
2970    const VResult &result() const { formula.result(vec); return vec; }
2971    Result total() const { return formula.total(); }
2972
2973    std::string str() const { return formula.str(); }
2974};
2975
2976/**
2977 * Helper class to construct formula node trees.
2978 */
2979class Temp
2980{
2981  protected:
2982    /**
2983     * Pointer to a Node object.
2984     */
2985    NodePtr node;
2986
2987  public:
2988    /**
2989     * Copy the given pointer to this class.
2990     * @param n A pointer to a Node object to copy.
2991     */
2992    Temp(NodePtr n) : node(n) { }
2993
2994    /**
2995     * Return the node pointer.
2996     * @return the node pointer.
2997     */
2998    operator NodePtr&() { return node; }
2999
3000  public:
3001    /**
3002     * Create a new ScalarStatNode.
3003     * @param s The ScalarStat to place in a node.
3004     */
3005    Temp(const Scalar &s)
3006        : node(new ScalarStatNode(s.info()))
3007    { }
3008
3009    /**
3010     * Create a new ScalarStatNode.
3011     * @param s The ScalarStat to place in a node.
3012     */
3013    Temp(const Value &s)
3014        : node(new ScalarStatNode(s.info()))
3015    { }
3016
3017    /**
3018     * Create a new ScalarStatNode.
3019     * @param s The ScalarStat to place in a node.
3020     */
3021    Temp(const Average &s)
3022        : node(new ScalarStatNode(s.info()))
3023    { }
3024
3025    /**
3026     * Create a new VectorStatNode.
3027     * @param s The VectorStat to place in a node.
3028     */
3029    Temp(const Vector &s)
3030        : node(new VectorStatNode(s.info()))
3031    { }
3032
3033    Temp(const AverageVector &s)
3034        : node(new VectorStatNode(s.info()))
3035    { }
3036
3037    /**
3038     *
3039     */
3040    Temp(const Formula &f)
3041        : node(new FormulaNode(f))
3042    { }
3043
3044    /**
3045     * Create a new ScalarProxyNode.
3046     * @param p The ScalarProxy to place in a node.
3047     */
3048    template <class Stat>
3049    Temp(const ScalarProxy<Stat> &p)
3050        : node(new ScalarProxyNode<Stat>(p))
3051    { }
3052
3053    /**
3054     * Create a ConstNode
3055     * @param value The value of the const node.
3056     */
3057    Temp(signed char value)
3058        : node(new ConstNode<signed char>(value))
3059    { }
3060
3061    /**
3062     * Create a ConstNode
3063     * @param value The value of the const node.
3064     */
3065    Temp(unsigned char value)
3066        : node(new ConstNode<unsigned char>(value))
3067    { }
3068
3069    /**
3070     * Create a ConstNode
3071     * @param value The value of the const node.
3072     */
3073    Temp(signed short value)
3074        : node(new ConstNode<signed short>(value))
3075    { }
3076
3077    /**
3078     * Create a ConstNode
3079     * @param value The value of the const node.
3080     */
3081    Temp(unsigned short value)
3082        : node(new ConstNode<unsigned short>(value))
3083    { }
3084
3085    /**
3086     * Create a ConstNode
3087     * @param value The value of the const node.
3088     */
3089    Temp(signed int value)
3090        : node(new ConstNode<signed int>(value))
3091    { }
3092
3093    /**
3094     * Create a ConstNode
3095     * @param value The value of the const node.
3096     */
3097    Temp(unsigned int value)
3098        : node(new ConstNode<unsigned int>(value))
3099    { }
3100
3101    /**
3102     * Create a ConstNode
3103     * @param value The value of the const node.
3104     */
3105    Temp(signed long value)
3106        : node(new ConstNode<signed long>(value))
3107    { }
3108
3109    /**
3110     * Create a ConstNode
3111     * @param value The value of the const node.
3112     */
3113    Temp(unsigned long value)
3114        : node(new ConstNode<unsigned long>(value))
3115    { }
3116
3117    /**
3118     * Create a ConstNode
3119     * @param value The value of the const node.
3120     */
3121    Temp(signed long long value)
3122        : node(new ConstNode<signed long long>(value))
3123    { }
3124
3125    /**
3126     * Create a ConstNode
3127     * @param value The value of the const node.
3128     */
3129    Temp(unsigned long long value)
3130        : node(new ConstNode<unsigned long long>(value))
3131    { }
3132
3133    /**
3134     * Create a ConstNode
3135     * @param value The value of the const node.
3136     */
3137    Temp(float value)
3138        : node(new ConstNode<float>(value))
3139    { }
3140
3141    /**
3142     * Create a ConstNode
3143     * @param value The value of the const node.
3144     */
3145    Temp(double value)
3146        : node(new ConstNode<double>(value))
3147    { }
3148};
3149
3150
3151/**
3152 * @}
3153 */
3154
3155inline Temp
3156operator+(Temp l, Temp r)
3157{
3158    return NodePtr(new BinaryNode<std::plus<Result> >(l, r));
3159}
3160
3161inline Temp
3162operator-(Temp l, Temp r)
3163{
3164    return NodePtr(new BinaryNode<std::minus<Result> >(l, r));
3165}
3166
3167inline Temp
3168operator*(Temp l, Temp r)
3169{
3170    return NodePtr(new BinaryNode<std::multiplies<Result> >(l, r));
3171}
3172
3173inline Temp
3174operator/(Temp l, Temp r)
3175{
3176    return NodePtr(new BinaryNode<std::divides<Result> >(l, r));
3177}
3178
3179inline Temp
3180operator-(Temp l)
3181{
3182    return NodePtr(new UnaryNode<std::negate<Result> >(l));
3183}
3184
3185template <typename T>
3186inline Temp
3187constant(T val)
3188{
3189    return NodePtr(new ConstNode<T>(val));
3190}
3191
3192template <typename T>
3193inline Temp
3194constantVector(T val)
3195{
3196    return NodePtr(new ConstVectorNode<T>(val));
3197}
3198
3199inline Temp
3200sum(Temp val)
3201{
3202    return NodePtr(new SumNode<std::plus<Result> >(val));
3203}
3204
3205/** Dump all statistics data to the registered outputs */
3206void dump();
3207void reset();
3208void enable();
3209bool enabled();
3210
3211/**
3212 * Register a callback that should be called whenever statistics are
3213 * reset
3214 */
3215void registerResetCallback(Callback *cb);
3216
3217/**
3218 * Register a callback that should be called whenever statistics are
3219 * about to be dumped
3220 */
3221void registerDumpCallback(Callback *cb);
3222
3223std::list<Info *> &statsList();
3224
3225typedef std::map<const void *, Info *> MapType;
3226MapType &statsMap();
3227
3228typedef std::map<std::string, Info *> NameMapType;
3229NameMapType &nameMap();
3230
3231bool validateStatName(const std::string &name);
3232
3233} // namespace Stats
3234
3235void debugDumpStats();
3236
3237#endif // __BASE_STATISTICS_HH__
3238