summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMonty Brandenberg <monty@lindenlab.com>2010-10-22 09:10:44 -0700
committerMonty Brandenberg <monty@lindenlab.com>2010-10-22 09:10:44 -0700
commit90168d285bfa0250cab6709eb3be8d6f2517011a (patch)
tree0e21b181e306fed41993ac1de26752e8ca0aedce
parentc7b082eac204380d805350ab73ffea470ee4f56a (diff)
ESC-108 Develop support classes for numerical collection
Stuff moved over and adapted from simulator code. Basic, simple counters and min/max/mean accumulators.
-rw-r--r--indra/newview/CMakeLists.txt5
-rw-r--r--indra/newview/llsimplestat.h140
-rw-r--r--indra/newview/tests/llsimplestat_test.cpp428
3 files changed, 573 insertions, 0 deletions
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 1f4302d870..0c4d2aaca6 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -1925,6 +1925,11 @@ if (LL_TESTS)
"${test_libs}"
)
+ LL_ADD_INTEGRATION_TEST(llsimplestat
+ ""
+ "${test_libs}"
+ )
+
#ADD_VIEWER_BUILD_TEST(llmemoryview viewer)
#ADD_VIEWER_BUILD_TEST(llagentaccess viewer)
#ADD_VIEWER_BUILD_TEST(llworldmap viewer)
diff --git a/indra/newview/llsimplestat.h b/indra/newview/llsimplestat.h
new file mode 100644
index 0000000000..f8f4be0390
--- /dev/null
+++ b/indra/newview/llsimplestat.h
@@ -0,0 +1,140 @@
+/**
+ * @file llsimplestat.h
+ * @brief Runtime statistics accumulation.
+ *
+ * $LicenseInfo:firstyear=2010&license=viewergpl$
+ *
+ * Copyright (c) 2010, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_SIMPLESTAT_H
+#define LL_SIMPLESTAT_H
+
+// History
+//
+// The original source for this code is the server repositories'
+// llcommon/llstat.h file. This particular code was added after the
+// viewer/server code schism but before the effort to convert common
+// code to libraries was complete. Rather than add to merge issues,
+// the needed code was cut'n'pasted into this new header as it isn't
+// too awful a burden. Post-modularization, we can look at removing
+// this redundancy.
+
+
+/**
+ * @class LLSimpleStatCounter
+ * @brief Just counts events.
+ *
+ * Really not needed but have a pattern in mind in the future.
+ * Interface limits what can be done at that's just fine.
+ *
+ * *TODO: Update/transfer unit tests
+ * Unit tests: indra/test/llcommon_llstat_tut.cpp
+ */
+class LLSimpleStatCounter
+{
+public:
+ inline LLSimpleStatCounter() { reset(); }
+ // Default destructor and assignment operator are valid
+
+ inline void reset() { mCount = 0; }
+
+ inline U32 operator++() { return ++mCount; }
+
+ inline U32 getCount() const { return mCount; }
+
+protected:
+ U32 mCount;
+};
+
+
+/**
+ * @class LLSimpleStatMMM
+ * @brief Templated collector of min, max and mean data for stats.
+ *
+ * Fed a stream of data samples, keeps a running account of the
+ * min, max and mean seen since construction or the last reset()
+ * call. A freshly-constructed or reset instance returns counts
+ * and values of zero.
+ *
+ * Overflows and underflows (integer, inf or -inf) and NaN's
+ * are the caller's problem. As is loss of precision when
+ * the running sum's exponent (when parameterized by a floating
+ * point of some type) differs from a given data sample's.
+ *
+ * Unit tests: indra/test/llcommon_llstat_tut.cpp
+ */
+template <typename VALUE_T = F32>
+class LLSimpleStatMMM
+{
+public:
+ typedef VALUE_T Value;
+
+public:
+ LLSimpleStatMMM() { reset(); }
+ // Default destructor and assignment operator are valid
+
+ /**
+ * Resets the object returning all counts and derived
+ * values back to zero.
+ */
+ void reset()
+ {
+ mCount = 0;
+ mMin = Value(0);
+ mMax = Value(0);
+ mTotal = Value(0);
+ }
+
+ void record(Value v)
+ {
+ if (mCount)
+ {
+ mMin = llmin(mMin, v);
+ mMax = llmax(mMax, v);
+ }
+ else
+ {
+ mMin = v;
+ mMax = v;
+ }
+ mTotal += v;
+ ++mCount;
+ }
+
+ inline U32 getCount() const { return mCount; }
+ inline Value getMin() const { return mMin; }
+ inline Value getMax() const { return mMax; }
+ inline Value getMean() const { return mCount ? mTotal / mCount : mTotal; }
+
+protected:
+ U32 mCount;
+ Value mMin;
+ Value mMax;
+ Value mTotal;
+};
+
+#endif // LL_SIMPLESTAT_H
diff --git a/indra/newview/tests/llsimplestat_test.cpp b/indra/newview/tests/llsimplestat_test.cpp
new file mode 100644
index 0000000000..5efc9cf857
--- /dev/null
+++ b/indra/newview/tests/llsimplestat_test.cpp
@@ -0,0 +1,428 @@
+/**
+ * @file llsimplestats_test.cpp
+ * @date 2010-10-22
+ * @brief Test cases for some of llsimplestat.h
+ *
+ * $LicenseInfo:firstyear=2010&license=viewergpl$
+ *
+ * Copyright (c) 2010, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include <tut/tut.hpp>
+
+#include "lltut.h"
+#include "../llsimplestat.h"
+#include "llsd.h"
+#include "llmath.h"
+
+// @brief Used as a pointer cast type to get access to LLSimpleStatCounter
+class TutStatCounter: public LLSimpleStatCounter
+{
+public:
+ TutStatCounter(); // Not defined
+ ~TutStatCounter(); // Not defined
+ void operator=(const TutStatCounter &); // Not defined
+
+ void setRawCount(U32 c) { mCount = c; }
+ U32 getRawCount() const { return mCount; }
+};
+
+
+namespace tut
+{
+ struct stat_counter_index
+ {};
+ typedef test_group<stat_counter_index> stat_counter_index_t;
+ typedef stat_counter_index_t::object stat_counter_index_object_t;
+ tut::stat_counter_index_t tut_stat_counter_index("stat_counter_test");
+
+ // Testing LLSimpleStatCounter's external interface
+ template<> template<>
+ void stat_counter_index_object_t::test<1>()
+ {
+ LLSimpleStatCounter c1;
+ ensure("Initialized counter is zero", (0 == c1.getCount()));
+
+ ensure("Counter increment return is 1", (1 == ++c1));
+ ensure("Counter increment return is 2", (2 == ++c1));
+
+ ensure("Current counter is 2", (2 == c1.getCount()));
+
+ c1.reset();
+ ensure("Counter is 0 after reset", (0 == c1.getCount()));
+
+ ensure("Counter increment return is 1", (1 == ++c1));
+ }
+
+ // Testing LLSimpleStatCounter's internal state
+ template<> template<>
+ void stat_counter_index_object_t::test<2>()
+ {
+ LLSimpleStatCounter c1;
+ TutStatCounter * tc1 = (TutStatCounter *) &c1;
+
+ ensure("Initialized private counter is zero", (0 == tc1->getRawCount()));
+
+ ++c1;
+ ++c1;
+
+ ensure("Current private counter is 2", (2 == tc1->getRawCount()));
+
+ c1.reset();
+ ensure("Raw counter is 0 after reset", (0 == tc1->getRawCount()));
+ }
+
+ // Testing LLSimpleStatCounter's wrapping behavior
+ template<> template<>
+ void stat_counter_index_object_t::test<3>()
+ {
+ LLSimpleStatCounter c1;
+ TutStatCounter * tc1 = (TutStatCounter *) &c1;
+
+ tc1->setRawCount(U32_MAX);
+ ensure("Initialized private counter is zero", (U32_MAX == c1.getCount()));
+
+ ensure("Increment of max value wraps to 0", (0 == ++c1));
+ }
+
+ // Testing LLSimpleStatMMM's external behavior
+ template<> template<>
+ void stat_counter_index_object_t::test<4>()
+ {
+ LLSimpleStatMMM<> m1;
+ typedef LLSimpleStatMMM<>::Value lcl_float;
+ lcl_float zero(0);
+
+ // Freshly-constructed
+ ensure("Constructed MMM<> has 0 count", (0 == m1.getCount()));
+ ensure("Constructed MMM<> has 0 min", (zero == m1.getMin()));
+ ensure("Constructed MMM<> has 0 max", (zero == m1.getMax()));
+ ensure("Constructed MMM<> has 0 mean no div-by-zero", (zero == m1.getMean()));
+
+ // Single insert
+ m1.record(1.0);
+ ensure("Single insert MMM<> has 1 count", (1 == m1.getCount()));
+ ensure("Single insert MMM<> has 1.0 min", (1.0 == m1.getMin()));
+ ensure("Single insert MMM<> has 1.0 max", (1.0 == m1.getMax()));
+ ensure("Single insert MMM<> has 1.0 mean", (1.0 == m1.getMean()));
+
+ // Second insert
+ m1.record(3.0);
+ ensure("2nd insert MMM<> has 2 count", (2 == m1.getCount()));
+ ensure("2nd insert MMM<> has 1.0 min", (1.0 == m1.getMin()));
+ ensure("2nd insert MMM<> has 3.0 max", (3.0 == m1.getMax()));
+ ensure_approximately_equals("2nd insert MMM<> has 2.0 mean", m1.getMean(), lcl_float(2.0), 1);
+
+ // Third insert
+ m1.record(5.0);
+ ensure("3rd insert MMM<> has 3 count", (3 == m1.getCount()));
+ ensure("3rd insert MMM<> has 1.0 min", (1.0 == m1.getMin()));
+ ensure("3rd insert MMM<> has 5.0 max", (5.0 == m1.getMax()));
+ ensure_approximately_equals("3rd insert MMM<> has 3.0 mean", m1.getMean(), lcl_float(3.0), 1);
+
+ // Fourth insert
+ m1.record(1000000.0);
+ ensure("4th insert MMM<> has 4 count", (4 == m1.getCount()));
+ ensure("4th insert MMM<> has 1.0 min", (1.0 == m1.getMin()));
+ ensure("4th insert MMM<> has 100000.0 max", (1000000.0 == m1.getMax()));
+ ensure_approximately_equals("4th insert MMM<> has 250002.0 mean", m1.getMean(), lcl_float(250002.0), 1);
+
+ // Reset
+ m1.reset();
+ ensure("Reset MMM<> has 0 count", (0 == m1.getCount()));
+ ensure("Reset MMM<> has 0 min", (zero == m1.getMin()));
+ ensure("Reset MMM<> has 0 max", (zero == m1.getMax()));
+ ensure("Reset MMM<> has 0 mean no div-by-zero", (zero == m1.getMean()));
+ }
+
+ // Testing LLSimpleStatMMM's response to large values
+ template<> template<>
+ void stat_counter_index_object_t::test<5>()
+ {
+ LLSimpleStatMMM<> m1;
+ typedef LLSimpleStatMMM<>::Value lcl_float;
+ lcl_float zero(0);
+
+ // Insert overflowing values
+ const lcl_float bignum(F32_MAX / 2);
+
+ m1.record(bignum);
+ m1.record(bignum);
+ m1.record(bignum);
+ m1.record(bignum);
+ m1.record(bignum);
+ m1.record(bignum);
+ m1.record(bignum);
+ m1.record(zero);
+
+ ensure("Overflowed MMM<> has 8 count", (8 == m1.getCount()));
+ ensure("Overflowed MMM<> has 0 min", (zero == m1.getMin()));
+ ensure("Overflowed MMM<> has huge max", (bignum == m1.getMax()));
+ ensure("Overflowed MMM<> has fetchable mean", (1.0 == m1.getMean() || true));
+ // We should be infinte but not interested in proving the IEEE standard here.
+ LLSD sd1(m1.getMean());
+ // std::cout << "Thingy: " << m1.getMean() << " and as LLSD: " << sd1 << std::endl;
+ ensure("Overflowed MMM<> produces LLSDable Real", (sd1.isReal()));
+ }
+
+ // Testing LLSimpleStatMMM<F32>'s external behavior
+ template<> template<>
+ void stat_counter_index_object_t::test<6>()
+ {
+ LLSimpleStatMMM<F32> m1;
+ typedef LLSimpleStatMMM<F32>::Value lcl_float;
+ lcl_float zero(0);
+
+ // Freshly-constructed
+ ensure("Constructed MMM<F32> has 0 count", (0 == m1.getCount()));
+ ensure("Constructed MMM<F32> has 0 min", (zero == m1.getMin()));
+ ensure("Constructed MMM<F32> has 0 max", (zero == m1.getMax()));
+ ensure("Constructed MMM<F32> has 0 mean no div-by-zero", (zero == m1.getMean()));
+
+ // Single insert
+ m1.record(1.0);
+ ensure("Single insert MMM<F32> has 1 count", (1 == m1.getCount()));
+ ensure("Single insert MMM<F32> has 1.0 min", (1.0 == m1.getMin()));
+ ensure("Single insert MMM<F32> has 1.0 max", (1.0 == m1.getMax()));
+ ensure("Single insert MMM<F32> has 1.0 mean", (1.0 == m1.getMean()));
+
+ // Second insert
+ m1.record(3.0);
+ ensure("2nd insert MMM<F32> has 2 count", (2 == m1.getCount()));
+ ensure("2nd insert MMM<F32> has 1.0 min", (1.0 == m1.getMin()));
+ ensure("2nd insert MMM<F32> has 3.0 max", (3.0 == m1.getMax()));
+ ensure_approximately_equals("2nd insert MMM<F32> has 2.0 mean", m1.getMean(), lcl_float(2.0), 1);
+
+ // Third insert
+ m1.record(5.0);
+ ensure("3rd insert MMM<F32> has 3 count", (3 == m1.getCount()));
+ ensure("3rd insert MMM<F32> has 1.0 min", (1.0 == m1.getMin()));
+ ensure("3rd insert MMM<F32> has 5.0 max", (5.0 == m1.getMax()));
+ ensure_approximately_equals("3rd insert MMM<F32> has 3.0 mean", m1.getMean(), lcl_float(3.0), 1);
+
+ // Fourth insert
+ m1.record(1000000.0);
+ ensure("4th insert MMM<F32> has 4 count", (4 == m1.getCount()));
+ ensure("4th insert MMM<F32> has 1.0 min", (1.0 == m1.getMin()));
+ ensure("4th insert MMM<F32> has 1000000.0 max", (1000000.0 == m1.getMax()));
+ ensure_approximately_equals("4th insert MMM<F32> has 250002.0 mean", m1.getMean(), lcl_float(250002.0), 1);
+
+ // Reset
+ m1.reset();
+ ensure("Reset MMM<F32> has 0 count", (0 == m1.getCount()));
+ ensure("Reset MMM<F32> has 0 min", (zero == m1.getMin()));
+ ensure("Reset MMM<F32> has 0 max", (zero == m1.getMax()));
+ ensure("Reset MMM<F32> has 0 mean no div-by-zero", (zero == m1.getMean()));
+ }
+
+ // Testing LLSimpleStatMMM's response to large values
+ template<> template<>
+ void stat_counter_index_object_t::test<7>()
+ {
+ LLSimpleStatMMM<F32> m1;
+ typedef LLSimpleStatMMM<F32>::Value lcl_float;
+ lcl_float zero(0);
+
+ // Insert overflowing values
+ const lcl_float bignum(F32_MAX / 2);
+
+ m1.record(bignum);
+ m1.record(bignum);
+ m1.record(bignum);
+ m1.record(bignum);
+ m1.record(bignum);
+ m1.record(bignum);
+ m1.record(bignum);
+ m1.record(zero);
+
+ ensure("Overflowed MMM<F32> has 8 count", (8 == m1.getCount()));
+ ensure("Overflowed MMM<F32> has 0 min", (zero == m1.getMin()));
+ ensure("Overflowed MMM<F32> has huge max", (bignum == m1.getMax()));
+ ensure("Overflowed MMM<F32> has fetchable mean", (1.0 == m1.getMean() || true));
+ // We should be infinte but not interested in proving the IEEE standard here.
+ LLSD sd1(m1.getMean());
+ // std::cout << "Thingy: " << m1.getMean() << " and as LLSD: " << sd1 << std::endl;
+ ensure("Overflowed MMM<F32> produces LLSDable Real", (sd1.isReal()));
+ }
+
+ // Testing LLSimpleStatMMM<F64>'s external behavior
+ template<> template<>
+ void stat_counter_index_object_t::test<8>()
+ {
+ LLSimpleStatMMM<F64> m1;
+ typedef LLSimpleStatMMM<F64>::Value lcl_float;
+ lcl_float zero(0);
+
+ // Freshly-constructed
+ ensure("Constructed MMM<F64> has 0 count", (0 == m1.getCount()));
+ ensure("Constructed MMM<F64> has 0 min", (zero == m1.getMin()));
+ ensure("Constructed MMM<F64> has 0 max", (zero == m1.getMax()));
+ ensure("Constructed MMM<F64> has 0 mean no div-by-zero", (zero == m1.getMean()));
+
+ // Single insert
+ m1.record(1.0);
+ ensure("Single insert MMM<F64> has 1 count", (1 == m1.getCount()));
+ ensure("Single insert MMM<F64> has 1.0 min", (1.0 == m1.getMin()));
+ ensure("Single insert MMM<F64> has 1.0 max", (1.0 == m1.getMax()));
+ ensure("Single insert MMM<F64> has 1.0 mean", (1.0 == m1.getMean()));
+
+ // Second insert
+ m1.record(3.0);
+ ensure("2nd insert MMM<F64> has 2 count", (2 == m1.getCount()));
+ ensure("2nd insert MMM<F64> has 1.0 min", (1.0 == m1.getMin()));
+ ensure("2nd insert MMM<F64> has 3.0 max", (3.0 == m1.getMax()));
+ ensure_approximately_equals("2nd insert MMM<F64> has 2.0 mean", m1.getMean(), lcl_float(2.0), 1);
+
+ // Third insert
+ m1.record(5.0);
+ ensure("3rd insert MMM<F64> has 3 count", (3 == m1.getCount()));
+ ensure("3rd insert MMM<F64> has 1.0 min", (1.0 == m1.getMin()));
+ ensure("3rd insert MMM<F64> has 5.0 max", (5.0 == m1.getMax()));
+ ensure_approximately_equals("3rd insert MMM<F64> has 3.0 mean", m1.getMean(), lcl_float(3.0), 1);
+
+ // Fourth insert
+ m1.record(1000000.0);
+ ensure("4th insert MMM<F64> has 4 count", (4 == m1.getCount()));
+ ensure("4th insert MMM<F64> has 1.0 min", (1.0 == m1.getMin()));
+ ensure("4th insert MMM<F64> has 1000000.0 max", (1000000.0 == m1.getMax()));
+ ensure_approximately_equals("4th insert MMM<F64> has 250002.0 mean", m1.getMean(), lcl_float(250002.0), 1);
+
+ // Reset
+ m1.reset();
+ ensure("Reset MMM<F64> has 0 count", (0 == m1.getCount()));
+ ensure("Reset MMM<F64> has 0 min", (zero == m1.getMin()));
+ ensure("Reset MMM<F64> has 0 max", (zero == m1.getMax()));
+ ensure("Reset MMM<F64> has 0 mean no div-by-zero", (zero == m1.getMean()));
+ }
+
+ // Testing LLSimpleStatMMM's response to large values
+ template<> template<>
+ void stat_counter_index_object_t::test<9>()
+ {
+ LLSimpleStatMMM<F64> m1;
+ typedef LLSimpleStatMMM<F64>::Value lcl_float;
+ lcl_float zero(0);
+
+ // Insert overflowing values
+ const lcl_float bignum(F64_MAX / 2);
+
+ m1.record(bignum);
+ m1.record(bignum);
+ m1.record(bignum);
+ m1.record(bignum);
+ m1.record(bignum);
+ m1.record(bignum);
+ m1.record(bignum);
+ m1.record(zero);
+
+ ensure("Overflowed MMM<F64> has 8 count", (8 == m1.getCount()));
+ ensure("Overflowed MMM<F64> has 0 min", (zero == m1.getMin()));
+ ensure("Overflowed MMM<F64> has huge max", (bignum == m1.getMax()));
+ ensure("Overflowed MMM<F64> has fetchable mean", (1.0 == m1.getMean() || true));
+ // We should be infinte but not interested in proving the IEEE standard here.
+ LLSD sd1(m1.getMean());
+ // std::cout << "Thingy: " << m1.getMean() << " and as LLSD: " << sd1 << std::endl;
+ ensure("Overflowed MMM<F64> produces LLSDable Real", (sd1.isReal()));
+ }
+
+ // Testing LLSimpleStatMMM<U64>'s external behavior
+ template<> template<>
+ void stat_counter_index_object_t::test<10>()
+ {
+ LLSimpleStatMMM<U64> m1;
+ typedef LLSimpleStatMMM<U64>::Value lcl_int;
+ lcl_int zero(0);
+
+ // Freshly-constructed
+ ensure("Constructed MMM<U64> has 0 count", (0 == m1.getCount()));
+ ensure("Constructed MMM<U64> has 0 min", (zero == m1.getMin()));
+ ensure("Constructed MMM<U64> has 0 max", (zero == m1.getMax()));
+ ensure("Constructed MMM<U64> has 0 mean no div-by-zero", (zero == m1.getMean()));
+
+ // Single insert
+ m1.record(1);
+ ensure("Single insert MMM<U64> has 1 count", (1 == m1.getCount()));
+ ensure("Single insert MMM<U64> has 1 min", (1 == m1.getMin()));
+ ensure("Single insert MMM<U64> has 1 max", (1 == m1.getMax()));
+ ensure("Single insert MMM<U64> has 1 mean", (1 == m1.getMean()));
+
+ // Second insert
+ m1.record(3);
+ ensure("2nd insert MMM<U64> has 2 count", (2 == m1.getCount()));
+ ensure("2nd insert MMM<U64> has 1 min", (1 == m1.getMin()));
+ ensure("2nd insert MMM<U64> has 3 max", (3 == m1.getMax()));
+ ensure("2nd insert MMM<U64> has 2 mean", (2 == m1.getMean()));
+
+ // Third insert
+ m1.record(5);
+ ensure("3rd insert MMM<U64> has 3 count", (3 == m1.getCount()));
+ ensure("3rd insert MMM<U64> has 1 min", (1 == m1.getMin()));
+ ensure("3rd insert MMM<U64> has 5 max", (5 == m1.getMax()));
+ ensure("3rd insert MMM<U64> has 3 mean", (3 == m1.getMean()));
+
+ // Fourth insert
+ m1.record(U64L(1000000000000));
+ ensure("4th insert MMM<U64> has 4 count", (4 == m1.getCount()));
+ ensure("4th insert MMM<U64> has 1 min", (1 == m1.getMin()));
+ ensure("4th insert MMM<U64> has 1000000000000ULL max", (U64L(1000000000000) == m1.getMax()));
+ ensure("4th insert MMM<U64> has 250000000002ULL mean", (U64L( 250000000002) == m1.getMean()));
+
+ // Reset
+ m1.reset();
+ ensure("Reset MMM<U64> has 0 count", (0 == m1.getCount()));
+ ensure("Reset MMM<U64> has 0 min", (zero == m1.getMin()));
+ ensure("Reset MMM<U64> has 0 max", (zero == m1.getMax()));
+ ensure("Reset MMM<U64> has 0 mean no div-by-zero", (zero == m1.getMean()));
+ }
+
+ // Testing LLSimpleStatMMM's response to large values
+ template<> template<>
+ void stat_counter_index_object_t::test<11>()
+ {
+ LLSimpleStatMMM<U64> m1;
+ typedef LLSimpleStatMMM<U64>::Value lcl_int;
+ lcl_int zero(0);
+
+ // Insert overflowing values
+ const lcl_int bignum(U64L(0xffffffffffffffff) / 2);
+
+ m1.record(bignum);
+ m1.record(bignum);
+ m1.record(bignum);
+ m1.record(bignum);
+ m1.record(bignum);
+ m1.record(bignum);
+ m1.record(bignum);
+ m1.record(zero);
+
+ ensure("Overflowed MMM<U64> has 8 count", (8 == m1.getCount()));
+ ensure("Overflowed MMM<U64> has 0 min", (zero == m1.getMin()));
+ ensure("Overflowed MMM<U64> has huge max", (bignum == m1.getMax()));
+ ensure("Overflowed MMM<U64> has fetchable mean", (zero == m1.getMean() || true));
+ }
+}