1 // (C) Copyright John Maddock 2005-2006.
2 // Use, modification and distribution are subject to the
3 // Boost Software License, Version 1.0. (See accompanying file
4 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 #ifndef BOOST_MATH_TOOLS_SERIES_INCLUDED
7 #define BOOST_MATH_TOOLS_SERIES_INCLUDED
13 #include <boost/config/no_tr1/cmath.hpp>
14 #include <boost/cstdint.hpp>
15 #include <boost/math/tools/config.hpp>
17 namespace boost
{ namespace math
{ namespace tools
{
20 // Simple series summation come first:
22 template <class Functor
>
23 typename
Functor::result_type
sum_series(Functor
& func
, int bits
)
27 typedef typename
Functor::result_type result_type
;
29 result_type factor
= pow(result_type(2), bits
);
30 result_type result
= func();
31 result_type next_term
;
36 while(fabs(result
) < fabs(factor
* next_term
));
40 template <class Functor
>
41 typename
Functor::result_type
sum_series(Functor
& func
, int bits
, boost::uintmax_t& max_terms
)
45 typedef typename
Functor::result_type result_type
;
47 boost::uintmax_t counter
= max_terms
;
49 result_type factor
= ldexp(result_type(1), bits
);
50 result_type result
= func();
51 result_type next_term
;
56 while((fabs(result
) < fabs(factor
* next_term
)) && --counter
);
58 // set max_terms to the actual number of terms of the series evaluated:
59 max_terms
= max_terms
- counter
;
64 template <class Functor
, class U
>
65 typename
Functor::result_type
sum_series(Functor
& func
, int bits
, U init_value
)
69 typedef typename
Functor::result_type result_type
;
71 result_type factor
= ldexp(result_type(1), bits
);
72 result_type result
= static_cast<result_type
>(init_value
);
73 result_type next_term
;
78 while(fabs(result
) < fabs(factor
* next_term
));
83 template <class Functor
, class U
>
84 typename
Functor::result_type
sum_series(Functor
& func
, int bits
, boost::uintmax_t& max_terms
, U init_value
)
88 typedef typename
Functor::result_type result_type
;
90 boost::uintmax_t counter
= max_terms
;
92 result_type factor
= ldexp(result_type(1), bits
);
93 result_type result
= init_value
;
94 result_type next_term
;
99 while((fabs(result
) < fabs(factor
* next_term
)) && --counter
);
101 // set max_terms to the actual number of terms of the series evaluated:
102 max_terms
= max_terms
- counter
;
108 // Algorithm kahan_sum_series invokes Functor func until the N'th
109 // term is too small to have any effect on the total, the terms
110 // are added using the Kahan summation method.
112 // CAUTION: Optimizing compilers combined with extended-precision
113 // machine registers conspire to render this algorithm partly broken:
114 // double rounding of intermediate terms (first to a long double machine
115 // register, and then to a double result) cause the rounding error computed
116 // by the algorithm to be off by up to 1ulp. However this occurs rarely, and
117 // in any case the result is still much better than a naive summation.
119 template <class Functor
>
120 typename
Functor::result_type
kahan_sum_series(Functor
& func
, int bits
)
124 typedef typename
Functor::result_type result_type
;
126 result_type factor
= pow(result_type(2), bits
);
127 result_type result
= func();
128 result_type next_term
, y
, t
;
129 result_type carry
= 0;
132 y
= next_term
- carry
;
138 while(fabs(result
) < fabs(factor
* next_term
));
142 template <class Functor
>
143 typename
Functor::result_type
kahan_sum_series(Functor
& func
, int bits
, boost::uintmax_t& max_terms
)
147 typedef typename
Functor::result_type result_type
;
149 boost::uintmax_t counter
= max_terms
;
151 result_type factor
= ldexp(result_type(1), bits
);
152 result_type result
= func();
153 result_type next_term
, y
, t
;
154 result_type carry
= 0;
157 y
= next_term
- carry
;
163 while((fabs(result
) < fabs(factor
* next_term
)) && --counter
);
165 // set max_terms to the actual number of terms of the series evaluated:
166 max_terms
= max_terms
- counter
;
175 #endif // BOOST_MATH_TOOLS_SERIES_INCLUDED