Index: boost/accumulators/statistics/sum_kahan.hpp =================================================================== --- boost/accumulators/statistics/sum_kahan.hpp (revision 0) +++ boost/accumulators/statistics/sum_kahan.hpp (revision 0) @@ -0,0 +1,91 @@ +/////////////////////////////////////////////////////////////////////////////// +// sum_kahan.hpp +// +// Copyright 2010 Gaetano Mendola. 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 +#include +#include + +namespace boost { namespace accumulators +{ + +namespace impl +{ + +template +struct sum_kahan_impl + : accumulator_base +{ + typedef Sample result_type; + + //////////////////////////////////////////////////////////////////////////// + // sum_kahan_impl + /** + @brief Kahan summation algorithm + + Kahan algorithm reduces the numerical error obtained with standard + sequential sum. + + */ + template + sum_kahan_impl(Args const & args) + : sum(args[sample | Sample()]), + compensation(boost::numeric_cast(0.0)) + { + } + + template + void operator ()(Args const & args) + { + const Sample myTmp1 = args[sample] - 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; +}; + +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +// tag::sum_kahan +namespace tag +{ + + struct sum_kahan + : depends_on<> + { + /// INTERNAL ONLY + /// + typedef impl::sum_kahan_impl< mpl::_1 > impl; + }; +} // namespace tag + +/////////////////////////////////////////////////////////////////////////////// +// extract::sum_kahan +namespace extract +{ + extractor const sum_kahan = {}; + + BOOST_ACCUMULATORS_IGNORE_GLOBAL(sum_kahan) +} // namespace extract + +using extract::sum_kahan; + +}} // namespace boost::accumulators + +#endif + Index: libs/accumulators/test/sum_kahan.cpp =================================================================== --- libs/accumulators/test/sum_kahan.cpp (revision 0) +++ libs/accumulators/test/sum_kahan.cpp (revision 0) @@ -0,0 +1,41 @@ +// (C) Copyright Gaetano Mendola 2010. +// 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 +#include +#include +#include + +using namespace boost; +using namespace unit_test; +using namespace accumulators; + +/////////////////////////////////////////////////////////////////////////////// +// test_stat +// +void test_stat() +{ + accumulator_set > 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)); +} + +/////////////////////////////////////////////////////////////////////////////// +// init_unit_test_suite +// +test_suite* init_unit_test_suite( int argc, char* argv[] ) +{ + test_suite *test = BOOST_TEST_SUITE("sum kahan test"); + + test->add(BOOST_TEST_CASE(&test_stat)); + + return test; +} Index: libs/accumulators/test/Jamfile.v2 =================================================================== --- libs/accumulators/test/Jamfile.v2 (revision 64372) +++ libs/accumulators/test/Jamfile.v2 (working copy) @@ -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 ]