zeta.hpp

来自「Boost provides free peer-reviewed portab」· HPP 代码 · 共 904 行 · 第 1/3 页

HPP
904
字号
//  Copyright John Maddock 2007.//  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)#ifndef BOOST_MATH_ZETA_HPP#define BOOST_MATH_ZETA_HPP#ifdef _MSC_VER#pragma once#endif#include <boost/math/tools/precision.hpp>#include <boost/math/tools/series.hpp>#include <boost/math/policies/error_handling.hpp>#include <boost/math/special_functions/gamma.hpp>#include <boost/math/special_functions/sin_pi.hpp>namespace boost{ namespace math{ namespace detail{template <class T, class Policy>struct zeta_series_cache_size{   //   // Work how large to make our cache size when evaluating the series    // evaluation:  normally this is just large enough for the series   // to have converged, but for arbitrary precision types we need a    // really large cache to achieve reasonable precision in a reasonable    // time.  This is important when constructing rational approximations   // to zeta for example.   //   typedef typename boost::math::policies::precision<T,Policy>::type precision_type;   typedef typename mpl::if_<      mpl::less_equal<precision_type, mpl::int_<0> >,      mpl::int_<5000>,      typename mpl::if_<         mpl::less_equal<precision_type, mpl::int_<64> >,         mpl::int_<70>,         typename mpl::if_<            mpl::less_equal<precision_type, mpl::int_<113> >,            mpl::int_<100>,            mpl::int_<5000>         >::type      >::type   >::type type;};template <class T, class Policy>T zeta_series_imp(T s, T sc, const Policy&){   //   // Series evaluation from:   // 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,       tools::digits<T>(),      max_iter);   policies::check_series_iterations("boost::math::zeta_series2<%1%>(%1%)", max_iter, pol);   return result;}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;    //   // 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);   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,         0.000255784226140488490982,         0.10991819782396112081e-4,      };      result = tools::evaluate_polynomial(P, -sc) / tools::evaluate_polynomial(Q, -sc);      result += 1 / (-sc);   }   else if(s <= 4)   {      // Maximum Deviation Found:          5.946e-22      // Expected Error Term:              -5.946e-22      static const float Y = 0.6986598968505859375;      static const T P[6] = {             -0.0537258300023595030676,         0.0445163473292365591906,         0.0128677673534519952905,         0.00097541770457391752726,         0.769875101573654070925e-4,         0.328032510000383084155e-5,      };      static const T Q[7] = {             1,         0.33383194553034051422,         0.0487798431291407621462,         0.00479039708573558490716,         0.000270776703956336357707,         0.106951867532057341359e-4,         0.236276623974978646399e-7,      };      result = tools::evaluate_polynomial(P, s - 2) / tools::evaluate_polynomial(Q, s - 2);      result += Y + 1 / (-sc);   }   else if(s <= 7)   {      // Maximum Deviation Found:                     2.955e-17      // Expected Error Term:                         2.955e-17      // Max error found at double precision:         2.009135e-16      static const T P[6] = {             -2.49710190602259410021,         -2.60013301809475665334,         -0.939260435377109939261,         -0.138448617995741530935,         -0.00701721240549802377623,         -0.229257310594893932383e-4,      };      static const T Q[9] = {             1,         0.706039025937745133628,         0.15739599649558626358,         0.0106117950976845084417,         -0.36910273311764618902e-4,         0.493409563927590008943e-5,         -0.234055487025287216506e-6,         0.718833729365459760664e-8,         -0.1129200113474947419e-9,      };      result = tools::evaluate_polynomial(P, s - 4) / tools::evaluate_polynomial(Q, s - 4);      result = 1 + exp(result);   }   else if(s < 15)   {      // Maximum Deviation Found:                     7.117e-16      // Expected Error Term:                         7.117e-16      // Max error found at double precision:         9.387771e-16      static const T P[7] = {             -4.78558028495135619286,         -1.89197364881972536382,         -0.211407134874412820099,         -0.000189204758260076688518,         0.00115140923889178742086,         0.639949204213164496988e-4,         0.139348932445324888343e-5,        };      static const T Q[9] = {             1,         0.244345337378188557777,         0.00873370754492288653669,         -0.00117592765334434471562,         -0.743743682899933180415e-4,         -0.21750464515767984778e-5,         0.471001264003076486547e-8,         -0.833378440625385520576e-10,         0.699841545204845636531e-12,        };      result = tools::evaluate_polynomial(P, s - 7) / tools::evaluate_polynomial(Q, s - 7);      result = 1 + exp(result);   }   else if(s < 36)   {      // Max error in interpolated form:             1.668e-17      // Max error found at long double precision:   1.669714e-17      static const T P[8] = {             -10.3948950573308896825,         -2.85827219671106697179,         -0.347728266539245787271,         -0.0251156064655346341766,         -0.00119459173416968685689,         -0.382529323507967522614e-4,         -0.785523633796723466968e-6,         -0.821465709095465524192e-8,      };      static const T Q[10] = {             1,         0.208196333572671890965,         0.0195687657317205033485,         0.00111079638102485921877,         0.408507746266039256231e-4,         0.955561123065693483991e-6,         0.118507153474022900583e-7,         0.222609483627352615142e-14,      };      result = tools::evaluate_polynomial(P, s - 15) / tools::evaluate_polynomial(Q, s - 15);      result = 1 + exp(result);   }

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?