Boost-Geometry-Utils
view release on metacpan or search on metacpan
src/boost/math/special_functions/zeta.hpp view on Meta::CPAN
// Havil, J. Gamma: Exploring Euler's Constant.
// Princeton, NJ: Princeton University Press, 2003.
//
// See also http://mathworld.wolfram.com/RiemannZetaFunction.html
//
BOOST_MATH_STD_USING
T sum = 0;
T mult = 0.5;
T change;
typedef typename zeta_series_cache_size<T,Policy>::type cache_size;
T powers[cache_size::value] = { 0, };
unsigned n = 0;
do{
T binom = -static_cast<T>(n);
T nested_sum = 1;
if(n < sizeof(powers) / sizeof(powers[0]))
powers[n] = pow(static_cast<T>(n + 1), -s);
for(unsigned k = 1; k <= n; ++k)
{
T p;
if(k < sizeof(powers) / sizeof(powers[0]))
{
p = powers[k];
//p = pow(k + 1, -s);
}
else
p = pow(static_cast<T>(k + 1), -s);
nested_sum += binom * p;
binom *= (k - static_cast<T>(n)) / (k + 1);
}
change = mult * nested_sum;
sum += change;
mult /= 2;
++n;
}while(fabs(change / sum) > tools::epsilon<T>());
return sum * 1 / -boost::math::powm1(T(2), sc);
}
//
// Classical p-series:
//
template <class T>
struct zeta_series2
{
typedef T result_type;
zeta_series2(T _s) : s(-_s), k(1){}
T operator()()
{
BOOST_MATH_STD_USING
return pow(static_cast<T>(k++), s);
}
private:
T s;
unsigned k;
};
template <class T, class Policy>
inline T zeta_series2_imp(T s, const Policy& pol)
{
boost::uintmax_t max_iter = policies::get_max_series_iterations<Policy>();;
zeta_series2<T> f(s);
T result = tools::sum_series(
f,
policies::get_epsilon<T, Policy>(),
max_iter);
policies::check_series_iterations<T>("boost::math::zeta_series2<%1%>(%1%)", max_iter, pol);
return result;
}
#endif
template <class T, class Policy>
T zeta_polynomial_series(T s, T sc, Policy const &)
{
//
// This is algorithm 3 from:
//
// "An Efficient Algorithm for the Riemann Zeta Function", P. Borwein,
// Canadian Mathematical Society, Conference Proceedings.
// See: http://www.cecm.sfu.ca/personal/pborwein/PAPERS/P155.pdf
//
BOOST_MATH_STD_USING
int n = itrunc(T(log(boost::math::tools::epsilon<T>()) / -2));
T sum = 0;
T two_n = ldexp(T(1), n);
int ej_sign = 1;
for(int j = 0; j < n; ++j)
{
sum += ej_sign * -two_n / pow(T(j + 1), s);
ej_sign = -ej_sign;
}
T ej_sum = 1;
T ej_term = 1;
for(int j = n; j <= 2 * n - 1; ++j)
{
sum += ej_sign * (ej_sum - two_n) / pow(T(j + 1), s);
ej_sign = -ej_sign;
ej_term *= 2 * n - j;
ej_term /= j - n + 1;
ej_sum += ej_term;
}
return -sum / (two_n * (-powm1(T(2), sc)));
}
template <class T, class Policy>
T zeta_imp_prec(T s, T sc, const Policy& pol, const mpl::int_<0>&)
{
BOOST_MATH_STD_USING
T result;
result = zeta_polynomial_series(s, sc, pol);
#if 0
// Old code archived for future reference:
//
// Only use power series if it will converge in 100
// iterations or less: the more iterations it consumes
// the slower convergence becomes so we have to be very
// careful in it's usage.
//
if (s > -log(tools::epsilon<T>()) / 4.5)
result = detail::zeta_series2_imp(s, pol);
else
result = detail::zeta_series_imp(s, sc, pol);
#endif
return result;
}
template <class T, class Policy>
inline T zeta_imp_prec(T s, T sc, const Policy&, const mpl::int_<53>&)
{
BOOST_MATH_STD_USING
T result;
if(s < 1)
{
// Rational Approximation
// Maximum Deviation Found: 2.020e-18
// Expected Error Term: -2.020e-18
// Max error found at double precision: 3.994987e-17
static const T P[6] = {
0.24339294433593750202L,
-0.49092470516353571651L,
0.0557616214776046784287L,
-0.00320912498879085894856L,
0.000451534528645796438704L,
-0.933241270357061460782e-5L,
};
static const T Q[6] = {
1L,
-0.279960334310344432495L,
0.0419676223309986037706L,
-0.00413421406552171059003L,
0.00024978985622317935355L,
-0.101855788418564031874e-4L,
};
result = tools::evaluate_polynomial(P, sc) / tools::evaluate_polynomial(Q, sc);
result -= 1.2433929443359375F;
result += (sc);
result /= (sc);
}
else if(s <= 2)
{
// Maximum Deviation Found: 9.007e-20
// Expected Error Term: 9.007e-20
static const T P[6] = {
0.577215664901532860516,
0.243210646940107164097,
0.0417364673988216497593,
0.00390252087072843288378,
0.000249606367151877175456,
0.110108440976732897969e-4,
};
static const T Q[6] = {
1,
0.295201277126631761737,
0.043460910607305495864,
0.00434930582085826330659,
( run in 0.588 second using v1.01-cache-2.11-cpan-96521ef73a4 )