statistics.hh revision 10373:342348537a53
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
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) {}
1365    };
1366
1367  private:
1368    /** The minimum value to track. */
1369    Counter min_track;
1370    /** The maximum value to track. */
1371    Counter max_track;
1372    /** The number of entries in each bucket. */
1373    Counter bucket_size;
1374
1375    /** The smallest value sampled. */
1376    Counter min_val;
1377    /** The largest value sampled. */
1378    Counter max_val;
1379    /** The number of values sampled less than min. */
1380    Counter underflow;
1381    /** The number of values sampled more than max. */
1382    Counter overflow;
1383    /** The current sum. */
1384    Counter sum;
1385    /** The sum of squares. */
1386    Counter squares;
1387    /** The number of samples. */
1388    Counter samples;
1389    /** Counter for each bucket. */
1390    VCounter cvec;
1391
1392  public:
1393    DistStor(Info *info)
1394        : cvec(safe_cast<const Params *>(info->storageParams)->buckets)
1395    {
1396        reset(info);
1397    }
1398
1399    /**
1400     * Add a value to the distribution for the given number of times.
1401     * @param val The value to add.
1402     * @param number The number of times to add the value.
1403     */
1404    void
1405    sample(Counter val, int number)
1406    {
1407        if (val < min_track)
1408            underflow += number;
1409        else if (val > max_track)
1410            overflow += number;
1411        else {
1412            size_type index =
1413                (size_type)std::floor((val - min_track) / bucket_size);
1414            assert(index < size());
1415            cvec[index] += number;
1416        }
1417
1418        if (val < min_val)
1419            min_val = val;
1420
1421        if (val > max_val)
1422            max_val = val;
1423
1424        sum += val * number;
1425        squares += val * val * number;
1426        samples += number;
1427    }
1428
1429    /**
1430     * Return the number of buckets in this distribution.
1431     * @return the number of buckets.
1432     */
1433    size_type size() const { return cvec.size(); }
1434
1435    /**
1436     * Returns true if any calls to sample have been made.
1437     * @return True if any values have been sampled.
1438     */
1439    bool
1440    zero() const
1441    {
1442        return samples == Counter();
1443    }
1444
1445    void
1446    prepare(Info *info, DistData &data)
1447    {
1448        const Params *params = safe_cast<const Params *>(info->storageParams);
1449
1450        assert(params->type == Dist);
1451        data.type = params->type;
1452        data.min = params->min;
1453        data.max = params->max;
1454        data.bucket_size = params->bucket_size;
1455
1456        data.min_val = (min_val == CounterLimits::max()) ? 0 : min_val;
1457        data.max_val = (max_val == CounterLimits::min()) ? 0 : max_val;
1458        data.underflow = underflow;
1459        data.overflow = overflow;
1460
1461        data.cvec.resize(params->buckets);
1462        for (off_type i = 0; i < params->buckets; ++i)
1463            data.cvec[i] = cvec[i];
1464
1465        data.sum = sum;
1466        data.squares = squares;
1467        data.samples = samples;
1468    }
1469
1470    /**
1471     * Reset stat value to default
1472     */
1473    void
1474    reset(Info *info)
1475    {
1476        const Params *params = safe_cast<const Params *>(info->storageParams);
1477        min_track = params->min;
1478        max_track = params->max;
1479        bucket_size = params->bucket_size;
1480
1481        min_val = CounterLimits::max();
1482        max_val = CounterLimits::min();
1483        underflow = Counter();
1484        overflow = Counter();
1485
1486        size_type size = cvec.size();
1487        for (off_type i = 0; i < size; ++i)
1488            cvec[i] = Counter();
1489
1490        sum = Counter();
1491        squares = Counter();
1492        samples = Counter();
1493    }
1494};
1495
1496/**
1497 * Templatized storage and interface for a histogram stat.
1498 */
1499class HistStor
1500{
1501  public:
1502    /** The parameters for a distribution stat. */
1503    struct Params : public DistParams
1504    {
1505        /** The number of buckets.. */
1506        size_type buckets;
1507
1508        Params() : DistParams(Hist), buckets(0) {}
1509    };
1510
1511  private:
1512    /** The minimum value to track. */
1513    Counter min_bucket;
1514    /** The maximum value to track. */
1515    Counter max_bucket;
1516    /** The number of entries in each bucket. */
1517    Counter bucket_size;
1518
1519    /** The current sum. */
1520    Counter sum;
1521    /** The sum of logarithm of each sample, used to compute geometric mean. */
1522    Counter logs;
1523    /** The sum of squares. */
1524    Counter squares;
1525    /** The number of samples. */
1526    Counter samples;
1527    /** Counter for each bucket. */
1528    VCounter cvec;
1529
1530  public:
1531    HistStor(Info *info)
1532        : cvec(safe_cast<const Params *>(info->storageParams)->buckets)
1533    {
1534        reset(info);
1535    }
1536
1537    void grow_up();
1538    void grow_out();
1539    void grow_convert();
1540    void add(HistStor *);
1541
1542    /**
1543     * Add a value to the distribution for the given number of times.
1544     * @param val The value to add.
1545     * @param number The number of times to add the value.
1546     */
1547    void
1548    sample(Counter val, int number)
1549    {
1550        assert(min_bucket < max_bucket);
1551        if (val < min_bucket) {
1552            if (min_bucket == 0)
1553                grow_convert();
1554
1555            while (val < min_bucket)
1556                grow_out();
1557        } else if (val >= max_bucket + bucket_size) {
1558            if (min_bucket == 0) {
1559                while (val >= max_bucket + bucket_size)
1560                    grow_up();
1561            } else {
1562                while (val >= max_bucket + bucket_size)
1563                    grow_out();
1564            }
1565        }
1566
1567        size_type index =
1568            (int64_t)std::floor((val - min_bucket) / bucket_size);
1569
1570        assert(index < size());
1571        cvec[index] += number;
1572
1573        sum += val * number;
1574        squares += val * val * number;
1575        logs += log(val) * number;
1576        samples += number;
1577    }
1578
1579    /**
1580     * Return the number of buckets in this distribution.
1581     * @return the number of buckets.
1582     */
1583    size_type size() const { return cvec.size(); }
1584
1585    /**
1586     * Returns true if any calls to sample have been made.
1587     * @return True if any values have been sampled.
1588     */
1589    bool
1590    zero() const
1591    {
1592        return samples == Counter();
1593    }
1594
1595    void
1596    prepare(Info *info, DistData &data)
1597    {
1598        const Params *params = safe_cast<const Params *>(info->storageParams);
1599
1600        assert(params->type == Hist);
1601        data.type = params->type;
1602        data.min = min_bucket;
1603        data.max = max_bucket + bucket_size - 1;
1604        data.bucket_size = bucket_size;
1605
1606        data.min_val = min_bucket;
1607        data.max_val = max_bucket;
1608
1609        int buckets = params->buckets;
1610        data.cvec.resize(buckets);
1611        for (off_type i = 0; i < buckets; ++i)
1612            data.cvec[i] = cvec[i];
1613
1614        data.sum = sum;
1615        data.logs = logs;
1616        data.squares = squares;
1617        data.samples = samples;
1618    }
1619
1620    /**
1621     * Reset stat value to default
1622     */
1623    void
1624    reset(Info *info)
1625    {
1626        const Params *params = safe_cast<const Params *>(info->storageParams);
1627        min_bucket = 0;
1628        max_bucket = params->buckets - 1;
1629        bucket_size = 1;
1630
1631        size_type size = cvec.size();
1632        for (off_type i = 0; i < size; ++i)
1633            cvec[i] = Counter();
1634
1635        sum = Counter();
1636        squares = Counter();
1637        samples = Counter();
1638        logs = Counter();
1639    }
1640};
1641
1642/**
1643 * Templatized storage and interface for a distribution that calculates mean
1644 * and variance.
1645 */
1646class SampleStor
1647{
1648  public:
1649    struct Params : public DistParams
1650    {
1651        Params() : DistParams(Deviation) {}
1652    };
1653
1654  private:
1655    /** The current sum. */
1656    Counter sum;
1657    /** The sum of squares. */
1658    Counter squares;
1659    /** The number of samples. */
1660    Counter samples;
1661
1662  public:
1663    /**
1664     * Create and initialize this storage.
1665     */
1666    SampleStor(Info *info)
1667        : sum(Counter()), squares(Counter()), samples(Counter())
1668    { }
1669
1670    /**
1671     * Add a value the given number of times to this running average.
1672     * Update the running sum and sum of squares, increment the number of
1673     * values seen by the given number.
1674     * @param val The value to add.
1675     * @param number The number of times to add the value.
1676     */
1677    void
1678    sample(Counter val, int number)
1679    {
1680        Counter value = val * number;
1681        sum += value;
1682        squares += value * value;
1683        samples += number;
1684    }
1685
1686    /**
1687     * Return the number of entries in this stat, 1
1688     * @return 1.
1689     */
1690    size_type size() const { return 1; }
1691
1692    /**
1693     * Return true if no samples have been added.
1694     * @return True if no samples have been added.
1695     */
1696    bool zero() const { return samples == Counter(); }
1697
1698    void
1699    prepare(Info *info, DistData &data)
1700    {
1701        const Params *params = safe_cast<const Params *>(info->storageParams);
1702
1703        assert(params->type == Deviation);
1704        data.type = params->type;
1705        data.sum = sum;
1706        data.squares = squares;
1707        data.samples = samples;
1708    }
1709
1710    /**
1711     * Reset stat value to default
1712     */
1713    void
1714    reset(Info *info)
1715    {
1716        sum = Counter();
1717        squares = Counter();
1718        samples = Counter();
1719    }
1720};
1721
1722/**
1723 * Templatized storage for distribution that calculates per tick mean and
1724 * variance.
1725 */
1726class AvgSampleStor
1727{
1728  public:
1729    struct Params : public DistParams
1730    {
1731        Params() : DistParams(Deviation) {}
1732    };
1733
1734  private:
1735    /** Current total. */
1736    Counter sum;
1737    /** Current sum of squares. */
1738    Counter squares;
1739
1740  public:
1741    /**
1742     * Create and initialize this storage.
1743     */
1744    AvgSampleStor(Info *info)
1745        : sum(Counter()), squares(Counter())
1746    {}
1747
1748    /**
1749     * Add a value to the distribution for the given number of times.
1750     * Update the running sum and sum of squares.
1751     * @param val The value to add.
1752     * @param number The number of times to add the value.
1753     */
1754    void
1755    sample(Counter val, int number)
1756    {
1757        Counter value = val * number;
1758        sum += value;
1759        squares += value * value;
1760    }
1761
1762    /**
1763     * Return the number of entries, in this case 1.
1764     * @return 1.
1765     */
1766    size_type size() const { return 1; }
1767
1768    /**
1769     * Return true if no samples have been added.
1770     * @return True if the sum is zero.
1771     */
1772    bool zero() const { return sum == Counter(); }
1773
1774    void
1775    prepare(Info *info, DistData &data)
1776    {
1777        const Params *params = safe_cast<const Params *>(info->storageParams);
1778
1779        assert(params->type == Deviation);
1780        data.type = params->type;
1781        data.sum = sum;
1782        data.squares = squares;
1783        data.samples = curTick();
1784    }
1785
1786    /**
1787     * Reset stat value to default
1788     */
1789    void
1790    reset(Info *info)
1791    {
1792        sum = Counter();
1793        squares = Counter();
1794    }
1795};
1796
1797/**
1798 * Implementation of a distribution stat. The type of distribution is
1799 * determined by the Storage template. @sa ScalarBase
1800 */
1801template <class Derived, class Stor>
1802class DistBase : public DataWrap<Derived, DistInfoProxy>
1803{
1804  public:
1805    typedef DistInfoProxy<Derived> Info;
1806    typedef Stor Storage;
1807    typedef typename Stor::Params Params;
1808
1809  protected:
1810    /** The storage for this stat. */
1811    char storage[sizeof(Storage)] __attribute__ ((aligned (8)));
1812
1813  protected:
1814    /**
1815     * Retrieve the storage.
1816     * @return The storage object for this stat.
1817     */
1818    Storage *
1819    data()
1820    {
1821        return reinterpret_cast<Storage *>(storage);
1822    }
1823
1824    /**
1825     * Retrieve a const pointer to the storage.
1826     * @return A const pointer to the storage object for this stat.
1827     */
1828    const Storage *
1829    data() const
1830    {
1831        return reinterpret_cast<const Storage *>(storage);
1832    }
1833
1834    void
1835    doInit()
1836    {
1837        new (storage) Storage(this->info());
1838        this->setInit();
1839    }
1840
1841  public:
1842    DistBase() { }
1843
1844    /**
1845     * Add a value to the distribtion n times. Calls sample on the storage
1846     * class.
1847     * @param v The value to add.
1848     * @param n The number of times to add it, defaults to 1.
1849     */
1850    template <typename U>
1851    void sample(const U &v, int n = 1) { data()->sample(v, n); }
1852
1853    /**
1854     * Return the number of entries in this stat.
1855     * @return The number of entries.
1856     */
1857    size_type size() const { return data()->size(); }
1858    /**
1859     * Return true if no samples have been added.
1860     * @return True if there haven't been any samples.
1861     */
1862    bool zero() const { return data()->zero(); }
1863
1864    void
1865    prepare()
1866    {
1867        Info *info = this->info();
1868        data()->prepare(info, info->data);
1869    }
1870
1871    /**
1872     * Reset stat value to default
1873     */
1874    void
1875    reset()
1876    {
1877        data()->reset(this->info());
1878    }
1879
1880    /**
1881     *  Add the argument distribution to the this distibution.
1882     */
1883    void add(DistBase &d) { data()->add(d.data()); }
1884
1885};
1886
1887template <class Stat>
1888class DistProxy;
1889
1890template <class Derived, class Stor>
1891class VectorDistBase : public DataWrapVec<Derived, VectorDistInfoProxy>
1892{
1893  public:
1894    typedef VectorDistInfoProxy<Derived> Info;
1895    typedef Stor Storage;
1896    typedef typename Stor::Params Params;
1897    typedef DistProxy<Derived> Proxy;
1898    friend class DistProxy<Derived>;
1899    friend class DataWrapVec<Derived, VectorDistInfoProxy>;
1900
1901  protected:
1902    Storage *storage;
1903    size_type _size;
1904
1905  protected:
1906    Storage *
1907    data(off_type index)
1908    {
1909        return &storage[index];
1910    }
1911
1912    const Storage *
1913    data(off_type index) const
1914    {
1915        return &storage[index];
1916    }
1917
1918    void
1919    doInit(size_type s)
1920    {
1921        assert(s > 0 && "size must be positive!");
1922        assert(!storage && "already initialized");
1923        _size = s;
1924
1925        char *ptr = new char[_size * sizeof(Storage)];
1926        storage = reinterpret_cast<Storage *>(ptr);
1927
1928        Info *info = this->info();
1929        for (off_type i = 0; i < _size; ++i)
1930            new (&storage[i]) Storage(info);
1931
1932        this->setInit();
1933    }
1934
1935  public:
1936    VectorDistBase()
1937        : storage(NULL)
1938    {}
1939
1940    ~VectorDistBase()
1941    {
1942        if (!storage)
1943            return ;
1944
1945        for (off_type i = 0; i < _size; ++i)
1946            data(i)->~Storage();
1947        delete [] reinterpret_cast<char *>(storage);
1948    }
1949
1950    Proxy operator[](off_type index)
1951    {
1952        assert(index >= 0 && index < size());
1953        return Proxy(this->self(), index);
1954    }
1955
1956    size_type
1957    size() const
1958    {
1959        return _size;
1960    }
1961
1962    bool
1963    zero() const
1964    {
1965        for (off_type i = 0; i < size(); ++i)
1966            if (!data(i)->zero())
1967                return false;
1968        return true;
1969    }
1970
1971    void
1972    prepare()
1973    {
1974        Info *info = this->info();
1975        size_type size = this->size();
1976        info->data.resize(size);
1977        for (off_type i = 0; i < size; ++i)
1978            data(i)->prepare(info, info->data[i]);
1979    }
1980
1981    bool
1982    check() const
1983    {
1984        return storage != NULL;
1985    }
1986};
1987
1988template <class Stat>
1989class DistProxy
1990{
1991  private:
1992    Stat &stat;
1993    off_type index;
1994
1995  protected:
1996    typename Stat::Storage *data() { return stat.data(index); }
1997    const typename Stat::Storage *data() const { return stat.data(index); }
1998
1999  public:
2000    DistProxy(Stat &s, off_type i)
2001        : stat(s), index(i)
2002    {}
2003
2004    DistProxy(const DistProxy &sp)
2005        : stat(sp.stat), index(sp.index)
2006    {}
2007
2008    const DistProxy &
2009    operator=(const DistProxy &sp)
2010    {
2011        stat = sp.stat;
2012        index = sp.index;
2013        return *this;
2014    }
2015
2016  public:
2017    template <typename U>
2018    void
2019    sample(const U &v, int n = 1)
2020    {
2021        data()->sample(v, n);
2022    }
2023
2024    size_type
2025    size() const
2026    {
2027        return 1;
2028    }
2029
2030    bool
2031    zero() const
2032    {
2033        return data()->zero();
2034    }
2035
2036    /**
2037     * Proxy has no state.  Nothing to reset.
2038     */
2039    void reset() { }
2040};
2041
2042//////////////////////////////////////////////////////////////////////
2043//
2044//  Formula Details
2045//
2046//////////////////////////////////////////////////////////////////////
2047
2048/**
2049 * Base class for formula statistic node. These nodes are used to build a tree
2050 * that represents the formula.
2051 */
2052class Node : public RefCounted
2053{
2054  public:
2055    /**
2056     * Return the number of nodes in the subtree starting at this node.
2057     * @return the number of nodes in this subtree.
2058     */
2059    virtual size_type size() const = 0;
2060    /**
2061     * Return the result vector of this subtree.
2062     * @return The result vector of this subtree.
2063     */
2064    virtual const VResult &result() const = 0;
2065    /**
2066     * Return the total of the result vector.
2067     * @return The total of the result vector.
2068     */
2069    virtual Result total() const = 0;
2070
2071    /**
2072     *
2073     */
2074    virtual std::string str() const = 0;
2075};
2076
2077/** Reference counting pointer to a function Node. */
2078typedef RefCountingPtr<Node> NodePtr;
2079
2080class ScalarStatNode : public Node
2081{
2082  private:
2083    const ScalarInfo *data;
2084    mutable VResult vresult;
2085
2086  public:
2087    ScalarStatNode(const ScalarInfo *d) : data(d), vresult(1) {}
2088
2089    const VResult &
2090    result() const
2091    {
2092        vresult[0] = data->result();
2093        return vresult;
2094    }
2095
2096    Result total() const { return data->result(); };
2097
2098    size_type size() const { return 1; }
2099
2100    /**
2101     *
2102     */
2103    std::string str() const { return data->name; }
2104};
2105
2106template <class Stat>
2107class ScalarProxyNode : public Node
2108{
2109  private:
2110    const ScalarProxy<Stat> proxy;
2111    mutable VResult vresult;
2112
2113  public:
2114    ScalarProxyNode(const ScalarProxy<Stat> &p)
2115        : proxy(p), vresult(1)
2116    { }
2117
2118    const VResult &
2119    result() const
2120    {
2121        vresult[0] = proxy.result();
2122        return vresult;
2123    }
2124
2125    Result
2126    total() const
2127    {
2128        return proxy.result();
2129    }
2130
2131    size_type
2132    size() const
2133    {
2134        return 1;
2135    }
2136
2137    /**
2138     *
2139     */
2140    std::string
2141    str() const
2142    {
2143        return proxy.str();
2144    }
2145};
2146
2147class VectorStatNode : public Node
2148{
2149  private:
2150    const VectorInfo *data;
2151
2152  public:
2153    VectorStatNode(const VectorInfo *d) : data(d) { }
2154    const VResult &result() const { return data->result(); }
2155    Result total() const { return data->total(); };
2156
2157    size_type size() const { return data->size(); }
2158
2159    std::string str() const { return data->name; }
2160};
2161
2162template <class T>
2163class ConstNode : public Node
2164{
2165  private:
2166    VResult vresult;
2167
2168  public:
2169    ConstNode(T s) : vresult(1, (Result)s) {}
2170    const VResult &result() const { return vresult; }
2171    Result total() const { return vresult[0]; };
2172    size_type size() const { return 1; }
2173    std::string str() const { return to_string(vresult[0]); }
2174};
2175
2176template <class T>
2177class ConstVectorNode : public Node
2178{
2179  private:
2180    VResult vresult;
2181
2182  public:
2183    ConstVectorNode(const T &s) : vresult(s.begin(), s.end()) {}
2184    const VResult &result() const { return vresult; }
2185
2186    Result
2187    total() const
2188    {
2189        size_type size = this->size();
2190        Result tmp = 0;
2191        for (off_type i = 0; i < size; i++)
2192            tmp += vresult[i];
2193        return tmp;
2194    }
2195
2196    size_type size() const { return vresult.size(); }
2197    std::string
2198    str() const
2199    {
2200        size_type size = this->size();
2201        std::string tmp = "(";
2202        for (off_type i = 0; i < size; i++)
2203            tmp += csprintf("%s ",to_string(vresult[i]));
2204        tmp += ")";
2205        return tmp;
2206    }
2207};
2208
2209template <class Op>
2210struct OpString;
2211
2212template<>
2213struct OpString<std::plus<Result> >
2214{
2215    static std::string str() { return "+"; }
2216};
2217
2218template<>
2219struct OpString<std::minus<Result> >
2220{
2221    static std::string str() { return "-"; }
2222};
2223
2224template<>
2225struct OpString<std::multiplies<Result> >
2226{
2227    static std::string str() { return "*"; }
2228};
2229
2230template<>
2231struct OpString<std::divides<Result> >
2232{
2233    static std::string str() { return "/"; }
2234};
2235
2236template<>
2237struct OpString<std::modulus<Result> >
2238{
2239    static std::string str() { return "%"; }
2240};
2241
2242template<>
2243struct OpString<std::negate<Result> >
2244{
2245    static std::string str() { return "-"; }
2246};
2247
2248template <class Op>
2249class UnaryNode : public Node
2250{
2251  public:
2252    NodePtr l;
2253    mutable VResult vresult;
2254
2255  public:
2256    UnaryNode(NodePtr &p) : l(p) {}
2257
2258    const VResult &
2259    result() const
2260    {
2261        const VResult &lvec = l->result();
2262        size_type size = lvec.size();
2263
2264        assert(size > 0);
2265
2266        vresult.resize(size);
2267        Op op;
2268        for (off_type i = 0; i < size; ++i)
2269            vresult[i] = op(lvec[i]);
2270
2271        return vresult;
2272    }
2273
2274    Result
2275    total() const
2276    {
2277        const VResult &vec = this->result();
2278        Result total = 0.0;
2279        for (off_type i = 0; i < size(); i++)
2280            total += vec[i];
2281        return total;
2282    }
2283
2284    size_type size() const { return l->size(); }
2285
2286    std::string
2287    str() const
2288    {
2289        return OpString<Op>::str() + l->str();
2290    }
2291};
2292
2293template <class Op>
2294class BinaryNode : public Node
2295{
2296  public:
2297    NodePtr l;
2298    NodePtr r;
2299    mutable VResult vresult;
2300
2301  public:
2302    BinaryNode(NodePtr &a, NodePtr &b) : l(a), r(b) {}
2303
2304    const VResult &
2305    result() const
2306    {
2307        Op op;
2308        const VResult &lvec = l->result();
2309        const VResult &rvec = r->result();
2310
2311        assert(lvec.size() > 0 && rvec.size() > 0);
2312
2313        if (lvec.size() == 1 && rvec.size() == 1) {
2314            vresult.resize(1);
2315            vresult[0] = op(lvec[0], rvec[0]);
2316        } else if (lvec.size() == 1) {
2317            size_type size = rvec.size();
2318            vresult.resize(size);
2319            for (off_type i = 0; i < size; ++i)
2320                vresult[i] = op(lvec[0], rvec[i]);
2321        } else if (rvec.size() == 1) {
2322            size_type size = lvec.size();
2323            vresult.resize(size);
2324            for (off_type i = 0; i < size; ++i)
2325                vresult[i] = op(lvec[i], rvec[0]);
2326        } else if (rvec.size() == lvec.size()) {
2327            size_type size = rvec.size();
2328            vresult.resize(size);
2329            for (off_type i = 0; i < size; ++i)
2330                vresult[i] = op(lvec[i], rvec[i]);
2331        }
2332
2333        return vresult;
2334    }
2335
2336    Result
2337    total() const
2338    {
2339        const VResult &vec = this->result();
2340        const VResult &lvec = l->result();
2341        const VResult &rvec = r->result();
2342        Result total = 0.0;
2343        Result lsum = 0.0;
2344        Result rsum = 0.0;
2345        Op op;
2346
2347        assert(lvec.size() > 0 && rvec.size() > 0);
2348        assert(lvec.size() == rvec.size() ||
2349               lvec.size() == 1 || rvec.size() == 1);
2350
2351        /** If vectors are the same divide their sums (x0+x1)/(y0+y1) */
2352        if (lvec.size() == rvec.size() && lvec.size() > 1) {
2353            for (off_type i = 0; i < size(); ++i) {
2354                lsum += lvec[i];
2355                rsum += rvec[i];
2356            }
2357            return op(lsum, rsum);
2358        }
2359
2360        /** Otherwise divide each item by the divisor */
2361        for (off_type i = 0; i < size(); ++i) {
2362            total += vec[i];
2363        }
2364
2365        return total;
2366    }
2367
2368    size_type
2369    size() const
2370    {
2371        size_type ls = l->size();
2372        size_type rs = r->size();
2373        if (ls == 1) {
2374            return rs;
2375        } else if (rs == 1) {
2376            return ls;
2377        } else {
2378            assert(ls == rs && "Node vector sizes are not equal");
2379            return ls;
2380        }
2381    }
2382
2383    std::string
2384    str() const
2385    {
2386        return csprintf("(%s %s %s)", l->str(), OpString<Op>::str(), r->str());
2387    }
2388};
2389
2390template <class Op>
2391class SumNode : public Node
2392{
2393  public:
2394    NodePtr l;
2395    mutable VResult vresult;
2396
2397  public:
2398    SumNode(NodePtr &p) : l(p), vresult(1) {}
2399
2400    const VResult &
2401    result() const
2402    {
2403        const VResult &lvec = l->result();
2404        size_type size = lvec.size();
2405        assert(size > 0);
2406
2407        vresult[0] = 0.0;
2408
2409        Op op;
2410        for (off_type i = 0; i < size; ++i)
2411            vresult[0] = op(vresult[0], lvec[i]);
2412
2413        return vresult;
2414    }
2415
2416    Result
2417    total() const
2418    {
2419        const VResult &lvec = l->result();
2420        size_type size = lvec.size();
2421        assert(size > 0);
2422
2423        Result result = 0.0;
2424
2425        Op op;
2426        for (off_type i = 0; i < size; ++i)
2427            result = op(result, lvec[i]);
2428
2429        return result;
2430    }
2431
2432    size_type size() const { return 1; }
2433
2434    std::string
2435    str() const
2436    {
2437        return csprintf("total(%s)", l->str());
2438    }
2439};
2440
2441
2442//////////////////////////////////////////////////////////////////////
2443//
2444// Visible Statistics Types
2445//
2446//////////////////////////////////////////////////////////////////////
2447/**
2448 * @defgroup VisibleStats "Statistic Types"
2449 * These are the statistics that are used in the simulator.
2450 * @{
2451 */
2452
2453/**
2454 * This is a simple scalar statistic, like a counter.
2455 * @sa Stat, ScalarBase, StatStor
2456 */
2457class Scalar : public ScalarBase<Scalar, StatStor>
2458{
2459  public:
2460    using ScalarBase<Scalar, StatStor>::operator=;
2461};
2462
2463/**
2464 * A stat that calculates the per tick average of a value.
2465 * @sa Stat, ScalarBase, AvgStor
2466 */
2467class Average : public ScalarBase<Average, AvgStor>
2468{
2469  public:
2470    using ScalarBase<Average, AvgStor>::operator=;
2471};
2472
2473class Value : public ValueBase<Value>
2474{
2475};
2476
2477/**
2478 * A vector of scalar stats.
2479 * @sa Stat, VectorBase, StatStor
2480 */
2481class Vector : public VectorBase<Vector, StatStor>
2482{
2483};
2484
2485/**
2486 * A vector of Average stats.
2487 * @sa Stat, VectorBase, AvgStor
2488 */
2489class AverageVector : public VectorBase<AverageVector, AvgStor>
2490{
2491};
2492
2493/**
2494 * A 2-Dimensional vecto of scalar stats.
2495 * @sa Stat, Vector2dBase, StatStor
2496 */
2497class Vector2d : public Vector2dBase<Vector2d, StatStor>
2498{
2499};
2500
2501/**
2502 * A simple distribution stat.
2503 * @sa Stat, DistBase, DistStor
2504 */
2505class Distribution : public DistBase<Distribution, DistStor>
2506{
2507  public:
2508    /**
2509     * Set the parameters of this distribution. @sa DistStor::Params
2510     * @param min The minimum value of the distribution.
2511     * @param max The maximum value of the distribution.
2512     * @param bkt The number of values in each bucket.
2513     * @return A reference to this distribution.
2514     */
2515    Distribution &
2516    init(Counter min, Counter max, Counter bkt)
2517    {
2518        DistStor::Params *params = new DistStor::Params;
2519        params->min = min;
2520        params->max = max;
2521        params->bucket_size = bkt;
2522        params->buckets = (size_type)ceil((max - min + 1.0) / bkt);
2523        this->setParams(params);
2524        this->doInit();
2525        return this->self();
2526    }
2527};
2528
2529/**
2530 * A simple histogram stat.
2531 * @sa Stat, DistBase, HistStor
2532 */
2533class Histogram : public DistBase<Histogram, HistStor>
2534{
2535  public:
2536    /**
2537     * Set the parameters of this histogram. @sa HistStor::Params
2538     * @param size The number of buckets in the histogram
2539     * @return A reference to this histogram.
2540     */
2541    Histogram &
2542    init(size_type size)
2543    {
2544        HistStor::Params *params = new HistStor::Params;
2545        params->buckets = size;
2546        this->setParams(params);
2547        this->doInit();
2548        return this->self();
2549    }
2550};
2551
2552/**
2553 * Calculates the mean and variance of all the samples.
2554 * @sa DistBase, SampleStor
2555 */
2556class StandardDeviation : public DistBase<StandardDeviation, SampleStor>
2557{
2558  public:
2559    /**
2560     * Construct and initialize this distribution.
2561     */
2562    StandardDeviation()
2563    {
2564        SampleStor::Params *params = new SampleStor::Params;
2565        this->doInit();
2566        this->setParams(params);
2567    }
2568};
2569
2570/**
2571 * Calculates the per tick mean and variance of the samples.
2572 * @sa DistBase, AvgSampleStor
2573 */
2574class AverageDeviation : public DistBase<AverageDeviation, AvgSampleStor>
2575{
2576  public:
2577    /**
2578     * Construct and initialize this distribution.
2579     */
2580    AverageDeviation()
2581    {
2582        AvgSampleStor::Params *params = new AvgSampleStor::Params;
2583        this->doInit();
2584        this->setParams(params);
2585    }
2586};
2587
2588/**
2589 * A vector of distributions.
2590 * @sa VectorDistBase, DistStor
2591 */
2592class VectorDistribution : public VectorDistBase<VectorDistribution, DistStor>
2593{
2594  public:
2595    /**
2596     * Initialize storage and parameters for this distribution.
2597     * @param size The size of the vector (the number of distributions).
2598     * @param min The minimum value of the distribution.
2599     * @param max The maximum value of the distribution.
2600     * @param bkt The number of values in each bucket.
2601     * @return A reference to this distribution.
2602     */
2603    VectorDistribution &
2604    init(size_type size, Counter min, Counter max, Counter bkt)
2605    {
2606        DistStor::Params *params = new DistStor::Params;
2607        params->min = min;
2608        params->max = max;
2609        params->bucket_size = bkt;
2610        params->buckets = (size_type)ceil((max - min + 1.0) / bkt);
2611        this->setParams(params);
2612        this->doInit(size);
2613        return this->self();
2614    }
2615};
2616
2617/**
2618 * This is a vector of StandardDeviation stats.
2619 * @sa VectorDistBase, SampleStor
2620 */
2621class VectorStandardDeviation
2622    : public VectorDistBase<VectorStandardDeviation, SampleStor>
2623{
2624  public:
2625    /**
2626     * Initialize storage for this distribution.
2627     * @param size The size of the vector.
2628     * @return A reference to this distribution.
2629     */
2630    VectorStandardDeviation &
2631    init(size_type size)
2632    {
2633        SampleStor::Params *params = new SampleStor::Params;
2634        this->doInit(size);
2635        this->setParams(params);
2636        return this->self();
2637    }
2638};
2639
2640/**
2641 * This is a vector of AverageDeviation stats.
2642 * @sa VectorDistBase, AvgSampleStor
2643 */
2644class VectorAverageDeviation
2645    : public VectorDistBase<VectorAverageDeviation, AvgSampleStor>
2646{
2647  public:
2648    /**
2649     * Initialize storage for this distribution.
2650     * @param size The size of the vector.
2651     * @return A reference to this distribution.
2652     */
2653    VectorAverageDeviation &
2654    init(size_type size)
2655    {
2656        AvgSampleStor::Params *params = new AvgSampleStor::Params;
2657        this->doInit(size);
2658        this->setParams(params);
2659        return this->self();
2660    }
2661};
2662
2663template <class Stat>
2664class FormulaInfoProxy : public InfoProxy<Stat, FormulaInfo>
2665{
2666  protected:
2667    mutable VResult vec;
2668    mutable VCounter cvec;
2669
2670  public:
2671    FormulaInfoProxy(Stat &stat) : InfoProxy<Stat, FormulaInfo>(stat) {}
2672
2673    size_type size() const { return this->s.size(); }
2674
2675    const VResult &
2676    result() const
2677    {
2678        this->s.result(vec);
2679        return vec;
2680    }
2681    Result total() const { return this->s.total(); }
2682    VCounter &value() const { return cvec; }
2683
2684    std::string str() const { return this->s.str(); }
2685};
2686
2687template <class Stat>
2688class SparseHistInfoProxy : public InfoProxy<Stat, SparseHistInfo>
2689{
2690  public:
2691    SparseHistInfoProxy(Stat &stat) : InfoProxy<Stat, SparseHistInfo>(stat) {}
2692};
2693
2694/**
2695 * Implementation of a sparse histogram stat. The storage class is
2696 * determined by the Storage template.
2697 */
2698template <class Derived, class Stor>
2699class SparseHistBase : public DataWrap<Derived, SparseHistInfoProxy>
2700{
2701  public:
2702    typedef SparseHistInfoProxy<Derived> Info;
2703    typedef Stor Storage;
2704    typedef typename Stor::Params Params;
2705
2706  protected:
2707    /** The storage for this stat. */
2708    char storage[sizeof(Storage)];
2709
2710  protected:
2711    /**
2712     * Retrieve the storage.
2713     * @return The storage object for this stat.
2714     */
2715    Storage *
2716    data()
2717    {
2718        return reinterpret_cast<Storage *>(storage);
2719    }
2720
2721    /**
2722     * Retrieve a const pointer to the storage.
2723     * @return A const pointer to the storage object for this stat.
2724     */
2725    const Storage *
2726    data() const
2727    {
2728        return reinterpret_cast<const Storage *>(storage);
2729    }
2730
2731    void
2732    doInit()
2733    {
2734        new (storage) Storage(this->info());
2735        this->setInit();
2736    }
2737
2738  public:
2739    SparseHistBase() { }
2740
2741    /**
2742     * Add a value to the distribtion n times. Calls sample on the storage
2743     * class.
2744     * @param v The value to add.
2745     * @param n The number of times to add it, defaults to 1.
2746     */
2747    template <typename U>
2748    void sample(const U &v, int n = 1) { data()->sample(v, n); }
2749
2750    /**
2751     * Return the number of entries in this stat.
2752     * @return The number of entries.
2753     */
2754    size_type size() const { return data()->size(); }
2755    /**
2756     * Return true if no samples have been added.
2757     * @return True if there haven't been any samples.
2758     */
2759    bool zero() const { return data()->zero(); }
2760
2761    void
2762    prepare()
2763    {
2764        Info *info = this->info();
2765        data()->prepare(info, info->data);
2766    }
2767
2768    /**
2769     * Reset stat value to default
2770     */
2771    void
2772    reset()
2773    {
2774        data()->reset(this->info());
2775    }
2776};
2777
2778/**
2779 * Templatized storage and interface for a sparse histogram stat.
2780 */
2781class SparseHistStor
2782{
2783  public:
2784    /** The parameters for a sparse histogram stat. */
2785    struct Params : public DistParams
2786    {
2787        Params() : DistParams(Hist) {}
2788    };
2789
2790  private:
2791    /** Counter for number of samples */
2792    Counter samples;
2793    /** Counter for each bucket. */
2794    MCounter cmap;
2795
2796  public:
2797    SparseHistStor(Info *info)
2798    {
2799        reset(info);
2800    }
2801
2802    /**
2803     * Add a value to the distribution for the given number of times.
2804     * @param val The value to add.
2805     * @param number The number of times to add the value.
2806     */
2807    void
2808    sample(Counter val, int number)
2809    {
2810        cmap[val] += number;
2811        samples += number;
2812    }
2813
2814    /**
2815     * Return the number of buckets in this distribution.
2816     * @return the number of buckets.
2817     */
2818    size_type size() const { return cmap.size(); }
2819
2820    /**
2821     * Returns true if any calls to sample have been made.
2822     * @return True if any values have been sampled.
2823     */
2824    bool
2825    zero() const
2826    {
2827        return samples == Counter();
2828    }
2829
2830    void
2831    prepare(Info *info, SparseHistData &data)
2832    {
2833        MCounter::iterator it;
2834        data.cmap.clear();
2835        for (it = cmap.begin(); it != cmap.end(); it++) {
2836            data.cmap[(*it).first] = (*it).second;
2837        }
2838
2839        data.samples = samples;
2840    }
2841
2842    /**
2843     * Reset stat value to default
2844     */
2845    void
2846    reset(Info *info)
2847    {
2848        cmap.clear();
2849        samples = 0;
2850    }
2851};
2852
2853class SparseHistogram : public SparseHistBase<SparseHistogram, SparseHistStor>
2854{
2855  public:
2856    /**
2857     * Set the parameters of this histogram. @sa HistStor::Params
2858     * @param size The number of buckets in the histogram
2859     * @return A reference to this histogram.
2860     */
2861    SparseHistogram &
2862    init(size_type size)
2863    {
2864        SparseHistStor::Params *params = new SparseHistStor::Params;
2865        this->setParams(params);
2866        this->doInit();
2867        return this->self();
2868    }
2869};
2870
2871class Temp;
2872/**
2873 * A formula for statistics that is calculated when printed. A formula is
2874 * stored as a tree of Nodes that represent the equation to calculate.
2875 * @sa Stat, ScalarStat, VectorStat, Node, Temp
2876 */
2877class Formula : public DataWrapVec<Formula, FormulaInfoProxy>
2878{
2879  protected:
2880    /** The root of the tree which represents the Formula */
2881    NodePtr root;
2882    friend class Temp;
2883
2884  public:
2885    /**
2886     * Create and initialize thie formula, and register it with the database.
2887     */
2888    Formula();
2889
2890    /**
2891     * Create a formula with the given root node, register it with the
2892     * database.
2893     * @param r The root of the expression tree.
2894     */
2895    Formula(Temp r);
2896
2897    /**
2898     * Set an unitialized Formula to the given root.
2899     * @param r The root of the expression tree.
2900     * @return a reference to this formula.
2901     */
2902    const Formula &operator=(Temp r);
2903
2904    /**
2905     * Add the given tree to the existing one.
2906     * @param r The root of the expression tree.
2907     * @return a reference to this formula.
2908     */
2909    const Formula &operator+=(Temp r);
2910
2911    /**
2912     * Divide the existing tree by the given one.
2913     * @param r The root of the expression tree.
2914     * @return a reference to this formula.
2915     */
2916    const Formula &operator/=(Temp r);
2917
2918    /**
2919     * Return the result of the Fomula in a vector.  If there were no Vector
2920     * components to the Formula, then the vector is size 1.  If there were,
2921     * like x/y with x being a vector of size 3, then the result returned will
2922     * be x[0]/y, x[1]/y, x[2]/y, respectively.
2923     * @return The result vector.
2924     */
2925    void result(VResult &vec) const;
2926
2927    /**
2928     * Return the total Formula result.  If there is a Vector
2929     * component to this Formula, then this is the result of the
2930     * Formula if the formula is applied after summing all the
2931     * components of the Vector.  For example, if Formula is x/y where
2932     * x is size 3, then total() will return (x[1]+x[2]+x[3])/y.  If
2933     * there is no Vector component, total() returns the same value as
2934     * the first entry in the VResult val() returns.
2935     * @return The total of the result vector.
2936     */
2937    Result total() const;
2938
2939    /**
2940     * Return the number of elements in the tree.
2941     */
2942    size_type size() const;
2943
2944    void prepare() { }
2945
2946    /**
2947     * Formulas don't need to be reset
2948     */
2949    void reset();
2950
2951    /**
2952     *
2953     */
2954    bool zero() const;
2955
2956    std::string str() const;
2957};
2958
2959class FormulaNode : public Node
2960{
2961  private:
2962    const Formula &formula;
2963    mutable VResult vec;
2964
2965  public:
2966    FormulaNode(const Formula &f) : formula(f) {}
2967
2968    size_type size() const { return formula.size(); }
2969    const VResult &result() const { formula.result(vec); return vec; }
2970    Result total() const { return formula.total(); }
2971
2972    std::string str() const { return formula.str(); }
2973};
2974
2975/**
2976 * Helper class to construct formula node trees.
2977 */
2978class Temp
2979{
2980  protected:
2981    /**
2982     * Pointer to a Node object.
2983     */
2984    NodePtr node;
2985
2986  public:
2987    /**
2988     * Copy the given pointer to this class.
2989     * @param n A pointer to a Node object to copy.
2990     */
2991    Temp(NodePtr n) : node(n) { }
2992
2993    /**
2994     * Return the node pointer.
2995     * @return the node pointer.
2996     */
2997    operator NodePtr&() { return node; }
2998
2999  public:
3000    /**
3001     * Create a new ScalarStatNode.
3002     * @param s The ScalarStat to place in a node.
3003     */
3004    Temp(const Scalar &s)
3005        : node(new ScalarStatNode(s.info()))
3006    { }
3007
3008    /**
3009     * Create a new ScalarStatNode.
3010     * @param s The ScalarStat to place in a node.
3011     */
3012    Temp(const Value &s)
3013        : node(new ScalarStatNode(s.info()))
3014    { }
3015
3016    /**
3017     * Create a new ScalarStatNode.
3018     * @param s The ScalarStat to place in a node.
3019     */
3020    Temp(const Average &s)
3021        : node(new ScalarStatNode(s.info()))
3022    { }
3023
3024    /**
3025     * Create a new VectorStatNode.
3026     * @param s The VectorStat to place in a node.
3027     */
3028    Temp(const Vector &s)
3029        : node(new VectorStatNode(s.info()))
3030    { }
3031
3032    Temp(const AverageVector &s)
3033        : node(new VectorStatNode(s.info()))
3034    { }
3035
3036    /**
3037     *
3038     */
3039    Temp(const Formula &f)
3040        : node(new FormulaNode(f))
3041    { }
3042
3043    /**
3044     * Create a new ScalarProxyNode.
3045     * @param p The ScalarProxy to place in a node.
3046     */
3047    template <class Stat>
3048    Temp(const ScalarProxy<Stat> &p)
3049        : node(new ScalarProxyNode<Stat>(p))
3050    { }
3051
3052    /**
3053     * Create a ConstNode
3054     * @param value The value of the const node.
3055     */
3056    Temp(signed char value)
3057        : node(new ConstNode<signed char>(value))
3058    { }
3059
3060    /**
3061     * Create a ConstNode
3062     * @param value The value of the const node.
3063     */
3064    Temp(unsigned char value)
3065        : node(new ConstNode<unsigned char>(value))
3066    { }
3067
3068    /**
3069     * Create a ConstNode
3070     * @param value The value of the const node.
3071     */
3072    Temp(signed short value)
3073        : node(new ConstNode<signed short>(value))
3074    { }
3075
3076    /**
3077     * Create a ConstNode
3078     * @param value The value of the const node.
3079     */
3080    Temp(unsigned short value)
3081        : node(new ConstNode<unsigned short>(value))
3082    { }
3083
3084    /**
3085     * Create a ConstNode
3086     * @param value The value of the const node.
3087     */
3088    Temp(signed int value)
3089        : node(new ConstNode<signed int>(value))
3090    { }
3091
3092    /**
3093     * Create a ConstNode
3094     * @param value The value of the const node.
3095     */
3096    Temp(unsigned int value)
3097        : node(new ConstNode<unsigned int>(value))
3098    { }
3099
3100    /**
3101     * Create a ConstNode
3102     * @param value The value of the const node.
3103     */
3104    Temp(signed long value)
3105        : node(new ConstNode<signed long>(value))
3106    { }
3107
3108    /**
3109     * Create a ConstNode
3110     * @param value The value of the const node.
3111     */
3112    Temp(unsigned long value)
3113        : node(new ConstNode<unsigned long>(value))
3114    { }
3115
3116    /**
3117     * Create a ConstNode
3118     * @param value The value of the const node.
3119     */
3120    Temp(signed long long value)
3121        : node(new ConstNode<signed long long>(value))
3122    { }
3123
3124    /**
3125     * Create a ConstNode
3126     * @param value The value of the const node.
3127     */
3128    Temp(unsigned long long value)
3129        : node(new ConstNode<unsigned long long>(value))
3130    { }
3131
3132    /**
3133     * Create a ConstNode
3134     * @param value The value of the const node.
3135     */
3136    Temp(float value)
3137        : node(new ConstNode<float>(value))
3138    { }
3139
3140    /**
3141     * Create a ConstNode
3142     * @param value The value of the const node.
3143     */
3144    Temp(double value)
3145        : node(new ConstNode<double>(value))
3146    { }
3147};
3148
3149
3150/**
3151 * @}
3152 */
3153
3154inline Temp
3155operator+(Temp l, Temp r)
3156{
3157    return NodePtr(new BinaryNode<std::plus<Result> >(l, r));
3158}
3159
3160inline Temp
3161operator-(Temp l, Temp r)
3162{
3163    return NodePtr(new BinaryNode<std::minus<Result> >(l, r));
3164}
3165
3166inline Temp
3167operator*(Temp l, Temp r)
3168{
3169    return NodePtr(new BinaryNode<std::multiplies<Result> >(l, r));
3170}
3171
3172inline Temp
3173operator/(Temp l, Temp r)
3174{
3175    return NodePtr(new BinaryNode<std::divides<Result> >(l, r));
3176}
3177
3178inline Temp
3179operator-(Temp l)
3180{
3181    return NodePtr(new UnaryNode<std::negate<Result> >(l));
3182}
3183
3184template <typename T>
3185inline Temp
3186constant(T val)
3187{
3188    return NodePtr(new ConstNode<T>(val));
3189}
3190
3191template <typename T>
3192inline Temp
3193constantVector(T val)
3194{
3195    return NodePtr(new ConstVectorNode<T>(val));
3196}
3197
3198inline Temp
3199sum(Temp val)
3200{
3201    return NodePtr(new SumNode<std::plus<Result> >(val));
3202}
3203
3204/** Dump all statistics data to the registered outputs */
3205void dump();
3206void reset();
3207void enable();
3208bool enabled();
3209
3210/**
3211 * Register a callback that should be called whenever statistics are
3212 * reset
3213 */
3214void registerResetCallback(Callback *cb);
3215
3216/**
3217 * Register a callback that should be called whenever statistics are
3218 * about to be dumped
3219 */
3220void registerDumpCallback(Callback *cb);
3221
3222std::list<Info *> &statsList();
3223
3224typedef std::map<const void *, Info *> MapType;
3225MapType &statsMap();
3226
3227typedef std::map<std::string, Info *> NameMapType;
3228NameMapType &nameMap();
3229
3230bool validateStatName(const std::string &name);
3231
3232} // namespace Stats
3233
3234void debugDumpStats();
3235
3236#endif // __BASE_STATISTICS_HH__
3237