x86: Adjust the size of the values written to the x87 misc registers
[gem5.git] / src / base / statistics.hh
index f7625779a141b758232f913c194d92dd049f7647..a21bf81d17ba21dda0e6ace9150a396f78b0bd09 100644 (file)
 #include <functional>
 #include <iosfwd>
 #include <list>
+#include <map>
+#include <memory>
 #include <string>
 #include <vector>
 
+#include "base/stats/info.hh"
+#include "base/stats/output.hh"
+#include "base/stats/types.hh"
 #include "base/cast.hh"
 #include "base/cprintf.hh"
 #include "base/intmath.hh"
-#include "base/refcnt.hh"
-#include "base/stats/info.hh"
-#include "base/stats/types.hh"
-#include "base/stats/visit.hh"
 #include "base/str.hh"
 #include "base/types.hh"
 
 class Callback;
 
 /** The current simulated tick. */
-extern Tick curTick;
+extern Tick curTick();
 
 /* A namespace for all of the Statistics */
 namespace Stats {
@@ -90,7 +91,7 @@ class InfoProxy : public Base
     void prepare() { s.prepare(); }
     void reset() { s.reset(); }
     void
-    visit(Visit &visitor)
+    visit(Output &visitor)
     {
         visitor.visit(*static_cast<Base *>(this));
     }
@@ -160,6 +161,11 @@ class Vector2dInfoProxy : public InfoProxy<Stat, Vector2dInfo>
     Vector2dInfoProxy(Stat &stat) : InfoProxy<Stat, Vector2dInfo>(stat) {}
 };
 
+struct StorageParams
+{
+    virtual ~StorageParams();
+};
+
 class InfoAccess
 {
   protected:
@@ -222,12 +228,12 @@ class DataWrap : public InfoAccess
     /**
      * Copy constructor, copies are not allowed.
      */
-    DataWrap(const DataWrap &stat);
+    DataWrap(const DataWrap &stat) {}
 
     /**
      * Can't copy stats.
      */
-    void operator=(const DataWrap &);
+    void operator=(const DataWrap &) {}
 
   public:
     DataWrap()
@@ -245,11 +251,28 @@ class DataWrap : public InfoAccess
     {
         Info *info = this->info();
         info->setName(name);
-        info->flags.set(print);
+        info->flags.set(display);
         return this->self();
     }
     const std::string &name() const { return this->info()->name; }
 
+    /**
+     * Set the character(s) used between the name and vector number
+     * on vectors, dist, etc.
+     * @param _sep The new separator string
+     * @return A reference to this stat.
+     */
+    Derived &
+    setSeparator(const std::string &_sep)
+    {
+      this->info()->setSeparator(_sep);
+      return this->self();
+    }
+    const std::string &setSeparator() const
+    {
+      return this->info()->separatorString;
+    }
+
     /**
      * Set the description and marks this stat to print at the end of
      * simulation.
@@ -308,6 +331,15 @@ class DataWrapVec : public DataWrap<Derived, InfoProxyType>
   public:
     typedef InfoProxyType<Derived> Info;
 
+    DataWrapVec()
+    {}
+
+    DataWrapVec(const DataWrapVec &ref)
+    {}
+
+    void operator=(const DataWrapVec &)
+    {}
+
     // The following functions are specific to vectors.  If you use them
     // in a non vector context, you will get a nice compiler error!
 
@@ -401,7 +433,7 @@ class DataWrapVec2d : public DataWrapVec<Derived, InfoProxyType>
     }
 
     Derived &
-    ysubname(off_type index, const std::string subname)
+    ysubname(off_type index, const std::string &subname)
     {
         Derived &self = this->self();
         Info *info = this->info();
@@ -411,6 +443,13 @@ class DataWrapVec2d : public DataWrapVec<Derived, InfoProxyType>
         info->y_subnames[index] = subname.c_str();
         return self;
     }
+
+    std::string
+    ysubname(off_type i) const
+    {
+        return this->info()->y_subnames[i];
+    }
+
 };
 
 //////////////////////////////////////////////////////////////////////
@@ -518,8 +557,8 @@ class AvgStor
     void
     set(Counter val)
     {
-        total += current * (curTick - last);
-        last = curTick;
+        total += current * (curTick() - last);
+        last = curTick();
         current = val;
     }
 
@@ -548,8 +587,8 @@ class AvgStor
     Result
     result() const
     {
-        assert(last == curTick);
-        return (Result)(total + current) / (Result)(curTick - lastReset + 1);
+        assert(last == curTick());
+        return (Result)(total + current) / (Result)(curTick() - lastReset + 1);
     }
 
     /**
@@ -563,8 +602,8 @@ class AvgStor
     void
     prepare(Info *info)
     {
-        total += current * (curTick - last);
-        last = curTick;
+        total += current * (curTick() - last);
+        last = curTick();
     }
 
     /**
@@ -574,8 +613,8 @@ class AvgStor
     reset(Info *info)
     {
         total = 0.0;
-        last = curTick;
-        lastReset = curTick;
+        last = curTick();
+        lastReset = curTick();
     }
 
 };
@@ -702,14 +741,14 @@ class ScalarBase : public DataWrap<Derived, ScalarInfoProxy>
 class ProxyInfo : public ScalarInfo
 {
   public:
-    std::string str() const { return to_string(value()); }
+    std::string str() const { return std::to_string(value()); }
     size_type size() const { return 1; }
     bool check() const { return true; }
     void prepare() { }
     void reset() { }
     bool zero() const { return value() == 0; }
 
-    void visit(Visit &visitor) { visitor.visit(*this); }
+    void visit(Output &visitor) { visitor.visit(*this); }
 };
 
 template <class T>
@@ -738,6 +777,25 @@ class FunctorProxy : public ProxyInfo
     Result total() const { return (*functor)(); }
 };
 
+/**
+ * A proxy similar to the FunctorProxy, but allows calling a method of a bound
+ * object, instead of a global free-standing function.
+ */
+template <class T, class V>
+class MethodProxy : public ProxyInfo
+{
+  private:
+    T *object;
+    typedef V (T::*MethodPointer) () const;
+    MethodPointer method;
+
+  public:
+    MethodProxy(T *obj, MethodPointer meth) : object(obj), method(meth) {}
+    Counter value() const { return (object->*method)(); }
+    Result result() const { return (object->*method)(); }
+    Result total() const { return (object->*method)(); }
+};
+
 template <class Derived>
 class ValueBase : public DataWrap<Derived, ScalarInfoProxy>
 {
@@ -766,6 +824,22 @@ class ValueBase : public DataWrap<Derived, ScalarInfoProxy>
         return this->self();
     }
 
+    /**
+     * Extended functor that calls the specified method of the provided object.
+     *
+     * @param obj Pointer to the object whose method should be called.
+     * @param method Pointer of the function / method of the object.
+     * @return Updated stats item.
+     */
+    template <class T, class V>
+    Derived &
+    method(T *obj,  V (T::*method)() const)
+    {
+        proxy = new MethodProxy<T,V>(obj, method);
+        this->setInit();
+        return this->self();
+    }
+
     Counter value() { return proxy->value(); }
     Result result() const { return proxy->result(); }
     Result total() const { return proxy->total(); };
@@ -1018,7 +1092,7 @@ class VectorBase : public DataWrapVec<Derived, VectorInfoProxy>
 
   public:
     VectorBase()
-        : storage(NULL)
+        : storage(nullptr), _size(0)
     {}
 
     ~VectorBase()
@@ -1158,7 +1232,7 @@ class Vector2dBase : public DataWrapVec2d<Derived, Vector2dInfoProxy>
 
   public:
     Vector2dBase()
-        : storage(NULL)
+        : x(0), y(0), _size(0), storage(nullptr)
     {}
 
     ~Vector2dBase()
@@ -1197,13 +1271,11 @@ class Vector2dBase : public DataWrapVec2d<Derived, Vector2dInfoProxy>
         return self;
     }
 
-    std::string ysubname(off_type i) const { return (*this->y_subnames)[i]; }
-
     Proxy
     operator[](off_type index)
     {
         off_type offset = index * y;
-        assert (index >= 0 && offset + index < size());
+        assert (index >= 0 && offset + y <= size());
         return Proxy(this->self(), offset, y);
     }
 
@@ -1264,6 +1336,12 @@ class Vector2dBase : public DataWrapVec2d<Derived, Vector2dInfoProxy>
 // Non formula statistics
 //
 //////////////////////////////////////////////////////////////////////
+/** The parameters for a distribution stat. */
+struct DistParams : public StorageParams
+{
+    const DistType type;
+    DistParams(DistType t) : type(t) {}
+};
 
 /**
  * Templatized storage and interface for a distrbution stat.
@@ -1274,7 +1352,17 @@ class DistStor
     /** The parameters for a distribution stat. */
     struct Params : public DistParams
     {
-        Params() : DistParams(Dist) {}
+        /** The minimum value to track. */
+        Counter min;
+        /** The maximum value to track. */
+        Counter max;
+        /** The number of entries in each bucket. */
+        Counter bucket_size;
+        /** The number of buckets. Equal to (max-min)/bucket_size. */
+        size_type buckets;
+
+        Params() : DistParams(Dist), min(0), max(0), bucket_size(0),
+                   buckets(0) {}
     };
 
   private:
@@ -1284,8 +1372,6 @@ class DistStor
     Counter max_track;
     /** The number of entries in each bucket. */
     Counter bucket_size;
-    /** The number of buckets. Equal to (max-min)/bucket_size. */
-    size_type buckets;
 
     /** The smallest value sampled. */
     Counter min_val;
@@ -1336,9 +1422,8 @@ class DistStor
         if (val > max_val)
             max_val = val;
 
-        Counter sample = val * number;
-        sum += sample;
-        squares += sample * sample;
+        sum += val * number;
+        squares += val * val * number;
         samples += number;
     }
 
@@ -1363,14 +1448,19 @@ class DistStor
     {
         const Params *params = safe_cast<const Params *>(info->storageParams);
 
+        assert(params->type == Dist);
+        data.type = params->type;
+        data.min = params->min;
+        data.max = params->max;
+        data.bucket_size = params->bucket_size;
+
         data.min_val = (min_val == CounterLimits::max()) ? 0 : min_val;
         data.max_val = (max_val == CounterLimits::min()) ? 0 : max_val;
         data.underflow = underflow;
         data.overflow = overflow;
 
-        size_type buckets = params->buckets;
-        data.cvec.resize(buckets);
-        for (off_type i = 0; i < buckets; ++i)
+        data.cvec.resize(params->buckets);
+        for (off_type i = 0; i < params->buckets; ++i)
             data.cvec[i] = cvec[i];
 
         data.sum = sum;
@@ -1404,6 +1494,152 @@ class DistStor
     }
 };
 
+/**
+ * Templatized storage and interface for a histogram stat.
+ */
+class HistStor
+{
+  public:
+    /** The parameters for a distribution stat. */
+    struct Params : public DistParams
+    {
+        /** The number of buckets.. */
+        size_type buckets;
+
+        Params() : DistParams(Hist), buckets(0) {}
+    };
+
+  private:
+    /** The minimum value to track. */
+    Counter min_bucket;
+    /** The maximum value to track. */
+    Counter max_bucket;
+    /** The number of entries in each bucket. */
+    Counter bucket_size;
+
+    /** The current sum. */
+    Counter sum;
+    /** The sum of logarithm of each sample, used to compute geometric mean. */
+    Counter logs;
+    /** The sum of squares. */
+    Counter squares;
+    /** The number of samples. */
+    Counter samples;
+    /** Counter for each bucket. */
+    VCounter cvec;
+
+  public:
+    HistStor(Info *info)
+        : cvec(safe_cast<const Params *>(info->storageParams)->buckets)
+    {
+        reset(info);
+    }
+
+    void grow_up();
+    void grow_out();
+    void grow_convert();
+    void add(HistStor *);
+
+    /**
+     * Add a value to the distribution for the given number of times.
+     * @param val The value to add.
+     * @param number The number of times to add the value.
+     */
+    void
+    sample(Counter val, int number)
+    {
+        assert(min_bucket < max_bucket);
+        if (val < min_bucket) {
+            if (min_bucket == 0)
+                grow_convert();
+
+            while (val < min_bucket)
+                grow_out();
+        } else if (val >= max_bucket + bucket_size) {
+            if (min_bucket == 0) {
+                while (val >= max_bucket + bucket_size)
+                    grow_up();
+            } else {
+                while (val >= max_bucket + bucket_size)
+                    grow_out();
+            }
+        }
+
+        size_type index =
+            (int64_t)std::floor((val - min_bucket) / bucket_size);
+
+        assert(index < size());
+        cvec[index] += number;
+
+        sum += val * number;
+        squares += val * val * number;
+        logs += log(val) * number;
+        samples += number;
+    }
+
+    /**
+     * Return the number of buckets in this distribution.
+     * @return the number of buckets.
+     */
+    size_type size() const { return cvec.size(); }
+
+    /**
+     * Returns true if any calls to sample have been made.
+     * @return True if any values have been sampled.
+     */
+    bool
+    zero() const
+    {
+        return samples == Counter();
+    }
+
+    void
+    prepare(Info *info, DistData &data)
+    {
+        const Params *params = safe_cast<const Params *>(info->storageParams);
+
+        assert(params->type == Hist);
+        data.type = params->type;
+        data.min = min_bucket;
+        data.max = max_bucket + bucket_size - 1;
+        data.bucket_size = bucket_size;
+
+        data.min_val = min_bucket;
+        data.max_val = max_bucket;
+
+        int buckets = params->buckets;
+        data.cvec.resize(buckets);
+        for (off_type i = 0; i < buckets; ++i)
+            data.cvec[i] = cvec[i];
+
+        data.sum = sum;
+        data.logs = logs;
+        data.squares = squares;
+        data.samples = samples;
+    }
+
+    /**
+     * Reset stat value to default
+     */
+    void
+    reset(Info *info)
+    {
+        const Params *params = safe_cast<const Params *>(info->storageParams);
+        min_bucket = 0;
+        max_bucket = params->buckets - 1;
+        bucket_size = 1;
+
+        size_type size = cvec.size();
+        for (off_type i = 0; i < size; ++i)
+            cvec[i] = Counter();
+
+        sum = Counter();
+        squares = Counter();
+        samples = Counter();
+        logs = Counter();
+    }
+};
+
 /**
  * Templatized storage and interface for a distribution that calculates mean
  * and variance.
@@ -1463,6 +1699,10 @@ class SampleStor
     void
     prepare(Info *info, DistData &data)
     {
+        const Params *params = safe_cast<const Params *>(info->storageParams);
+
+        assert(params->type == Deviation);
+        data.type = params->type;
         data.sum = sum;
         data.squares = squares;
         data.samples = samples;
@@ -1535,9 +1775,13 @@ class AvgSampleStor
     void
     prepare(Info *info, DistData &data)
     {
+        const Params *params = safe_cast<const Params *>(info->storageParams);
+
+        assert(params->type == Deviation);
+        data.type = params->type;
         data.sum = sum;
         data.squares = squares;
-        data.samples = curTick;
+        data.samples = curTick();
     }
 
     /**
@@ -1633,6 +1877,12 @@ class DistBase : public DataWrap<Derived, DistInfoProxy>
     {
         data()->reset(this->info());
     }
+
+    /**
+     *  Add the argument distribution to the this distibution.
+     */
+    void add(DistBase &d) { data()->add(d.data()); }
+
 };
 
 template <class Stat>
@@ -1713,13 +1963,10 @@ class VectorDistBase : public DataWrapVec<Derived, VectorDistInfoProxy>
     bool
     zero() const
     {
-        return false;
-#if 0
         for (off_type i = 0; i < size(); ++i)
             if (!data(i)->zero())
                 return false;
         return true;
-#endif
     }
 
     void
@@ -1792,27 +2039,6 @@ class DistProxy
      */
     void reset() { }
 };
-/*
-template <class Derived, class Stor>
-inline typename VectorDistBase<Derived, Stor>::Proxy
-VectorDistBase<Derived, Stor>::operator[](off_type index)
-{
-    assert (index >= 0 && index < size());
-    typedef typename VectorDistBase<Derived, Stor>::Proxy Proxy;
-    return Proxy(this->self(), index);
-}
-*/
-
-#if 0
-template <class Storage>
-Result
-VectorDistBase<Storage>::total(off_type index) const
-{
-    Result total = 0.0;
-    for (off_type i = 0; i < x_size(); ++i)
-        total += data(i)->result();
-}
-#endif
 
 //////////////////////////////////////////////////////////////////////
 //
@@ -1824,7 +2050,7 @@ VectorDistBase<Storage>::total(off_type index) const
  * Base class for formula statistic node. These nodes are used to build a tree
  * that represents the formula.
  */
-class Node : public RefCounted
+class Node
 {
   public:
     /**
@@ -1849,8 +2075,8 @@ class Node : public RefCounted
     virtual std::string str() const = 0;
 };
 
-/** Reference counting pointer to a function Node. */
-typedef RefCountingPtr<Node> NodePtr;
+/** Shared pointer to a function Node. */
+typedef std::shared_ptr<Node> NodePtr;
 
 class ScalarStatNode : public Node
 {
@@ -1945,7 +2171,7 @@ class ConstNode : public Node
     const VResult &result() const { return vresult; }
     Result total() const { return vresult[0]; };
     size_type size() const { return 1; }
-    std::string str() const { return to_string(vresult[0]); }
+    std::string str() const { return std::to_string(vresult[0]); }
 };
 
 template <class T>
@@ -1975,7 +2201,7 @@ class ConstVectorNode : public Node
         size_type size = this->size();
         std::string tmp = "(";
         for (off_type i = 0; i < size; i++)
-            tmp += csprintf("%s ",to_string(vresult[i]));
+            tmp += csprintf("%s ", std::to_string(vresult[i]));
         tmp += ")";
         return tmp;
     }
@@ -2112,9 +2338,31 @@ class BinaryNode : public Node
     total() const
     {
         const VResult &vec = this->result();
+        const VResult &lvec = l->result();
+        const VResult &rvec = r->result();
         Result total = 0.0;
-        for (off_type i = 0; i < size(); i++)
+        Result lsum = 0.0;
+        Result rsum = 0.0;
+        Op op;
+
+        assert(lvec.size() > 0 && rvec.size() > 0);
+        assert(lvec.size() == rvec.size() ||
+               lvec.size() == 1 || rvec.size() == 1);
+
+        /** If vectors are the same divide their sums (x0+x1)/(y0+y1) */
+        if (lvec.size() == rvec.size() && lvec.size() > 1) {
+            for (off_type i = 0; i < size(); ++i) {
+                lsum += lvec[i];
+                rsum += rvec[i];
+            }
+            return op(lsum, rsum);
+        }
+
+        /** Otherwise divide each item by the divisor */
+        for (off_type i = 0; i < size(); ++i) {
             total += vec[i];
+        }
+
         return total;
     }
 
@@ -2173,13 +2421,13 @@ class SumNode : public Node
         size_type size = lvec.size();
         assert(size > 0);
 
-        Result vresult = 0.0;
+        Result result = 0.0;
 
         Op op;
         for (off_type i = 0; i < size; ++i)
-            vresult = op(vresult, lvec[i]);
+            result = op(result, lvec[i]);
 
-        return vresult;
+        return result;
     }
 
     size_type size() const { return 1; }
@@ -2272,7 +2520,30 @@ class Distribution : public DistBase<Distribution, DistStor>
         params->min = min;
         params->max = max;
         params->bucket_size = bkt;
-        params->buckets = (size_type)rint((max - min + 1.0) / bkt );
+        params->buckets = (size_type)ceil((max - min + 1.0) / bkt);
+        this->setParams(params);
+        this->doInit();
+        return this->self();
+    }
+};
+
+/**
+ * A simple histogram stat.
+ * @sa Stat, DistBase, HistStor
+ */
+class Histogram : public DistBase<Histogram, HistStor>
+{
+  public:
+    /**
+     * Set the parameters of this histogram. @sa HistStor::Params
+     * @param size The number of buckets in the histogram
+     * @return A reference to this histogram.
+     */
+    Histogram &
+    init(size_type size)
+    {
+        HistStor::Params *params = new HistStor::Params;
+        params->buckets = size;
         this->setParams(params);
         this->doInit();
         return this->self();
@@ -2291,7 +2562,9 @@ class StandardDeviation : public DistBase<StandardDeviation, SampleStor>
      */
     StandardDeviation()
     {
+        SampleStor::Params *params = new SampleStor::Params;
         this->doInit();
+        this->setParams(params);
     }
 };
 
@@ -2307,7 +2580,9 @@ class AverageDeviation : public DistBase<AverageDeviation, AvgSampleStor>
      */
     AverageDeviation()
     {
+        AvgSampleStor::Params *params = new AvgSampleStor::Params;
         this->doInit();
+        this->setParams(params);
     }
 };
 
@@ -2333,7 +2608,7 @@ class VectorDistribution : public VectorDistBase<VectorDistribution, DistStor>
         params->min = min;
         params->max = max;
         params->bucket_size = bkt;
-        params->buckets = (size_type)rint((max - min + 1.0) / bkt);
+        params->buckets = (size_type)ceil((max - min + 1.0) / bkt);
         this->setParams(params);
         this->doInit(size);
         return this->self();
@@ -2356,7 +2631,9 @@ class VectorStandardDeviation
     VectorStandardDeviation &
     init(size_type size)
     {
+        SampleStor::Params *params = new SampleStor::Params;
         this->doInit(size);
+        this->setParams(params);
         return this->self();
     }
 };
@@ -2377,7 +2654,9 @@ class VectorAverageDeviation
     VectorAverageDeviation &
     init(size_type size)
     {
+        AvgSampleStor::Params *params = new AvgSampleStor::Params;
         this->doInit(size);
+        this->setParams(params);
         return this->self();
     }
 };
@@ -2406,6 +2685,190 @@ class FormulaInfoProxy : public InfoProxy<Stat, FormulaInfo>
     std::string str() const { return this->s.str(); }
 };
 
+template <class Stat>
+class SparseHistInfoProxy : public InfoProxy<Stat, SparseHistInfo>
+{
+  public:
+    SparseHistInfoProxy(Stat &stat) : InfoProxy<Stat, SparseHistInfo>(stat) {}
+};
+
+/**
+ * Implementation of a sparse histogram stat. The storage class is
+ * determined by the Storage template.
+ */
+template <class Derived, class Stor>
+class SparseHistBase : public DataWrap<Derived, SparseHistInfoProxy>
+{
+  public:
+    typedef SparseHistInfoProxy<Derived> Info;
+    typedef Stor Storage;
+    typedef typename Stor::Params Params;
+
+  protected:
+    /** The storage for this stat. */
+    char storage[sizeof(Storage)];
+
+  protected:
+    /**
+     * Retrieve the storage.
+     * @return The storage object for this stat.
+     */
+    Storage *
+    data()
+    {
+        return reinterpret_cast<Storage *>(storage);
+    }
+
+    /**
+     * Retrieve a const pointer to the storage.
+     * @return A const pointer to the storage object for this stat.
+     */
+    const Storage *
+    data() const
+    {
+        return reinterpret_cast<const Storage *>(storage);
+    }
+
+    void
+    doInit()
+    {
+        new (storage) Storage(this->info());
+        this->setInit();
+    }
+
+  public:
+    SparseHistBase() { }
+
+    /**
+     * Add a value to the distribtion n times. Calls sample on the storage
+     * class.
+     * @param v The value to add.
+     * @param n The number of times to add it, defaults to 1.
+     */
+    template <typename U>
+    void sample(const U &v, int n = 1) { data()->sample(v, n); }
+
+    /**
+     * Return the number of entries in this stat.
+     * @return The number of entries.
+     */
+    size_type size() const { return data()->size(); }
+    /**
+     * Return true if no samples have been added.
+     * @return True if there haven't been any samples.
+     */
+    bool zero() const { return data()->zero(); }
+
+    void
+    prepare()
+    {
+        Info *info = this->info();
+        data()->prepare(info, info->data);
+    }
+
+    /**
+     * Reset stat value to default
+     */
+    void
+    reset()
+    {
+        data()->reset(this->info());
+    }
+};
+
+/**
+ * Templatized storage and interface for a sparse histogram stat.
+ */
+class SparseHistStor
+{
+  public:
+    /** The parameters for a sparse histogram stat. */
+    struct Params : public DistParams
+    {
+        Params() : DistParams(Hist) {}
+    };
+
+  private:
+    /** Counter for number of samples */
+    Counter samples;
+    /** Counter for each bucket. */
+    MCounter cmap;
+
+  public:
+    SparseHistStor(Info *info)
+    {
+        reset(info);
+    }
+
+    /**
+     * Add a value to the distribution for the given number of times.
+     * @param val The value to add.
+     * @param number The number of times to add the value.
+     */
+    void
+    sample(Counter val, int number)
+    {
+        cmap[val] += number;
+        samples += number;
+    }
+
+    /**
+     * Return the number of buckets in this distribution.
+     * @return the number of buckets.
+     */
+    size_type size() const { return cmap.size(); }
+
+    /**
+     * Returns true if any calls to sample have been made.
+     * @return True if any values have been sampled.
+     */
+    bool
+    zero() const
+    {
+        return samples == Counter();
+    }
+
+    void
+    prepare(Info *info, SparseHistData &data)
+    {
+        MCounter::iterator it;
+        data.cmap.clear();
+        for (it = cmap.begin(); it != cmap.end(); it++) {
+            data.cmap[(*it).first] = (*it).second;
+        }
+
+        data.samples = samples;
+    }
+
+    /**
+     * Reset stat value to default
+     */
+    void
+    reset(Info *info)
+    {
+        cmap.clear();
+        samples = 0;
+    }
+};
+
+class SparseHistogram : public SparseHistBase<SparseHistogram, SparseHistStor>
+{
+  public:
+    /**
+     * Set the parameters of this histogram. @sa HistStor::Params
+     * @param size The number of buckets in the histogram
+     * @return A reference to this histogram.
+     */
+    SparseHistogram &
+    init(size_type size)
+    {
+        SparseHistStor::Params *params = new SparseHistStor::Params;
+        this->setParams(params);
+        this->doInit();
+        return this->self();
+    }
+};
+
 class Temp;
 /**
  * A formula for statistics that is calculated when printed. A formula is
@@ -2445,6 +2908,14 @@ class Formula : public DataWrapVec<Formula, FormulaInfoProxy>
      * @return a reference to this formula.
      */
     const Formula &operator+=(Temp r);
+
+    /**
+     * Divide the existing tree by the given one.
+     * @param r The root of the expression tree.
+     * @return a reference to this formula.
+     */
+    const Formula &operator/=(Temp r);
+
     /**
      * Return the result of the Fomula in a vector.  If there were no Vector
      * components to the Formula, then the vector is size 1.  If there were,
@@ -2518,7 +2989,9 @@ class Temp
      * Copy the given pointer to this class.
      * @param n A pointer to a Node object to copy.
      */
-    Temp(NodePtr n) : node(n) { }
+    Temp(const NodePtr &n) : node(n) { }
+
+    Temp(NodePtr &&n) : node(std::move(n)) { }
 
     /**
      * Return the node pointer.
@@ -2526,6 +2999,11 @@ class Temp
      */
     operator NodePtr&() { return node; }
 
+    /**
+     * Makde gcc < 4.6.3 happy and explicitly get the underlying node.
+     */
+    NodePtr getNodePtr() const { return node; }
+
   public:
     /**
      * Create a new ScalarStatNode.
@@ -2684,83 +3162,102 @@ class Temp
 inline Temp
 operator+(Temp l, Temp r)
 {
-    return NodePtr(new BinaryNode<std::plus<Result> >(l, r));
+    return Temp(std::make_shared<BinaryNode<std::plus<Result> > >(l, r));
 }
 
 inline Temp
 operator-(Temp l, Temp r)
 {
-    return NodePtr(new BinaryNode<std::minus<Result> >(l, r));
+    return Temp(std::make_shared<BinaryNode<std::minus<Result> > >(l, r));
 }
 
 inline Temp
 operator*(Temp l, Temp r)
 {
-    return NodePtr(new BinaryNode<std::multiplies<Result> >(l, r));
+    return Temp(std::make_shared<BinaryNode<std::multiplies<Result> > >(l, r));
 }
 
 inline Temp
 operator/(Temp l, Temp r)
 {
-    return NodePtr(new BinaryNode<std::divides<Result> >(l, r));
+    return Temp(std::make_shared<BinaryNode<std::divides<Result> > >(l, r));
 }
 
 inline Temp
 operator-(Temp l)
 {
-    return NodePtr(new UnaryNode<std::negate<Result> >(l));
+    return Temp(std::make_shared<UnaryNode<std::negate<Result> > >(l));
 }
 
 template <typename T>
 inline Temp
 constant(T val)
 {
-    return NodePtr(new ConstNode<T>(val));
+    return Temp(std::make_shared<ConstNode<T> >(val));
 }
 
 template <typename T>
 inline Temp
 constantVector(T val)
 {
-    return NodePtr(new ConstVectorNode<T>(val));
+    return Temp(std::make_shared<ConstVectorNode<T> >(val));
 }
 
 inline Temp
 sum(Temp val)
 {
-    return NodePtr(new SumNode<std::plus<Result> >(val));
+    return Temp(std::make_shared<SumNode<std::plus<Result> > >(val));
 }
 
+/** Dump all statistics data to the registered outputs */
+void dump();
+void reset();
+void enable();
+bool enabled();
+
 /**
- * Enable the statistics package.  Before the statistics package is
- * enabled, all statistics must be created and initialized and once
- * the package is enabled, no more statistics can be created.
+ * Register reset and dump handlers.  These are the functions which
+ * will actually perform the whole statistics reset/dump actions
+ * including processing the reset/dump callbacks
  */
-void enable();
+typedef void (*Handler)();
+
+void registerHandlers(Handler reset_handler, Handler dump_handler);
 
 /**
- * Prepare all stats for data access.  This must be done before
- * dumping and serialization.
+ * Register a callback that should be called whenever statistics are
+ * reset
  */
-void prepare();
+void registerResetCallback(Callback *cb);
 
 /**
- * Dump all statistics data to the registered outputs
+ * Register a callback that should be called whenever statistics are
+ * about to be dumped
  */
-void dump();
+void registerDumpCallback(Callback *cb);
 
 /**
- * Reset all statistics to the base state
+ * Process all the callbacks in the reset callbacks queue
  */
-void reset();
+void processResetQueue();
+
 /**
- * Register a callback that should be called whenever statistics are
- * reset
+ * Process all the callbacks in the dump callbacks queue
  */
-void registerResetCallback(Callback *cb);
+void processDumpQueue();
 
 std::list<Info *> &statsList();
 
-/* namespace Stats */ }
+typedef std::map<const void *, Info *> MapType;
+MapType &statsMap();
+
+typedef std::map<std::string, Info *> NameMapType;
+NameMapType &nameMap();
+
+bool validateStatName(const std::string &name);
+
+} // namespace Stats
+
+void debugDumpStats();
 
 #endif // __BASE_STATISTICS_HH__