Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r72045 - in trunk: boost/accumulators boost/accumulators/statistics libs/accumulators/doc libs/accumulators/test
From: eric_at_[hidden]
Date: 2011-05-19 08:06:14


Author: eric_niebler
Date: 2011-05-19 08:06:12 EDT (Thu, 19 May 2011)
New Revision: 72045
URL: http://svn.boost.org/trac/boost/changeset/72045

Log:
add kahan sum, fixes #4471
Added:
   trunk/boost/accumulators/statistics/sum_kahan.hpp (contents, props changed)
   trunk/boost/accumulators/statistics/weighted_sum_kahan.hpp (contents, props changed)
   trunk/libs/accumulators/test/sum_kahan.cpp (contents, props changed)
   trunk/libs/accumulators/test/weighted_sum_kahan.cpp (contents, props changed)
Text files modified:
   trunk/boost/accumulators/accumulators_fwd.hpp | 3 ++
   trunk/boost/accumulators/statistics.hpp | 2 +
   trunk/boost/accumulators/statistics_fwd.hpp | 13 +++++++++
   trunk/libs/accumulators/doc/accumulators.qbk | 53 +++++++++++++++++++++++++++++++++------
   trunk/libs/accumulators/test/Jamfile.v2 | 3 +
   5 files changed, 65 insertions(+), 9 deletions(-)

Modified: trunk/boost/accumulators/accumulators_fwd.hpp
==============================================================================
--- trunk/boost/accumulators/accumulators_fwd.hpp (original)
+++ trunk/boost/accumulators/accumulators_fwd.hpp 2011-05-19 08:06:12 EDT (Thu, 19 May 2011)
@@ -48,6 +48,9 @@
 # define BOOST_ACCUMULATORS_PROTO_DISABLE_IF_IS_CONST(T)
 #endif
 
+#define BOOST_ACCUMULATORS_GCC_VERSION \
+ (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
+
 namespace boost { namespace accumulators
 {
 

Modified: trunk/boost/accumulators/statistics.hpp
==============================================================================
--- trunk/boost/accumulators/statistics.hpp (original)
+++ trunk/boost/accumulators/statistics.hpp 2011-05-19 08:06:12 EDT (Thu, 19 May 2011)
@@ -30,6 +30,7 @@
 #include <boost/accumulators/statistics/skewness.hpp>
 #include <boost/accumulators/statistics/stats.hpp>
 #include <boost/accumulators/statistics/sum.hpp>
+#include <boost/accumulators/statistics/sum_kahan.hpp>
 #include <boost/accumulators/statistics/tail.hpp>
 #include <boost/accumulators/statistics/tail_quantile.hpp>
 #include <boost/accumulators/statistics/tail_mean.hpp>
@@ -48,6 +49,7 @@
 #include <boost/accumulators/statistics/weighted_p_square_quantile.hpp>
 #include <boost/accumulators/statistics/weighted_skewness.hpp>
 #include <boost/accumulators/statistics/weighted_sum.hpp>
+#include <boost/accumulators/statistics/weighted_sum_kahan.hpp>
 #include <boost/accumulators/statistics/weighted_tail_quantile.hpp>
 #include <boost/accumulators/statistics/weighted_tail_mean.hpp>
 #include <boost/accumulators/statistics/weighted_tail_variate_means.hpp>

Added: trunk/boost/accumulators/statistics/sum_kahan.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/accumulators/statistics/sum_kahan.hpp 2011-05-19 08:06:12 EDT (Thu, 19 May 2011)
@@ -0,0 +1,188 @@
+///////////////////////////////////////////////////////////////////////////////
+// sum_kahan.hpp
+//
+// Copyright 2010 Gaetano Mendola, 2011 Simon West. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_ACCUMULATORS_STATISTICS_SUM_KAHAN_HPP_EAN_26_07_2010
+#define BOOST_ACCUMULATORS_STATISTICS_SUM_KAHAN_HPP_EAN_26_07_2010
+
+#include <boost/accumulators/framework/accumulator_base.hpp>
+#include <boost/accumulators/framework/parameters/sample.hpp>
+#include <boost/accumulators/statistics_fwd.hpp>
+#include <boost/accumulators/statistics/sum.hpp>
+#include <boost/accumulators/statistics/weighted_sum_kahan.hpp>
+#include <boost/numeric/conversion/cast.hpp>
+
+namespace boost { namespace accumulators
+{
+
+namespace impl
+{
+
+#if _MSC_VER > 1400
+# pragma float_control(push)
+# pragma float_control(precise, on)
+#endif
+
+template<typename Sample, typename Tag>
+struct sum_kahan_impl
+ : accumulator_base
+{
+ typedef Sample result_type;
+
+ ////////////////////////////////////////////////////////////////////////////
+ // sum_kahan_impl
+ /**
+ @brief Kahan summation algorithm
+
+ The Kahan summation algorithm reduces the numerical error obtained with standard
+ sequential sum.
+
+ */
+ template<typename Args>
+ sum_kahan_impl(Args const & args)
+ : sum(args[parameter::keyword<Tag>::get() | Sample()]),
+ compensation(boost::numeric_cast<Sample>(0.0))
+ {
+ }
+
+ template<typename Args>
+ void
+#if BOOST_ACCUMULATORS_GCC_VERSION > 40305
+# __attribute__((optimize("fno-associative-math")))
+#endif
+ operator ()(Args const & args)
+ {
+ const Sample myTmp1 = args[parameter::keyword<Tag>::get()] - this->compensation;
+ const Sample myTmp2 = this->sum + myTmp1;
+ this->compensation = (myTmp2 - this->sum) - myTmp1;
+ this->sum = myTmp2;
+ };
+
+ result_type result(dont_care) const
+ {
+ return this->sum;
+ }
+
+private:
+ Sample sum;
+ Sample compensation;
+};
+
+#if _MSC_VER > 1400
+# pragma float_control(pop)
+#endif
+
+} // namespace impl
+
+///////////////////////////////////////////////////////////////////////////////
+// tag::sum_kahan
+// tag::sum_of_weights_kahan
+// tag::sum_of_variates_kahan
+//
+namespace tag
+{
+
+ struct sum_kahan
+ : depends_on<>
+ {
+ /// INTERNAL ONLY
+ ///
+ typedef impl::sum_kahan_impl< mpl::_1, tag::sample > impl;
+ };
+
+ struct sum_of_weights_kahan
+ : depends_on<>
+ {
+ typedef mpl::true_ is_weight_accumulator;
+ /// INTERNAL ONLY
+ ///
+ typedef accumulators::impl::sum_kahan_impl<mpl::_2, tag::weight> impl;
+ };
+
+ template<typename VariateType, typename VariateTag>
+ struct sum_of_variates_kahan
+ : depends_on<>
+ {
+ /// INTERNAL ONLY
+ ///
+ typedef mpl::always<accumulators::impl::sum_kahan_impl<VariateType, VariateTag> > impl;
+ };
+
+} // namespace tag
+
+///////////////////////////////////////////////////////////////////////////////
+// extract::sum_kahan
+// extract::sum_of_weights_kahan
+// extract::sum_of_variates_kahan
+//
+namespace extract
+{
+ extractor<tag::sum_kahan> const sum_kahan = {};
+ extractor<tag::sum_of_weights_kahan> const sum_of_weights_kahan = {};
+ extractor<tag::abstract_sum_of_variates> const sum_of_variates_kahan = {};
+
+ BOOST_ACCUMULATORS_IGNORE_GLOBAL(sum_kahan)
+ BOOST_ACCUMULATORS_IGNORE_GLOBAL(sum_of_weights_kahan)
+ BOOST_ACCUMULATORS_IGNORE_GLOBAL(sum_of_variates_kahan)
+} // namespace extract
+
+using extract::sum_kahan;
+using extract::sum_of_weights_kahan;
+using extract::sum_of_variates_kahan;
+
+// sum(kahan) -> sum_kahan
+template<>
+struct as_feature<tag::sum(kahan)>
+{
+ typedef tag::sum_kahan type;
+};
+
+// sum_of_weights(kahan) -> sum_of_weights_kahan
+template<>
+struct as_feature<tag::sum_of_weights(kahan)>
+{
+ typedef tag::sum_of_weights_kahan type;
+};
+
+// So that sum_kahan can be automatically substituted with
+// weighted_sum_kahan when the weight parameter is non-void.
+template<>
+struct as_weighted_feature<tag::sum_kahan>
+{
+ typedef tag::weighted_sum_kahan type;
+};
+
+template<>
+struct feature_of<tag::weighted_sum_kahan>
+ : feature_of<tag::sum>
+{};
+
+// for the purposes of feature-based dependency resolution,
+// sum_kahan provides the same feature as sum
+template<>
+struct feature_of<tag::sum_kahan>
+ : feature_of<tag::sum>
+{
+};
+
+// for the purposes of feature-based dependency resolution,
+// sum_of_weights_kahan provides the same feature as sum_of_weights
+template<>
+struct feature_of<tag::sum_of_weights_kahan>
+ : feature_of<tag::sum_of_weights>
+{
+};
+
+template<typename VariateType, typename VariateTag>
+struct feature_of<tag::sum_of_variates_kahan<VariateType, VariateTag> >
+ : feature_of<tag::abstract_sum_of_variates>
+{
+};
+
+}} // namespace boost::accumulators
+
+#endif
+

Added: trunk/boost/accumulators/statistics/weighted_sum_kahan.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/accumulators/statistics/weighted_sum_kahan.hpp 2011-05-19 08:06:12 EDT (Thu, 19 May 2011)
@@ -0,0 +1,138 @@
+///////////////////////////////////////////////////////////////////////////////
+// weighted_sum_kahan.hpp
+//
+// Copyright 2011 Simon West. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_SUM_KAHAN_HPP_EAN_11_05_2011
+#define BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_SUM_KAHAN_HPP_EAN_11_05_2011
+
+#include <boost/mpl/placeholders.hpp>
+#include <boost/accumulators/framework/accumulator_base.hpp>
+#include <boost/accumulators/framework/extractor.hpp>
+#include <boost/accumulators/numeric/functional.hpp>
+#include <boost/accumulators/framework/parameters/sample.hpp>
+#include <boost/accumulators/framework/parameters/weight.hpp>
+#include <boost/accumulators/framework/accumulators/external_accumulator.hpp>
+#include <boost/accumulators/framework/depends_on.hpp>
+#include <boost/accumulators/statistics_fwd.hpp>
+#include <boost/accumulators/statistics/weighted_sum.hpp>
+#include <boost/numeric/conversion/cast.hpp>
+
+namespace boost { namespace accumulators
+{
+
+namespace impl
+{
+#if _MSC_VER > 1400
+# pragma float_control(push)
+# pragma float_control(precise, on)
+#endif
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // weighted_sum_kahan_impl
+ template<typename Sample, typename Weight, typename Tag>
+ struct weighted_sum_kahan_impl
+ : accumulator_base
+ {
+ typedef typename numeric::functional::multiplies<Sample, Weight>::result_type weighted_sample;
+
+ // for boost::result_of
+ typedef weighted_sample result_type;
+
+ template<typename Args>
+ weighted_sum_kahan_impl(Args const &args)
+ : weighted_sum_(
+ args[parameter::keyword<Tag>::get() | Sample()] * numeric::one<Weight>::value),
+ compensation(boost::numeric_cast<weighted_sample>(0.0))
+ {
+ }
+
+ template<typename Args>
+ void
+#if BOOST_ACCUMULATORS_GCC_VERSION > 40305
+# __attribute__((optimize("fno-associative-math")))
+#endif
+ operator ()(Args const &args)
+ {
+ const weighted_sample myTmp1 = args[parameter::keyword<Tag>::get()] * args[weight] - this->compensation;
+ const weighted_sample myTmp2 = this->weighted_sum_ + myTmp1;
+ this->compensation = (myTmp2 - this->weighted_sum_) - myTmp1;
+ this->weighted_sum_ = myTmp2;
+
+ }
+
+ result_type result(dont_care) const
+ {
+ return this->weighted_sum_;
+ }
+
+ private:
+ weighted_sample weighted_sum_;
+ weighted_sample compensation;
+ };
+
+#if _MSC_VER > 1400
+# pragma float_control(pop)
+#endif
+
+} // namespace impl
+
+///////////////////////////////////////////////////////////////////////////////
+// tag::weighted_sum_kahan
+// tag::weighted_sum_of_variates_kahan
+//
+namespace tag
+{
+ struct weighted_sum_kahan
+ : depends_on<>
+ {
+ /// INTERNAL ONLY
+ ///
+ typedef accumulators::impl::weighted_sum_kahan_impl<mpl::_1, mpl::_2, tag::sample> impl;
+ };
+
+ template<typename VariateType, typename VariateTag>
+ struct weighted_sum_of_variates_kahan
+ : depends_on<>
+ {
+ /// INTERNAL ONLY
+ ///
+ typedef accumulators::impl::weighted_sum_kahan_impl<VariateType, mpl::_2, VariateTag> impl;
+ };
+
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// extract::weighted_sum_kahan
+// extract::weighted_sum_of_variates_kahan
+//
+namespace extract
+{
+ extractor<tag::weighted_sum_kahan> const weighted_sum_kahan = {};
+ extractor<tag::abstract_weighted_sum_of_variates> const weighted_sum_of_variates_kahan = {};
+
+ BOOST_ACCUMULATORS_IGNORE_GLOBAL(weighted_sum_kahan)
+ BOOST_ACCUMULATORS_IGNORE_GLOBAL(weighted_sum_of_variates_kahan)
+}
+
+using extract::weighted_sum_kahan;
+using extract::weighted_sum_of_variates_kahan;
+
+// weighted_sum(kahan) -> weighted_sum_kahan
+template<>
+struct as_feature<tag::weighted_sum(kahan)>
+{
+ typedef tag::weighted_sum_kahan type;
+};
+
+template<typename VariateType, typename VariateTag>
+struct feature_of<tag::weighted_sum_of_variates_kahan<VariateType, VariateTag> >
+ : feature_of<tag::abstract_weighted_sum_of_variates>
+{
+};
+
+}} // namespace boost::accumulators
+
+#endif

Modified: trunk/boost/accumulators/statistics_fwd.hpp
==============================================================================
--- trunk/boost/accumulators/statistics_fwd.hpp (original)
+++ trunk/boost/accumulators/statistics_fwd.hpp 2011-05-19 08:06:12 EDT (Thu, 19 May 2011)
@@ -109,6 +109,10 @@
     struct sum_of_weights;
     template<typename VariateType, typename VariateTag>
     struct sum_of_variates;
+ struct sum_kahan;
+ struct sum_of_weights_kahan;
+ template<typename VariateType, typename VariateTag>
+ struct sum_of_variates_kahan;
     template<typename LeftRight>
     struct tail;
     template<typename LeftRight>
@@ -263,6 +267,9 @@
     template<typename Sample, typename Tag = tag::sample>
     struct sum_impl;
 
+ template<typename Sample, typename Tag>
+ struct sum_kahan_impl;
+
     template<typename Sample, typename LeftRight>
     struct tail_impl;
 
@@ -338,6 +345,9 @@
     template<typename Sample, typename Weight, typename Tag>
     struct weighted_sum_impl;
 
+ template<typename Sample, typename Weight, typename Tag>
+ struct weighted_sum_kahan_impl;
+
     template<typename Sample, typename Weight, typename LeftRight>
     struct non_coherent_weighted_tail_mean_impl;
 
@@ -414,6 +424,9 @@
 struct regular {};
 struct for_median {};
 
+// modifier for sum_kahan, sum_of_weights_kahan, sum_of_variates_kahan, weighted_sum_kahan
+struct kahan {};
+
 }} // namespace boost::accumulators
 
 #endif

Modified: trunk/libs/accumulators/doc/accumulators.qbk
==============================================================================
--- trunk/libs/accumulators/doc/accumulators.qbk (original)
+++ trunk/libs/accumulators/doc/accumulators.qbk 2011-05-19 08:06:12 EDT (Thu, 19 May 2011)
@@ -500,7 +500,7 @@
     
     }}}
 
-Much of the above should be pretty self-explanitory, except for the use of argument packs
+Much of the above should be pretty self-explanatory, except for the use of argument packs
 which may be confusing if you have never used the _parameter_ library before. An argument
 pack is a cluster of values, each of which can be accessed with a key. So `args[sample]`
 extracts from the pack the value associated with the `sample` key. And the cryptic
@@ -853,7 +853,7 @@
 
 [*Registering feature variants with [^as_feature<>]]
 
-You may hve noticed that some feature variants in the Accumulators Framework can be
+You may have noticed that some feature variants in the Accumulators Framework can be
 specified with a nicer syntax. For instance, instead of `tag::mean` and `tag::immediate_mean`
 you can specify them with `tag::mean(lazy)` and `tag::mean(immediate)` respectively.
 These are merely aliases, but the syntax makes the relationship between the two clearer.
@@ -2219,7 +2219,8 @@
 
 [section:sum sum ['and variants]]
 
-For summing the samples, weights or variates.
+For summing the samples, weights or variates. The default implementation uses the standard sum operation,
+but variants using the Kahan summation algorithm are also provided.
 
 [variablelist
     [[Result Type] [`_sample_type_` for summing samples \n
@@ -2228,19 +2229,26 @@
     [[Depends On] [['none]]]
     [[Variants] [`tag::sum` \n
                  `tag::sum_of_weights` \n
- `tag::sum_of_variates<_variate_type_, _variate_tag_>`]]
+ `tag::sum_of_variates<_variate_type_, _variate_tag_>` \n
+ `tag::sum_kahan` (a.k.a. `tag::sum(kahan)`) \n
+ `tag::sum_of_weights_kahan` (a.k.a. `tag::sum_of_weights(kahan)`) \n
+ `tag::sum_of_variates_kahan<_variate_type_, _variate_tag_>` \n]]
     [[Initialization Parameters] [['none]]]
     [[Accumulator Parameters] [`weight` for summing weights \n
                                `_variate_tag_` for summing variates]]
     [[Extractor Parameters] [['none]]]
- [[Accumulator Complexity] [O(1)]]
+ [[Accumulator Complexity] [O(1). Note that the Kahan sum performs four floating-point sum
+ operations per accumulated value, whereas the naive sum
+ performs only one.]]
     [[Extractor Complexity] [O(1)]]
 ]
 
 [*Header]
 [def _SUM_HPP_ [headerref boost/accumulators/statistics/sum.hpp]]
+[def _SUM_KAHAN_HPP_ [headerref boost/accumulators/statistics/sum_kahan.hpp]]
 
     #include <_SUM_HPP_>
+ #include <_SUM_KAHAN_HPP_>
 
 [*Example]
 
@@ -2269,9 +2277,18 @@
     BOOST_CHECK_EQUAL(12, sum_of_weights(acc));
     BOOST_CHECK_EQUAL(18, sum_of_variates(acc));
 
+ // demonstrate Kahan summation
+ accumulator_set<float, stats<tag::sum_kahan> > acc;
+ BOOST_CHECK_EQUAL(0.0f, sum_kahan(acc));
+ for (size_t i = 0; i < 1e6; ++i) {
+ acc(1e-6f);
+ }
+ BOOST_CHECK_EQUAL(1.0f, sum_kahan(acc));
+
 [*See also]
 
 * [classref boost::accumulators::impl::sum_impl [^sum_impl]]
+* [classref boost::accumulators::impl::sum_kahan_impl [^sum_kahan_impl]]
 
 [endsect]
 
@@ -3573,26 +3590,34 @@
 [section:weighted_sum weighted_sum ['and variants]]
 
 For summing the weighted samples or variates. All of the `tag::weighted_sum_of_variates<>` features
-can be extracted with the `weighted_sum_of_variates()` extractor.
+can be extracted with the `weighted_sum_of_variates()` extractor. Variants that implement the Kahan
+summation algorithm are also provided.
 
 [variablelist
     [[Result Type] [`numeric::functional::multiplies<_sample_type_, _weight_type_>::result_type` for summing weighted samples \n
                     `numeric::functional::multiplies<_variate_type_, _weight_type_>::result_type` for summing weighted variates]]
     [[Depends On] [['none]]]
     [[Variants] [`tag::weighted_sum` \n
- `tag::weighted_sum_of_variates<_variate_type_, _variate_tag_>`]]
+ `tag::weighted_sum_of_variates<_variate_type_, _variate_tag_>` \n
+ `tag::weighted_sum_kahan` (a.k.a. tag::weighted_sum(kahan)) \n
+ `tag::weighted_sum_of_variates_kahan<_variate_type_, _variate_tag_>` \n]]
     [[Initialization Parameters] [['none]]]
     [[Accumulator Parameters] [`weight` \n
                                `_variate_tag_` for summing variates]]
     [[Extractor Parameters] [['none]]]
- [[Accumulator Complexity] [O(1)]]
+ [[Accumulator Complexity] [O(1). Note that the Kahan sum performs four floating-point sum
+ operations per accumulated value, whereas the naive sum
+ performs only one.]]
     [[Extractor Complexity] [O(1)]]
 ]
 
 [*Header]
 [def _WEIGHTED_SUM_HPP_ [headerref boost/accumulators/statistics/weighted_sum.hpp]]
+[def _WEIGHTED_SUM_KAHAN_HPP_ [headerref boost/accumulators/statistics/weighted_sum_kahan.hpp]]
 
     #include <_WEIGHTED_SUM_HPP_>
+ #include <_WEIGHTED_SUM_KAHAN_HPP_>
+
 
 [*Example]
 
@@ -3610,9 +3635,18 @@
     BOOST_CHECK_EQUAL(32, weighted_sum(acc));
     BOOST_CHECK_EQUAL(78, weighted_sum_of_variates(acc));
 
+ // demonstrate weighted Kahan summation
+ accumulator_set<float, stats<tag::weighted_sum_kahan>, float > acc;
+ BOOST_CHECK_EQUAL(0.0f, weighted_sum_kahan(acc));
+ for (size_t i = 0; i < 1e6; ++i) {
+ acc(1.0f, weight = 1e-6f);
+ }
+ BOOST_CHECK_EQUAL(1.0f, weighted_sum_kahan(acc));
+
 [*See also]
 
 * [classref boost::accumulators::impl::weighted_sum_impl [^weighted_sum_impl]]
+* [classref boost::accumulators::impl::weighted_sum_impl [^weighted_sum_kahan_impl]]
 
 [endsect]
 
@@ -4014,6 +4048,9 @@
 Gauckler and Olivier Gygi, who, along with Daniel Egloff, implemented many of the
 statistical accumulators.
 
+I would also like to thank Simon West for all his assistance maintaining
+Boost.Accumulators.
+
 Finally, I would like to thank _ZKB_ for sponsoring the work on Boost.Accumulators
 and graciously donating it to the community.
 

Modified: trunk/libs/accumulators/test/Jamfile.v2
==============================================================================
--- trunk/libs/accumulators/test/Jamfile.v2 (original)
+++ trunk/libs/accumulators/test/Jamfile.v2 2011-05-19 08:06:12 EDT (Thu, 19 May 2011)
@@ -50,6 +50,7 @@
       [ run rolling_mean.cpp ]
       [ run skewness.cpp ]
       [ run sum.cpp ]
+ [ run sum_kahan.cpp ]
       [ run tail.cpp ]
       [ run tail_mean.cpp ]
       [ run tail_quantile.cpp ]
@@ -67,8 +68,8 @@
       [ run weighted_p_square_quantile.cpp ]
       [ run weighted_skewness.cpp ]
       [ run weighted_sum.cpp ]
+ [ run weighted_sum_kahan.cpp ]
       [ run weighted_variance.cpp ]
-
       [ run weighted_pot_quantile.cpp ]
       [ run weighted_tail_mean.cpp ]
       [ run weighted_tail_quantile.cpp ]

Added: trunk/libs/accumulators/test/sum_kahan.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/accumulators/test/sum_kahan.cpp 2011-05-19 08:06:12 EDT (Thu, 19 May 2011)
@@ -0,0 +1,81 @@
+// (C) Copyright Gaetano Mendola 2010, Simon West 2011.
+// Use, modification and distribution are subject to the
+// Boost Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/test/unit_test.hpp>
+#include <boost/accumulators/accumulators.hpp>
+#include <boost/accumulators/statistics/stats.hpp>
+#include <boost/accumulators/statistics/sum_kahan.hpp>
+#include <boost/accumulators/statistics/variates/covariate.hpp>
+
+using namespace boost;
+using namespace unit_test;
+using namespace accumulators;
+
+///////////////////////////////////////////////////////////////////////////////
+// test_sum_kahan
+//
+void test_sum_kahan()
+{
+ accumulator_set<float, stats<tag::sum_kahan> > acc;
+
+ BOOST_CHECK_EQUAL(0.0f, sum_kahan(acc));
+
+ for (size_t i = 0; i < 1e6; ++i) {
+ acc(1e-6f);
+ }
+
+ BOOST_CHECK_EQUAL(1.0f, sum_kahan(acc));
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// test_sum_of_weights_kahan
+//
+void test_sum_of_weights_kahan()
+{
+ accumulator_set<float, stats<tag::sum_of_weights_kahan>, float > acc;
+
+ BOOST_CHECK_EQUAL(0.0f, sum_of_weights_kahan(acc));
+
+ for (size_t i = 0; i < 1e6; ++i) {
+ acc(0, weight = 1e-6f);
+ }
+
+ BOOST_CHECK_EQUAL(1.0f, sum_of_weights_kahan(acc));
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// test_sum_of_variates_kahan
+//
+void test_sum_of_variates_kahan()
+{
+ accumulator_set<
+ float,
+ stats<tag::sum_of_variates_kahan<float, tag::covariate1> >,
+ float
+ >
+ acc;
+
+ BOOST_CHECK_EQUAL(0.0f, sum_of_variates_kahan(acc));
+
+ for (size_t i = 0; i < 1e6; ++i) {
+ acc(0, covariate1 = 1e-6f);
+ }
+
+ BOOST_CHECK_EQUAL(1.0f, sum_of_variates_kahan(acc));
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// init_unit_test_suite
+//
+test_suite* init_unit_test_suite( int argc, char* argv[] )
+{
+ test_suite *test = BOOST_TEST_SUITE("sum kahan tests");
+
+ test->add(BOOST_TEST_CASE(&test_sum_kahan));
+ test->add(BOOST_TEST_CASE(&test_sum_of_weights_kahan));
+ test->add(BOOST_TEST_CASE(&test_sum_of_variates_kahan));
+
+ return test;
+}

Added: trunk/libs/accumulators/test/weighted_sum_kahan.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/accumulators/test/weighted_sum_kahan.cpp 2011-05-19 08:06:12 EDT (Thu, 19 May 2011)
@@ -0,0 +1,64 @@
+// (C) Copyright Simon West 2011.
+// Use, modification and distribution are subject to the
+// Boost Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/test/unit_test.hpp>
+#include <boost/accumulators/accumulators.hpp>
+#include <boost/accumulators/statistics/stats.hpp>
+#include <boost/accumulators/statistics/weighted_sum_kahan.hpp>
+#include <boost/accumulators/statistics/variates/covariate.hpp>
+
+using namespace boost;
+using namespace unit_test;
+using namespace accumulators;
+
+///////////////////////////////////////////////////////////////////////////////
+// test_weighted_sum_kahan
+//
+void test_weighted_sum_kahan()
+{
+ accumulator_set<float, stats<tag::weighted_sum_kahan>, float > acc;
+
+ BOOST_CHECK_EQUAL(0.0f, weighted_sum_kahan(acc));
+
+ for (size_t i = 0; i < 1e6; ++i) {
+ acc(1, weight = 1e-6f);
+ }
+
+ BOOST_CHECK_EQUAL(1.0f, weighted_sum_kahan(acc));
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// test_weighted_sum_of_variates_kahan
+//
+void test_weighted_sum_of_variates_kahan()
+{
+ accumulator_set<
+ float,
+ stats<tag::weighted_sum_of_variates_kahan<float, tag::covariate1> >,
+ float
+ >
+ acc;
+
+ BOOST_CHECK_EQUAL(0.0f, weighted_sum_of_variates_kahan(acc));
+
+ for (size_t i = 0; i < 1e6; ++i) {
+ acc(0, weight = 1.0f, covariate1 = 1e-6f);
+ }
+
+ BOOST_CHECK_EQUAL(1.0f, weighted_sum_of_variates_kahan(acc));
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// init_unit_test_suite
+//
+test_suite* init_unit_test_suite( int argc, char* argv[] )
+{
+ test_suite *test = BOOST_TEST_SUITE("weighted sum kahan tests");
+
+ test->add(BOOST_TEST_CASE(&test_weighted_sum_kahan));
+ test->add(BOOST_TEST_CASE(&test_weighted_sum_of_variates_kahan));
+
+ return test;
+}


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk