summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/base/statistics.hh185
-rw-r--r--src/base/stats/info.hh14
-rw-r--r--src/base/stats/output.hh2
-rw-r--r--src/base/stats/text.cc86
-rw-r--r--src/base/stats/text.hh1
-rw-r--r--src/base/stats/types.hh3
-rw-r--r--src/python/swig/stats.i1
-rw-r--r--src/unittest/stattest.cc11
8 files changed, 303 insertions, 0 deletions
diff --git a/src/base/statistics.hh b/src/base/statistics.hh
index cf8349d24..d98c79414 100644
--- a/src/base/statistics.hh
+++ b/src/base/statistics.hh
@@ -56,6 +56,7 @@
#include <functional>
#include <iosfwd>
#include <list>
+#include <map>
#include <string>
#include <vector>
@@ -2608,6 +2609,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
diff --git a/src/base/stats/info.hh b/src/base/stats/info.hh
index fa7c8cc3d..2c5b44a38 100644
--- a/src/base/stats/info.hh
+++ b/src/base/stats/info.hh
@@ -234,6 +234,20 @@ class FormulaInfo : public VectorInfo
virtual std::string str() const = 0;
};
+/** Data structure of sparse histogram */
+struct SparseHistData
+{
+ MCounter cmap;
+ Counter samples;
+};
+
+
+class SparseHistInfo : public Info
+{
+ public:
+ /** Local storage for the entry values, used for printing. */
+ SparseHistData data;
+};
} // namespace Stats
diff --git a/src/base/stats/output.hh b/src/base/stats/output.hh
index 26c4c5bbd..9cd33a5f9 100644
--- a/src/base/stats/output.hh
+++ b/src/base/stats/output.hh
@@ -43,6 +43,7 @@ class DistInfo;
class VectorDistInfo;
class Vector2dInfo;
class FormulaInfo;
+class SparseHistInfo; // Sparse histogram
struct Output
{
@@ -57,6 +58,7 @@ struct Output
virtual void visit(const VectorDistInfo &info) = 0;
virtual void visit(const Vector2dInfo &info) = 0;
virtual void visit(const FormulaInfo &info) = 0;
+ virtual void visit(const SparseHistInfo &info) = 0; // Sparse histogram
};
} // namespace Stats
diff --git a/src/base/stats/text.cc b/src/base/stats/text.cc
index 45d59ff29..f8471f1a1 100644
--- a/src/base/stats/text.cc
+++ b/src/base/stats/text.cc
@@ -581,6 +581,92 @@ Text::visit(const FormulaInfo &info)
visit((const VectorInfo &)info);
}
+/*
+ This struct implements the output methods for the sparse
+ histogram stat
+*/
+struct SparseHistPrint
+{
+ string name;
+ string separatorString;
+ string desc;
+ Flags flags;
+ bool descriptions;
+ int precision;
+
+ const SparseHistData &data;
+
+ SparseHistPrint(const Text *text, const SparseHistInfo &info);
+ void init(const Text *text, const Info &info);
+ void operator()(ostream &stream) const;
+};
+
+/* Call initialization function */
+SparseHistPrint::SparseHistPrint(const Text *text, const SparseHistInfo &info)
+ : data(info.data)
+{
+ init(text, info);
+}
+
+/* Initialization function */
+void
+SparseHistPrint::init(const Text *text, const Info &info)
+{
+ name = info.name;
+ separatorString = info.separatorString;
+ desc = info.desc;
+ flags = info.flags;
+ precision = info.precision;
+ descriptions = text->descriptions;
+}
+
+/* Grab data from map and write to output stream */
+void
+SparseHistPrint::operator()(ostream &stream) const
+{
+ string base = name + separatorString;
+
+ ScalarPrint print;
+ print.precision = precision;
+ print.flags = flags;
+ print.descriptions = descriptions;
+ print.desc = desc;
+ print.pdf = NAN;
+ print.cdf = NAN;
+
+ print.name = base + "samples";
+ print.value = data.samples;
+ print(stream);
+
+ MCounter::const_iterator it;
+ for (it = data.cmap.begin(); it != data.cmap.end(); it++) {
+ stringstream namestr;
+ namestr << base;
+
+ namestr <<(*it).first;
+ print.name = namestr.str();
+ print.value = (*it).second;
+ print(stream);
+ }
+
+ print.pdf = NAN;
+ print.cdf = NAN;
+
+ print.name = base + "total";
+ print.value = total;
+ print(stream);
+}
+
+void
+Text::visit(const SparseHistInfo &info)
+{
+ if (noOutput(info))
+ return;
+
+ SparseHistPrint print(this, info);
+ print(*stream);
+}
+
Output *
initText(const string &filename, bool desc)
{
diff --git a/src/base/stats/text.hh b/src/base/stats/text.hh
index 24abaac97..7f7edaa91 100644
--- a/src/base/stats/text.hh
+++ b/src/base/stats/text.hh
@@ -67,6 +67,7 @@ class Text : public Output
virtual void visit(const VectorDistInfo &info);
virtual void visit(const Vector2dInfo &info);
virtual void visit(const FormulaInfo &info);
+ virtual void visit(const SparseHistInfo &info);
// Implement Output
virtual bool valid() const;
diff --git a/src/base/stats/types.hh b/src/base/stats/types.hh
index 9faa8d33d..831cc6db5 100644
--- a/src/base/stats/types.hh
+++ b/src/base/stats/types.hh
@@ -32,6 +32,7 @@
#define __BASE_STATS_TYPES_HH__
#include <limits>
+#include <map>
#include <vector>
#include "base/types.hh"
@@ -42,6 +43,8 @@ namespace Stats {
typedef double Counter;
/** vector of counters. */
typedef std::vector<Counter> VCounter;
+/** map of counters */
+typedef std::map<Counter, int> MCounter;
typedef std::numeric_limits<Counter> CounterLimits;
diff --git a/src/python/swig/stats.i b/src/python/swig/stats.i
index 0213d5c01..87810d305 100644
--- a/src/python/swig/stats.i
+++ b/src/python/swig/stats.i
@@ -137,6 +137,7 @@ template <class T> T cast_info(Info *info);
%template(dynamic_VectorDistInfo) cast_info<VectorDistInfo *>;
%template(dynamic_Vector2dInfo) cast_info<Vector2dInfo *>;
%template(dynamic_FormulaInfo) cast_info<FormulaInfo *>;
+%template(dynamic_SparseHistInfo) cast_info<SparseHistInfo *>;
void initSimStats();
Output *initText(const std::string &filename, bool desc);
diff --git a/src/unittest/stattest.cc b/src/unittest/stattest.cc
index c5e39888d..ccce2173b 100644
--- a/src/unittest/stattest.cc
+++ b/src/unittest/stattest.cc
@@ -92,6 +92,7 @@ struct StatTest
Histogram h10;
Histogram h11;
Histogram h12;
+ SparseHistogram sh1;
Formula f1;
Formula f2;
@@ -316,6 +317,12 @@ StatTest::init()
.desc("this is histogram 12")
;
+ sh1
+ .init(0)
+ .name("SparseHistogram1")
+ .desc("this is sparse histogram 1")
+ ;
+
f1
.name("Formula1")
.desc("this is formula 1")
@@ -623,4 +630,8 @@ StatTest::run()
h11.sample(i);
h12.sample(i);
}
+
+ for (int i = 0; i < 1000; i++) {
+ sh1.sample(random() % 10000);
+ }
}