author | William Roberts <williamr@symbian.org> |
Tue, 16 Mar 2010 16:12:26 +0000 | |
branch | Symbian2 |
changeset 2 | 2fe1408b6811 |
permissions | -rw-r--r-- |
williamr@2 | 1 |
// (C) Copyright John Maddock 2005. |
williamr@2 | 2 |
// Use, modification and distribution are subject to the |
williamr@2 | 3 |
// Boost Software License, Version 1.0. (See accompanying file |
williamr@2 | 4 |
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
williamr@2 | 5 |
|
williamr@2 | 6 |
#ifndef BOOST_MATH_SERIES_INCLUDED |
williamr@2 | 7 |
#define BOOST_MATH_SERIES_INCLUDED |
williamr@2 | 8 |
|
williamr@2 | 9 |
#include <cmath> |
williamr@2 | 10 |
|
williamr@2 | 11 |
#ifdef BOOST_NO_STDC_NAMESPACE |
williamr@2 | 12 |
namespace std{ using ::pow; using ::fabs; } |
williamr@2 | 13 |
#endif |
williamr@2 | 14 |
|
williamr@2 | 15 |
|
williamr@2 | 16 |
namespace boost{ namespace math{ namespace detail{ |
williamr@2 | 17 |
|
williamr@2 | 18 |
// |
williamr@2 | 19 |
// Algorithm kahan_sum_series invokes Functor func until the N'th |
williamr@2 | 20 |
// term is too small to have any effect on the total, the terms |
williamr@2 | 21 |
// are added using the Kahan summation method. |
williamr@2 | 22 |
// |
williamr@2 | 23 |
// CAUTION: Optimizing compilers combined with extended-precision |
williamr@2 | 24 |
// machine registers conspire to render this algorithm partly broken: |
williamr@2 | 25 |
// double rounding of intermediate terms (first to a long double machine |
williamr@2 | 26 |
// register, and then to a double result) cause the rounding error computed |
williamr@2 | 27 |
// by the algorithm to be off by up to 1ulp. However this occurs rarely, and |
williamr@2 | 28 |
// in any case the result is still much better than a naive summation. |
williamr@2 | 29 |
// |
williamr@2 | 30 |
template <class Functor> |
williamr@2 | 31 |
typename Functor::result_type kahan_sum_series(Functor& func, int bits) |
williamr@2 | 32 |
{ |
williamr@2 | 33 |
typedef typename Functor::result_type result_type; |
williamr@2 | 34 |
result_type factor = std::pow(result_type(2), bits); |
williamr@2 | 35 |
result_type result = func(); |
williamr@2 | 36 |
result_type next_term, y, t; |
williamr@2 | 37 |
result_type carry = 0; |
williamr@2 | 38 |
do{ |
williamr@2 | 39 |
next_term = func(); |
williamr@2 | 40 |
y = next_term - carry; |
williamr@2 | 41 |
t = result + y; |
williamr@2 | 42 |
carry = t - result; |
williamr@2 | 43 |
carry -= y; |
williamr@2 | 44 |
result = t; |
williamr@2 | 45 |
} |
williamr@2 | 46 |
while(std::fabs(result) < std::fabs(factor * next_term)); |
williamr@2 | 47 |
return result; |
williamr@2 | 48 |
} |
williamr@2 | 49 |
|
williamr@2 | 50 |
} } } // namespaces |
williamr@2 | 51 |
|
williamr@2 | 52 |
#endif // BOOST_MATH_SERIES_INCLUDED |