riemann_zeta.tcc
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043 #ifndef _GLIBCXX_TR1_RIEMANN_ZETA_TCC
00044 #define _GLIBCXX_TR1_RIEMANN_ZETA_TCC 1
00045
00046 #include "special_function_util.h"
00047
00048 namespace std
00049 {
00050 namespace tr1
00051 {
00052
00053
00054
00055
00056 namespace __detail
00057 {
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072 template<typename _Tp>
00073 _Tp
00074 __riemann_zeta_sum(const _Tp __s)
00075 {
00076
00077 if (__s < _Tp(1))
00078 std::__throw_domain_error(__N("Bad argument in zeta sum."));
00079
00080 const unsigned int max_iter = 10000;
00081 _Tp __zeta = _Tp(0);
00082 for (unsigned int __k = 1; __k < max_iter; ++__k)
00083 {
00084 _Tp __term = std::pow(static_cast<_Tp>(__k), -__s);
00085 if (__term < std::numeric_limits<_Tp>::epsilon())
00086 {
00087 break;
00088 }
00089 __zeta += __term;
00090 }
00091
00092 return __zeta;
00093 }
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109 template<typename _Tp>
00110 _Tp
00111 __riemann_zeta_alt(const _Tp __s)
00112 {
00113 _Tp __sgn = _Tp(1);
00114 _Tp __zeta = _Tp(0);
00115 for (unsigned int __i = 1; __i < 10000000; ++__i)
00116 {
00117 _Tp __term = __sgn / std::pow(__i, __s);
00118 if (std::abs(__term) < std::numeric_limits<_Tp>::epsilon())
00119 break;
00120 __zeta += __term;
00121 __sgn *= _Tp(-1);
00122 }
00123 __zeta /= _Tp(1) - std::pow(_Tp(2), _Tp(1) - __s);
00124
00125 return __zeta;
00126 }
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151 template<typename _Tp>
00152 _Tp
00153 __riemann_zeta_glob(const _Tp __s)
00154 {
00155 _Tp __zeta = _Tp(0);
00156
00157 const _Tp __eps = std::numeric_limits<_Tp>::epsilon();
00158
00159 const _Tp __max_bincoeff = std::numeric_limits<_Tp>::max_exponent10
00160 * std::log(_Tp(10)) - _Tp(1);
00161
00162
00163
00164 if (__s < _Tp(0))
00165 {
00166 #if _GLIBCXX_USE_C99_MATH_TR1
00167 if (std::tr1::fmod(__s,_Tp(2)) == _Tp(0))
00168 return _Tp(0);
00169 else
00170 #endif
00171 {
00172 _Tp __zeta = __riemann_zeta_glob(_Tp(1) - __s);
00173 __zeta *= std::pow(_Tp(2)
00174 * __numeric_constants<_Tp>::__pi(), __s)
00175 * std::sin(__numeric_constants<_Tp>::__pi_2() * __s)
00176 #if _GLIBCXX_USE_C99_MATH_TR1
00177 * std::exp(std::tr1::lgamma(_Tp(1) - __s))
00178 #else
00179 * std::exp(__log_gamma(_Tp(1) - __s))
00180 #endif
00181 / __numeric_constants<_Tp>::__pi();
00182 return __zeta;
00183 }
00184 }
00185
00186 _Tp __num = _Tp(0.5L);
00187 const unsigned int __maxit = 10000;
00188 for (unsigned int __i = 0; __i < __maxit; ++__i)
00189 {
00190 bool __punt = false;
00191 _Tp __sgn = _Tp(1);
00192 _Tp __term = _Tp(0);
00193 for (unsigned int __j = 0; __j <= __i; ++__j)
00194 {
00195 #if _GLIBCXX_USE_C99_MATH_TR1
00196 _Tp __bincoeff = std::tr1::lgamma(_Tp(1 + __i))
00197 - std::tr1::lgamma(_Tp(1 + __j))
00198 - std::tr1::lgamma(_Tp(1 + __i - __j));
00199 #else
00200 _Tp __bincoeff = __log_gamma(_Tp(1 + __i))
00201 - __log_gamma(_Tp(1 + __j))
00202 - __log_gamma(_Tp(1 + __i - __j));
00203 #endif
00204 if (__bincoeff > __max_bincoeff)
00205 {
00206
00207 __punt = true;
00208 break;
00209 }
00210 __bincoeff = std::exp(__bincoeff);
00211 __term += __sgn * __bincoeff * std::pow(_Tp(1 + __j), -__s);
00212 __sgn *= _Tp(-1);
00213 }
00214 if (__punt)
00215 break;
00216 __term *= __num;
00217 __zeta += __term;
00218 if (std::abs(__term/__zeta) < __eps)
00219 break;
00220 __num *= _Tp(0.5L);
00221 }
00222
00223 __zeta /= _Tp(1) - std::pow(_Tp(2), _Tp(1) - __s);
00224
00225 return __zeta;
00226 }
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246 template<typename _Tp>
00247 _Tp
00248 __riemann_zeta_product(const _Tp __s)
00249 {
00250 static const _Tp __prime[] = {
00251 _Tp(2), _Tp(3), _Tp(5), _Tp(7), _Tp(11), _Tp(13), _Tp(17), _Tp(19),
00252 _Tp(23), _Tp(29), _Tp(31), _Tp(37), _Tp(41), _Tp(43), _Tp(47),
00253 _Tp(53), _Tp(59), _Tp(61), _Tp(67), _Tp(71), _Tp(73), _Tp(79),
00254 _Tp(83), _Tp(89), _Tp(97), _Tp(101), _Tp(103), _Tp(107), _Tp(109)
00255 };
00256 static const unsigned int __num_primes = sizeof(__prime) / sizeof(_Tp);
00257
00258 _Tp __zeta = _Tp(1);
00259 for (unsigned int __i = 0; __i < __num_primes; ++__i)
00260 {
00261 const _Tp __fact = _Tp(1) - std::pow(__prime[__i], -__s);
00262 __zeta *= __fact;
00263 if (_Tp(1) - __fact < std::numeric_limits<_Tp>::epsilon())
00264 break;
00265 }
00266
00267 __zeta = _Tp(1) / __zeta;
00268
00269 return __zeta;
00270 }
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287 template<typename _Tp>
00288 _Tp
00289 __riemann_zeta(const _Tp __s)
00290 {
00291 if (__isnan(__s))
00292 return std::numeric_limits<_Tp>::quiet_NaN();
00293 else if (__s == _Tp(1))
00294 return std::numeric_limits<_Tp>::infinity();
00295 else if (__s < -_Tp(19))
00296 {
00297 _Tp __zeta = __riemann_zeta_product(_Tp(1) - __s);
00298 __zeta *= std::pow(_Tp(2) * __numeric_constants<_Tp>::__pi(), __s)
00299 * std::sin(__numeric_constants<_Tp>::__pi_2() * __s)
00300 #if _GLIBCXX_USE_C99_MATH_TR1
00301 * std::exp(std::tr1::lgamma(_Tp(1) - __s))
00302 #else
00303 * std::exp(__log_gamma(_Tp(1) - __s))
00304 #endif
00305 / __numeric_constants<_Tp>::__pi();
00306 return __zeta;
00307 }
00308 else if (__s < _Tp(20))
00309 {
00310
00311 bool __glob = true;
00312 if (__glob)
00313 return __riemann_zeta_glob(__s);
00314 else
00315 {
00316 if (__s > _Tp(1))
00317 return __riemann_zeta_sum(__s);
00318 else
00319 {
00320 _Tp __zeta = std::pow(_Tp(2)
00321 * __numeric_constants<_Tp>::__pi(), __s)
00322 * std::sin(__numeric_constants<_Tp>::__pi_2() * __s)
00323 #if _GLIBCXX_USE_C99_MATH_TR1
00324 * std::tr1::tgamma(_Tp(1) - __s)
00325 #else
00326 * std::exp(__log_gamma(_Tp(1) - __s))
00327 #endif
00328 * __riemann_zeta_sum(_Tp(1) - __s);
00329 return __zeta;
00330 }
00331 }
00332 }
00333 else
00334 return __riemann_zeta_product(__s);
00335 }
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359 template<typename _Tp>
00360 _Tp
00361 __hurwitz_zeta_glob(const _Tp __a, const _Tp __s)
00362 {
00363 _Tp __zeta = _Tp(0);
00364
00365 const _Tp __eps = std::numeric_limits<_Tp>::epsilon();
00366
00367 const _Tp __max_bincoeff = std::numeric_limits<_Tp>::max_exponent10
00368 * std::log(_Tp(10)) - _Tp(1);
00369
00370 const unsigned int __maxit = 10000;
00371 for (unsigned int __i = 0; __i < __maxit; ++__i)
00372 {
00373 bool __punt = false;
00374 _Tp __sgn = _Tp(1);
00375 _Tp __term = _Tp(0);
00376 for (unsigned int __j = 0; __j <= __i; ++__j)
00377 {
00378 #if _GLIBCXX_USE_C99_MATH_TR1
00379 _Tp __bincoeff = std::tr1::lgamma(_Tp(1 + __i))
00380 - std::tr1::lgamma(_Tp(1 + __j))
00381 - std::tr1::lgamma(_Tp(1 + __i - __j));
00382 #else
00383 _Tp __bincoeff = __log_gamma(_Tp(1 + __i))
00384 - __log_gamma(_Tp(1 + __j))
00385 - __log_gamma(_Tp(1 + __i - __j));
00386 #endif
00387 if (__bincoeff > __max_bincoeff)
00388 {
00389
00390 __punt = true;
00391 break;
00392 }
00393 __bincoeff = std::exp(__bincoeff);
00394 __term += __sgn * __bincoeff * std::pow(_Tp(__a + __j), -__s);
00395 __sgn *= _Tp(-1);
00396 }
00397 if (__punt)
00398 break;
00399 __term /= _Tp(__i + 1);
00400 if (std::abs(__term / __zeta) < __eps)
00401 break;
00402 __zeta += __term;
00403 }
00404
00405 __zeta /= __s - _Tp(1);
00406
00407 return __zeta;
00408 }
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424 template<typename _Tp>
00425 inline _Tp
00426 __hurwitz_zeta(const _Tp __a, const _Tp __s)
00427 {
00428 return __hurwitz_zeta_glob(__a, __s);
00429 }
00430
00431 }
00432 }
00433 }
00434
00435 #endif // _GLIBCXX_TR1_RIEMANN_ZETA_TCC