brintos

brintos / llvm-project-archived public Read only

0
0
Text · 27.7 KiB · f2219cc Raw
551 lines · plain
1//  Copyright (c) 2006 Xiaogang Zhang2//  Copyright (c) 2017 John Maddock3//  Copyright (c) 2024 Matt Borland4//  Use, modification and distribution are subject to the5//  Boost Software License, Version 1.0. (See accompanying file6//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)7 8#ifndef BOOST_MATH_BESSEL_I0_HPP9#define BOOST_MATH_BESSEL_I0_HPP10 11#ifdef _MSC_VER12#pragma once13#endif14 15#include <boost/math/tools/rational.hpp>16#include <boost/math/tools/big_constant.hpp>17#include <boost/math/tools/assert.hpp>18#include <boost/math/tools/type_traits.hpp>19#include <boost/math/tools/numeric_limits.hpp>20#include <boost/math/tools/precision.hpp>21 22#if defined(__GNUC__) && defined(BOOST_MATH_USE_FLOAT128)23//24// This is the only way we can avoid25// warning: non-standard suffix on floating constant [-Wpedantic]26// when building with -Wall -pedantic.  Neither __extension__27// nor #pragma diagnostic ignored work :(28//29#pragma GCC system_header30#endif31 32// Modified Bessel function of the first kind of order zero33// we use the approximating forms derived in:34// "Rational Approximations for the Modified Bessel Function of the First Kind - I0(x) for Computations with Double Precision"35// by Pavel Holoborodko, 36// see http://www.advanpix.com/2015/11/11/rational-approximations-for-the-modified-bessel-function-of-the-first-kind-i0-computations-double-precision37// The actual coefficients used are our own, and extend Pavel's work to precision's other than double.38 39namespace boost { namespace math { namespace detail{40 41template <typename T>42BOOST_MATH_GPU_ENABLED T bessel_i0(const T& x);43 44template <typename T, int N>45BOOST_MATH_GPU_ENABLED T bessel_i0_imp(const T&, const boost::math::integral_constant<int, N>&)46{47   BOOST_MATH_ASSERT(0);48   return 0;49}50 51template <typename T>52BOOST_MATH_GPU_ENABLED T bessel_i0_imp(const T& x, const boost::math::integral_constant<int, 24>&)53{54   BOOST_MATH_STD_USING55   if(x < 7.75)56   {57      // Max error in interpolated form: 3.929e-0858      // Max Error found at float precision = Poly: 1.991226e-0759      BOOST_MATH_STATIC const float P[] = {60         1.00000003928615375e+00f,61         2.49999576572179639e-01f,62         2.77785268558399407e-02f,63         1.73560257755821695e-03f,64         6.96166518788906424e-05f,65         1.89645733877137904e-06f,66         4.29455004657565361e-08f,67         3.90565476357034480e-10f,68         1.48095934745267240e-11f69      };70      T a = x * x / 4;71      return a * boost::math::tools::evaluate_polynomial(P, a) + 1;72   }73   else if(x < 50)74   {75      // Max error in interpolated form: 5.195e-0876      // Max Error found at float precision = Poly: 8.502534e-0877      BOOST_MATH_STATIC const float P[] = {78         3.98942651588301770e-01f,79         4.98327234176892844e-02f,80         2.91866904423115499e-02f,81         1.35614940793742178e-02f,82         1.31409251787866793e-01f83      };84      return exp(x) * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x);85   }86   else87   {88      // Max error in interpolated form: 1.782e-0989      // Max Error found at float precision = Poly: 6.473568e-0890      BOOST_MATH_STATIC const float P[] = {91         3.98942391532752700e-01f,92         4.98455950638200020e-02f,93         2.94835666900682535e-02f94      };95      T ex = exp(x / 2);96      T result = ex * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x);97      result *= ex;98      return result;99   }100}101 102template <typename T>103BOOST_MATH_GPU_ENABLED T bessel_i0_imp(const T& x, const boost::math::integral_constant<int, 53>&)104{105   BOOST_MATH_STD_USING106   if(x < 7.75)107   {108      // Bessel I0 over[10 ^ -16, 7.75]109      // Max error in interpolated form : 3.042e-18110      // Max Error found at double precision = Poly : 5.106609e-16 Cheb : 5.239199e-16111      BOOST_MATH_STATIC const double P[] = {112         1.00000000000000000e+00,113         2.49999999999999909e-01,114         2.77777777777782257e-02,115         1.73611111111023792e-03,116         6.94444444453352521e-05,117         1.92901234513219920e-06,118         3.93675991102510739e-08,119         6.15118672704439289e-10,120         7.59407002058973446e-12,121         7.59389793369836367e-14,122         6.27767773636292611e-16,123         4.34709704153272287e-18,124         2.63417742690109154e-20,125         1.13943037744822825e-22,126         9.07926920085624812e-25127      };128      T a = x * x / 4;129      return a * boost::math::tools::evaluate_polynomial(P, a) + 1;130   }131   else if(x < 500)132   {133      // Max error in interpolated form : 1.685e-16134      // Max Error found at double precision = Poly : 2.575063e-16 Cheb : 2.247615e+00135      BOOST_MATH_STATIC const double P[] = {136         3.98942280401425088e-01,137         4.98677850604961985e-02,138         2.80506233928312623e-02,139         2.92211225166047873e-02,140         4.44207299493659561e-02,141         1.30970574605856719e-01,142         -3.35052280231727022e+00,143         2.33025711583514727e+02,144         -1.13366350697172355e+04,145         4.24057674317867331e+05,146         -1.23157028595698731e+07,147         2.80231938155267516e+08,148         -5.01883999713777929e+09,149         7.08029243015109113e+10,150         -7.84261082124811106e+11,151         6.76825737854096565e+12,152         -4.49034849696138065e+13,153         2.24155239966958995e+14,154         -8.13426467865659318e+14,155         2.02391097391687777e+15,156         -3.08675715295370878e+15,157         2.17587543863819074e+15158      };159      return exp(x) * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x);160   }161   else162   {163      // Max error in interpolated form : 2.437e-18164      // Max Error found at double precision = Poly : 1.216719e-16165      BOOST_MATH_STATIC const double P[] = {166         3.98942280401432905e-01,167         4.98677850491434560e-02,168         2.80506308916506102e-02,169         2.92179096853915176e-02,170         4.53371208762579442e-02171      };172      T ex = exp(x / 2);173      T result = ex * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x);174      result *= ex;175      return result;176   }177}178 179template <typename T>180BOOST_MATH_GPU_ENABLED T bessel_i0_imp(const T& x, const boost::math::integral_constant<int, 64>&)181{182   BOOST_MATH_STD_USING183   if(x < 7.75)184   {185      // Bessel I0 over[10 ^ -16, 7.75]186      // Max error in interpolated form : 3.899e-20187      // Max Error found at float80 precision = Poly : 1.770840e-19188      // LCOV_EXCL_START189      BOOST_MATH_STATIC const T P[] = {190         BOOST_MATH_BIG_CONSTANT(T, 64, 9.99999999999999999961011629e-01),191         BOOST_MATH_BIG_CONSTANT(T, 64, 2.50000000000000001321873912e-01),192         BOOST_MATH_BIG_CONSTANT(T, 64, 2.77777777777777703400424216e-02),193         BOOST_MATH_BIG_CONSTANT(T, 64, 1.73611111111112764793802701e-03),194         BOOST_MATH_BIG_CONSTANT(T, 64, 6.94444444444251461247253525e-05),195         BOOST_MATH_BIG_CONSTANT(T, 64, 1.92901234569262206386118739e-06),196         BOOST_MATH_BIG_CONSTANT(T, 64, 3.93675988851131457141005209e-08),197         BOOST_MATH_BIG_CONSTANT(T, 64, 6.15118734688297476454205352e-10),198         BOOST_MATH_BIG_CONSTANT(T, 64, 7.59405797058091016449222685e-12),199         BOOST_MATH_BIG_CONSTANT(T, 64, 7.59406599631719800679835140e-14),200         BOOST_MATH_BIG_CONSTANT(T, 64, 6.27598961062070013516660425e-16),201         BOOST_MATH_BIG_CONSTANT(T, 64, 4.35920318970387940278362992e-18),202         BOOST_MATH_BIG_CONSTANT(T, 64, 2.57372492687715452949437981e-20),203         BOOST_MATH_BIG_CONSTANT(T, 64, 1.33908663475949906992942204e-22),204         BOOST_MATH_BIG_CONSTANT(T, 64, 5.15976668870980234582896010e-25),205         BOOST_MATH_BIG_CONSTANT(T, 64, 3.46240478946376069211156548e-27)206      };207      // LCOV_EXCL_STOP208      T a = x * x / 4;209      return a * boost::math::tools::evaluate_polynomial(P, a) + 1;210   }211   else if(x < 10)212   {213      // Maximum Deviation Found:                     6.906e-21214      // Expected Error Term : -6.903e-21215      // Maximum Relative Change in Control Points : 1.631e-04216      // Max Error found at float80 precision = Poly : 7.811948e-21217      // LCOV_EXCL_START218      BOOST_MATH_STATIC const T Y = 4.051098823547363281250e-01f;219      BOOST_MATH_STATIC const T P[] = {220         BOOST_MATH_BIG_CONSTANT(T, 64, -6.158081780620616479492e-03),221         BOOST_MATH_BIG_CONSTANT(T, 64, 4.883635969834048766148e-02),222         BOOST_MATH_BIG_CONSTANT(T, 64, 7.892782002476195771920e-02),223         BOOST_MATH_BIG_CONSTANT(T, 64, -1.478784996478070170327e+00),224         BOOST_MATH_BIG_CONSTANT(T, 64, 2.988611837308006851257e+01),225         BOOST_MATH_BIG_CONSTANT(T, 64, -4.140133766747436806179e+02),226         BOOST_MATH_BIG_CONSTANT(T, 64, 4.117316447921276453271e+03),227         BOOST_MATH_BIG_CONSTANT(T, 64, -2.942353667455141676001e+04),228         BOOST_MATH_BIG_CONSTANT(T, 64, 1.493482682461387081534e+05),229         BOOST_MATH_BIG_CONSTANT(T, 64, -5.228100538921466124653e+05),230         BOOST_MATH_BIG_CONSTANT(T, 64, 1.195279248600467989454e+06),231         BOOST_MATH_BIG_CONSTANT(T, 64, -1.601530760654337045917e+06),232         BOOST_MATH_BIG_CONSTANT(T, 64, 9.504921137873298402679e+05)233      };234      // LCOV_EXCL_STOP235      return exp(x) * (boost::math::tools::evaluate_polynomial(P, T(1 / x)) + Y) / sqrt(x);236   }237   else if(x < 15)238   {239      // Maximum Deviation Found:                     4.083e-21240      // Expected Error Term : -4.025e-21241      // Maximum Relative Change in Control Points : 1.304e-03242      // Max Error found at float80 precision = Poly : 2.303527e-20243      // LCOV_EXCL_START244      BOOST_MATH_STATIC const T Y = 4.033188819885253906250e-01f;245      BOOST_MATH_STATIC const T P[] = {246         BOOST_MATH_BIG_CONSTANT(T, 64, -4.376373876116109401062e-03),247         BOOST_MATH_BIG_CONSTANT(T, 64, 4.982899138682911273321e-02),248         BOOST_MATH_BIG_CONSTANT(T, 64, 3.109477529533515397644e-02),249         BOOST_MATH_BIG_CONSTANT(T, 64, -1.163760580110576407673e-01),250         BOOST_MATH_BIG_CONSTANT(T, 64, 4.776501832837367371883e+00),251         BOOST_MATH_BIG_CONSTANT(T, 64, -1.101478069227776656318e+02),252         BOOST_MATH_BIG_CONSTANT(T, 64, 1.892071912448960299773e+03),253         BOOST_MATH_BIG_CONSTANT(T, 64, -2.417739279982328117483e+04),254         BOOST_MATH_BIG_CONSTANT(T, 64, 2.296963447724067390552e+05),255         BOOST_MATH_BIG_CONSTANT(T, 64, -1.598589306710589358747e+06),256         BOOST_MATH_BIG_CONSTANT(T, 64, 7.903662411851774878322e+06),257         BOOST_MATH_BIG_CONSTANT(T, 64, -2.622677059040339516093e+07),258         BOOST_MATH_BIG_CONSTANT(T, 64, 5.227776578828667629347e+07),259         BOOST_MATH_BIG_CONSTANT(T, 64, -4.727797957441040896878e+07)260      };261      // LCOV_EXCL_STOP262      return exp(x) * (boost::math::tools::evaluate_polynomial(P, T(1 / x)) + Y) / sqrt(x);263   }264   else if(x < 50)265   {266      // Max error in interpolated form: 1.035e-21267      // Max Error found at float80 precision = Poly: 1.885872e-21268      // LCOV_EXCL_START269      BOOST_MATH_STATIC const T Y = 4.011702537536621093750e-01f;270      BOOST_MATH_STATIC const T P[] = {271         BOOST_MATH_BIG_CONSTANT(T, 64, -2.227973351806078464328e-03),272         BOOST_MATH_BIG_CONSTANT(T, 64, 4.986778486088017419036e-02),273         BOOST_MATH_BIG_CONSTANT(T, 64, 2.805066823812285310011e-02),274         BOOST_MATH_BIG_CONSTANT(T, 64, 2.921443721160964964623e-02),275         BOOST_MATH_BIG_CONSTANT(T, 64, 4.517504941996594744052e-02),276         BOOST_MATH_BIG_CONSTANT(T, 64, 6.316922639868793684401e-02),277         BOOST_MATH_BIG_CONSTANT(T, 64, 1.535891099168810015433e+00),278         BOOST_MATH_BIG_CONSTANT(T, 64, -4.706078229522448308087e+01),279         BOOST_MATH_BIG_CONSTANT(T, 64, 1.351015763079160914632e+03),280         BOOST_MATH_BIG_CONSTANT(T, 64, -2.948809013999277355098e+04),281         BOOST_MATH_BIG_CONSTANT(T, 64, 4.967598958582595361757e+05),282         BOOST_MATH_BIG_CONSTANT(T, 64, -6.346924657995383019558e+06),283         BOOST_MATH_BIG_CONSTANT(T, 64, 5.998794574259956613472e+07),284         BOOST_MATH_BIG_CONSTANT(T, 64, -4.016371355801690142095e+08),285         BOOST_MATH_BIG_CONSTANT(T, 64, 1.768791455631826490838e+09),286         BOOST_MATH_BIG_CONSTANT(T, 64, -4.441995678177349895640e+09),287         BOOST_MATH_BIG_CONSTANT(T, 64, 4.482292669974971387738e+09)288      };289      // LCOV_EXCL_STOP290      return exp(x) * (boost::math::tools::evaluate_polynomial(P, T(1 / x)) + Y) / sqrt(x);291   }292   else293   {294      // Bessel I0 over[50, INF]295      // Max error in interpolated form : 5.587e-20296      // Max Error found at float80 precision = Poly : 8.776852e-20297      // LCOV_EXCL_START298      BOOST_MATH_STATIC const T P[] = {299         BOOST_MATH_BIG_CONSTANT(T, 64, 3.98942280401432677955074061e-01),300         BOOST_MATH_BIG_CONSTANT(T, 64, 4.98677850501789875615574058e-02),301         BOOST_MATH_BIG_CONSTANT(T, 64, 2.80506290908675604202206833e-02),302         BOOST_MATH_BIG_CONSTANT(T, 64, 2.92194052159035901631494784e-02),303         BOOST_MATH_BIG_CONSTANT(T, 64, 4.47422430732256364094681137e-02),304         BOOST_MATH_BIG_CONSTANT(T, 64, 9.05971614435738691235525172e-02),305         BOOST_MATH_BIG_CONSTANT(T, 64, 2.29180522595459823234266708e-01),306         BOOST_MATH_BIG_CONSTANT(T, 64, 6.15122547776140254569073131e-01),307         BOOST_MATH_BIG_CONSTANT(T, 64, 7.48491812136365376477357324e+00),308         BOOST_MATH_BIG_CONSTANT(T, 64, -2.45569740166506688169730713e+02),309         BOOST_MATH_BIG_CONSTANT(T, 64, 9.66857566379480730407063170e+03),310         BOOST_MATH_BIG_CONSTANT(T, 64, -2.71924083955641197750323901e+05),311         BOOST_MATH_BIG_CONSTANT(T, 64, 5.74276685704579268845870586e+06),312         BOOST_MATH_BIG_CONSTANT(T, 64, -8.89753803265734681907148778e+07),313         BOOST_MATH_BIG_CONSTANT(T, 64, 9.82590905134996782086242180e+08),314         BOOST_MATH_BIG_CONSTANT(T, 64, -7.30623197145529889358596301e+09),315         BOOST_MATH_BIG_CONSTANT(T, 64, 3.27310000726207055200805893e+10),316         BOOST_MATH_BIG_CONSTANT(T, 64, -6.64365417189215599168817064e+10)317      };318      // LCOV_EXCL_STOP319      T ex = exp(x / 2);320      T result = ex * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x);321      result *= ex;322      return result;323   }324}325 326template <typename T>327BOOST_MATH_GPU_ENABLED T bessel_i0_imp(const T& x, const boost::math::integral_constant<int, 113>&)328{329   BOOST_MATH_STD_USING330   if(x < 7.75)331   {332      // Bessel I0 over[10 ^ -34, 7.75]333      // Max error in interpolated form : 1.274e-34334      // Max Error found at float128 precision = Poly : 3.096091e-34335      // LCOV_EXCL_START336      BOOST_MATH_STATIC const T P[] = {337         BOOST_MATH_BIG_CONSTANT(T, 113, 1.0000000000000000000000000000000001273856e+00),338         BOOST_MATH_BIG_CONSTANT(T, 113, 2.4999999999999999999999999999999107477496e-01),339         BOOST_MATH_BIG_CONSTANT(T, 113, 2.7777777777777777777777777777881795230918e-02),340         BOOST_MATH_BIG_CONSTANT(T, 113, 1.7361111111111111111111111106290091648808e-03),341         BOOST_MATH_BIG_CONSTANT(T, 113, 6.9444444444444444444444445629960334523101e-05),342         BOOST_MATH_BIG_CONSTANT(T, 113, 1.9290123456790123456790105563456483249753e-06),343         BOOST_MATH_BIG_CONSTANT(T, 113, 3.9367598891408415217940836339080514004844e-08),344         BOOST_MATH_BIG_CONSTANT(T, 113, 6.1511873267825648777900014857992724731476e-10),345         BOOST_MATH_BIG_CONSTANT(T, 113, 7.5940584281266233066162999610732449709209e-12),346         BOOST_MATH_BIG_CONSTANT(T, 113, 7.5940584281266232783124723601470051895304e-14),347         BOOST_MATH_BIG_CONSTANT(T, 113, 6.2760813455591936763439337059117957836078e-16),348         BOOST_MATH_BIG_CONSTANT(T, 113, 4.3583898233049738471136482147779094353096e-18),349         BOOST_MATH_BIG_CONSTANT(T, 113, 2.5789288895299965395422423848480340736308e-20),350         BOOST_MATH_BIG_CONSTANT(T, 113, 1.3157800456718804437960453545507623434606e-22),351         BOOST_MATH_BIG_CONSTANT(T, 113, 5.8479113149412360748032684260932041506493e-25),352         BOOST_MATH_BIG_CONSTANT(T, 113, 2.2843403488398038539283241944594140493394e-27),353         BOOST_MATH_BIG_CONSTANT(T, 113, 7.9042925594356556196790242908697582021825e-30),354         BOOST_MATH_BIG_CONSTANT(T, 113, 2.4395919891312152120710245152115597111101e-32),355         BOOST_MATH_BIG_CONSTANT(T, 113, 6.7580986145276689333214547502373003196707e-35),356         BOOST_MATH_BIG_CONSTANT(T, 113, 1.6886514018062348877723837017198859723889e-37),357         BOOST_MATH_BIG_CONSTANT(T, 113, 3.8540558465757554512570197585002702777999e-40),358         BOOST_MATH_BIG_CONSTANT(T, 113, 7.4684706070226893763741850944911705726436e-43),359         BOOST_MATH_BIG_CONSTANT(T, 113, 2.0210715309399646335858150349406935414314e-45)360      };361      // LCOV_EXCL_STOP362      T a = x * x / 4;363      return a * boost::math::tools::evaluate_polynomial(P, a) + 1;364   }365   else if(x < 15)366   {367      // Bessel I0 over[7.75, 15]368      // Max error in interpolated form : 7.534e-35369      // Max Error found at float128 precision = Poly : 6.123912e-34370      // LCOV_EXCL_START371      BOOST_MATH_STATIC const T P[] = {372         BOOST_MATH_BIG_CONSTANT(T, 113, 9.9999999999999999992388573069504617493518e-01),373         BOOST_MATH_BIG_CONSTANT(T, 113, 2.5000000000000000007304739268173096975340e-01),374         BOOST_MATH_BIG_CONSTANT(T, 113, 2.7777777777777777744261405400543564492074e-02),375         BOOST_MATH_BIG_CONSTANT(T, 113, 1.7361111111111111209006987259719750726867e-03),376         BOOST_MATH_BIG_CONSTANT(T, 113, 6.9444444444444442399703186871329381908321e-05),377         BOOST_MATH_BIG_CONSTANT(T, 113, 1.9290123456790126709286741580242189785431e-06),378         BOOST_MATH_BIG_CONSTANT(T, 113, 3.9367598891408374246503061422528266924389e-08),379         BOOST_MATH_BIG_CONSTANT(T, 113, 6.1511873267826068395343047827801353170966e-10),380         BOOST_MATH_BIG_CONSTANT(T, 113, 7.5940584281262673459688011737168286944521e-12),381         BOOST_MATH_BIG_CONSTANT(T, 113, 7.5940584281291583769928563167645746144508e-14),382         BOOST_MATH_BIG_CONSTANT(T, 113, 6.2760813455438840231126529638737436950274e-16),383         BOOST_MATH_BIG_CONSTANT(T, 113, 4.3583898233839583885132809584770578894948e-18),384         BOOST_MATH_BIG_CONSTANT(T, 113, 2.5789288891798658971960571838369339742994e-20),385         BOOST_MATH_BIG_CONSTANT(T, 113, 1.3157800470129311623308216856009970266088e-22),386         BOOST_MATH_BIG_CONSTANT(T, 113, 5.8479112701534604520063520412207286692581e-25),387         BOOST_MATH_BIG_CONSTANT(T, 113, 2.2843404822552330714586265081801727491890e-27),388         BOOST_MATH_BIG_CONSTANT(T, 113, 7.9042888166225242675881424439818162458179e-30),389         BOOST_MATH_BIG_CONSTANT(T, 113, 2.4396027771820721384198604723320045236973e-32),390         BOOST_MATH_BIG_CONSTANT(T, 113, 6.7577659910606076328136207973456511895030e-35),391         BOOST_MATH_BIG_CONSTANT(T, 113, 1.6896548123724136624716224328803899914646e-37),392         BOOST_MATH_BIG_CONSTANT(T, 113, 3.8285850162160539150210466453921758781984e-40),393         BOOST_MATH_BIG_CONSTANT(T, 113, 7.9419071894227736216423562425429524883562e-43),394         BOOST_MATH_BIG_CONSTANT(T, 113, 1.4720374049498608905571855665134539425038e-45),395         BOOST_MATH_BIG_CONSTANT(T, 113, 2.7763533278527958112907118930154738930378e-48),396         BOOST_MATH_BIG_CONSTANT(T, 113, 3.1213839473168678646697528580511702663617e-51),397         BOOST_MATH_BIG_CONSTANT(T, 113, 1.0648035313124146852372607519737686740964e-53),398         -BOOST_MATH_BIG_CONSTANT(T, 113, 5.1255595184052024349371058585102280860878e-57),399         BOOST_MATH_BIG_CONSTANT(T, 113, 3.4652470895944157957727948355523715335882e-59)400      };401      // LCOV_EXCL_STOP402      T a = x * x / 4;403      return a * boost::math::tools::evaluate_polynomial(P, a) + 1;404   }405   else if(x < 30)406   {407      // Max error in interpolated form : 1.808e-34408      // Max Error found at float128 precision = Poly : 2.399403e-34409      // LCOV_EXCL_START410      BOOST_MATH_STATIC const T P[] = {411         BOOST_MATH_BIG_CONSTANT(T, 113, 3.9894228040870793650581242239624530714032e-01),412         BOOST_MATH_BIG_CONSTANT(T, 113, 4.9867780576714783790784348982178607842250e-02),413         BOOST_MATH_BIG_CONSTANT(T, 113, 2.8051948347934462928487999569249907599510e-02),414         BOOST_MATH_BIG_CONSTANT(T, 113, 2.8971143420388958551176254291160976367263e-02),415         BOOST_MATH_BIG_CONSTANT(T, 113, 7.8197359701715582763961322341827341098897e-02),416         BOOST_MATH_BIG_CONSTANT(T, 113, -3.3430484862908317377522273217643346601271e+00),417         BOOST_MATH_BIG_CONSTANT(T, 113, 2.7884507603213662610604413960838990199224e+02),418         BOOST_MATH_BIG_CONSTANT(T, 113, -1.8304926482356755790062999202373909300514e+04),419         BOOST_MATH_BIG_CONSTANT(T, 113, 9.8867173178574875515293357145875120137676e+05),420         BOOST_MATH_BIG_CONSTANT(T, 113, -4.4261178812193528551544261731796888257644e+07),421         BOOST_MATH_BIG_CONSTANT(T, 113, 1.6453010340778116475788083817762403540097e+09),422         BOOST_MATH_BIG_CONSTANT(T, 113, -5.0432401330113978669454035365747869477960e+10),423         BOOST_MATH_BIG_CONSTANT(T, 113, 1.2462165331309799059332310595587606836357e+12),424         BOOST_MATH_BIG_CONSTANT(T, 113, -2.3299800389951335932792950236410844978273e+13),425         BOOST_MATH_BIG_CONSTANT(T, 113, 2.5748218240248714177527965706790413406639e+14),426         BOOST_MATH_BIG_CONSTANT(T, 113, 1.8330014378766930869945511450377736037385e+15),427         BOOST_MATH_BIG_CONSTANT(T, 113, -1.8494610073827453236940544799030787866218e+17),428         BOOST_MATH_BIG_CONSTANT(T, 113, 5.7244661371420647691301043350229977856476e+18),429         BOOST_MATH_BIG_CONSTANT(T, 113, -1.2386378807889388140099109087465781254321e+20),430         BOOST_MATH_BIG_CONSTANT(T, 113, 2.1104000573102013529518477353943384110982e+21),431         BOOST_MATH_BIG_CONSTANT(T, 113, -2.9426541092239879262282594572224300191016e+22),432         BOOST_MATH_BIG_CONSTANT(T, 113, 3.4061439136301913488512592402635688101020e+23),433         BOOST_MATH_BIG_CONSTANT(T, 113, -3.2836554760521986358980180942859101564671e+24),434         BOOST_MATH_BIG_CONSTANT(T, 113, 2.6270285589905206294944214795661236766988e+25),435         BOOST_MATH_BIG_CONSTANT(T, 113, -1.7278631455211972017740134341610659484259e+26),436         BOOST_MATH_BIG_CONSTANT(T, 113, 9.1971734473772196124736986948034978906801e+26),437         BOOST_MATH_BIG_CONSTANT(T, 113, -3.8669270707172568763908838463689093500098e+27),438         BOOST_MATH_BIG_CONSTANT(T, 113, 1.2368879358870281916900125550129211146626e+28),439         BOOST_MATH_BIG_CONSTANT(T, 113, -2.8296235063297831758204519071113999839858e+28),440         BOOST_MATH_BIG_CONSTANT(T, 113, 4.1253861666023020670144616019148954773662e+28),441         BOOST_MATH_BIG_CONSTANT(T, 113, -2.8809536950051955163648980306847791014734e+28) 442      };443      // LCOV_EXCL_STOP444      return exp(x) * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x);445   }446   else if(x < 100)447   {448      // Bessel I0 over[30, 100]449      // Max error in interpolated form : 1.487e-34450      // Max Error found at float128 precision = Poly : 1.929924e-34451      // LCOV_EXCL_START452      BOOST_MATH_STATIC const T P[] = {453         BOOST_MATH_BIG_CONSTANT(T, 113, 3.9894228040143267793996798658172135362278e-01),454         BOOST_MATH_BIG_CONSTANT(T, 113, 4.9867785050179084714910130342157246539820e-02),455         BOOST_MATH_BIG_CONSTANT(T, 113, 2.8050629090725751585266360464766768437048e-02),456         BOOST_MATH_BIG_CONSTANT(T, 113, 2.9219405302833158254515212437025679637597e-02),457         BOOST_MATH_BIG_CONSTANT(T, 113, 4.4742214371598631578107310396249912330627e-02),458         BOOST_MATH_BIG_CONSTANT(T, 113, 9.0602983776478659136184969363625092585520e-02),459         BOOST_MATH_BIG_CONSTANT(T, 113, 2.2839507231977478205885469900971893734770e-01),460         BOOST_MATH_BIG_CONSTANT(T, 113, 6.8925739165733823730525449511456529001868e-01),461         BOOST_MATH_BIG_CONSTANT(T, 113, 2.4238082222874015159424842335385854632223e+00),462         BOOST_MATH_BIG_CONSTANT(T, 113, 9.6759648427182491050716309699208988458050e+00),463         BOOST_MATH_BIG_CONSTANT(T, 113, 4.7292246491169360014875196108746167872215e+01),464         BOOST_MATH_BIG_CONSTANT(T, 113, 3.1001411442786230340015781205680362993575e+01),465         BOOST_MATH_BIG_CONSTANT(T, 113, 9.8277628835804873490331739499978938078848e+03),466         BOOST_MATH_BIG_CONSTANT(T, 113, -3.1208326312801432038715638596517882759639e+05),467         BOOST_MATH_BIG_CONSTANT(T, 113, 9.4813611580683862051838126076298945680803e+06),468         BOOST_MATH_BIG_CONSTANT(T, 113, -2.1278197693321821164135890132925119054391e+08),469         BOOST_MATH_BIG_CONSTANT(T, 113, 3.3190303792682886967459489059860595063574e+09),470         BOOST_MATH_BIG_CONSTANT(T, 113, -2.1580767338646580750893606158043485767644e+10),471         BOOST_MATH_BIG_CONSTANT(T, 113, -5.0256008808415702780816006134784995506549e+11),472         BOOST_MATH_BIG_CONSTANT(T, 113, 1.9044186472918017896554580836514681614475e+13),473         BOOST_MATH_BIG_CONSTANT(T, 113, -3.2521078890073151875661384381880225635135e+14),474         BOOST_MATH_BIG_CONSTANT(T, 113, 3.3620352486836976842181057590770636605454e+15),475         BOOST_MATH_BIG_CONSTANT(T, 113, -2.0375525734060401555856465179734887312420e+16),476         BOOST_MATH_BIG_CONSTANT(T, 113, 5.6392664899881014534361728644608549445131e+16)477      };478      // LCOV_EXCL_STOP479      return exp(x) * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x);480   }481   else482   {483      // Bessel I0 over[100, INF]484      // Max error in interpolated form : 5.459e-35485      // Max Error found at float128 precision = Poly : 1.472240e-34486      // LCOV_EXCL_START487      BOOST_MATH_STATIC const T P[] = {488         BOOST_MATH_BIG_CONSTANT(T, 113, 3.9894228040143267793994605993438166526772e-01),489         BOOST_MATH_BIG_CONSTANT(T, 113, 4.9867785050179084742493257495245185241487e-02),490         BOOST_MATH_BIG_CONSTANT(T, 113, 2.8050629090725735167652437695397756897920e-02),491         BOOST_MATH_BIG_CONSTANT(T, 113, 2.9219405302839307466358297347675795965363e-02),492         BOOST_MATH_BIG_CONSTANT(T, 113, 4.4742214369972689474366968442268908028204e-02),493         BOOST_MATH_BIG_CONSTANT(T, 113, 9.0602984099194778006610058410222616383078e-02),494         BOOST_MATH_BIG_CONSTANT(T, 113, 2.2839502241666629677015839125593079416327e-01),495         BOOST_MATH_BIG_CONSTANT(T, 113, 6.8926354981801627920292655818232972385750e-01),496         BOOST_MATH_BIG_CONSTANT(T, 113, 2.4231921590621824187100989532173995000655e+00),497         BOOST_MATH_BIG_CONSTANT(T, 113, 9.7264260959693775207585700654645245723497e+00),498         BOOST_MATH_BIG_CONSTANT(T, 113, 4.3890136225398811195878046856373030127018e+01),499         BOOST_MATH_BIG_CONSTANT(T, 113, 2.1999720924619285464910452647408431234369e+02),500         BOOST_MATH_BIG_CONSTANT(T, 113, 1.2076909538525038580501368530598517194748e+03),501         BOOST_MATH_BIG_CONSTANT(T, 113, 7.5684635141332367730007149159063086133399e+03),502         BOOST_MATH_BIG_CONSTANT(T, 113, 3.5178192543258299267923025833141286569141e+04),503         BOOST_MATH_BIG_CONSTANT(T, 113, 6.2966297919851965784482163987240461837728e+05) 504      };505      // LCOV_EXCL_STOP506      T ex = exp(x / 2);507      T result = ex * boost::math::tools::evaluate_polynomial(P, T(1 / x)) / sqrt(x);508      result *= ex;509      return result;510   }511}512 513template <typename T>514BOOST_MATH_GPU_ENABLED T bessel_i0_imp(const T& x, const boost::math::integral_constant<int, 0>&)515{516   if(boost::math::tools::digits<T>() <= 24)517      return bessel_i0_imp(x, boost::math::integral_constant<int, 24>());518   else if(boost::math::tools::digits<T>() <= 53)519      return bessel_i0_imp(x, boost::math::integral_constant<int, 53>());520   else if(boost::math::tools::digits<T>() <= 64)521      return bessel_i0_imp(x, boost::math::integral_constant<int, 64>());522   else if(boost::math::tools::digits<T>() <= 113)523      return bessel_i0_imp(x, boost::math::integral_constant<int, 113>());524   BOOST_MATH_ASSERT(0);525   return 0;526}527 528template <typename T>529BOOST_MATH_GPU_ENABLED inline T bessel_i0(const T& x)530{531   typedef boost::math::integral_constant<int,532      ((boost::math::numeric_limits<T>::digits == 0) || (boost::math::numeric_limits<T>::radix != 2)) ?533      0 :534      boost::math::numeric_limits<T>::digits <= 24 ?535      24 :536      boost::math::numeric_limits<T>::digits <= 53 ?537      53 :538      boost::math::numeric_limits<T>::digits <= 64 ?539      64 :540      boost::math::numeric_limits<T>::digits <= 113 ?541      113 : -1542   > tag_type;543 544   return bessel_i0_imp(x, tag_type());545}546 547}}} // namespaces548 549#endif // BOOST_MATH_BESSEL_I0_HPP550 551