expint.hpp

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

HPP
1,515
字号
{   typedef T result_type;   expint_series(unsigned k_, T z_, T x_k_, T denom_, T fact_)       : k(k_), z(z_), x_k(x_k_), denom(denom_), fact(fact_){}   T operator()()   {      x_k *= -z;      denom += 1;      fact *= ++k;      return x_k / (denom * fact);   }private:   unsigned k;   T z;   T x_k;   T denom;   T fact;};template <class T, class Policy>inline T expint_as_series(unsigned n, T z, const Policy& pol){   BOOST_MATH_STD_USING   boost::uintmax_t max_iter = policies::get_max_series_iterations<Policy>();   BOOST_MATH_INSTRUMENT_VARIABLE(z)   T result = 0;   T x_k = -1;   T denom = T(1) - n;   T fact = 1;   unsigned k = 0;   for(; k < n - 1;)   {      result += x_k / (denom * fact);      denom += 1;      x_k *= -z;      fact *= ++k;   }   BOOST_MATH_INSTRUMENT_VARIABLE(result)   result += pow(-z, static_cast<T>(n - 1))       * (boost::math::digamma(static_cast<T>(n)) - log(z)) / fact;   BOOST_MATH_INSTRUMENT_VARIABLE(result)   expint_series<T> s(k, z, x_k, denom, fact);   result = tools::sum_series(s, policies::digits<T, Policy>(), max_iter, result);   policies::check_series_iterations("boost::math::expint_series<%1%>(unsigned,%1%)", max_iter, pol);   BOOST_MATH_INSTRUMENT_VARIABLE(result)   BOOST_MATH_INSTRUMENT_VARIABLE(max_iter)   return result;}template <class T, class Policy, class Tag>T expint_imp(unsigned n, T z, const Policy& pol, const Tag& tag){   BOOST_MATH_STD_USING   static const char* function = "boost::math::expint<%1%>(unsigned, %1%)";   if(z < 0)      return policies::raise_domain_error<T>(function, "Function requires z >= 0 but got %1%.", z, pol);   if(z == 0)      return n == 1 ? policies::raise_overflow_error<T>(function, 0, pol) : 1 / (static_cast<T>(n - 1));   T result;   bool f;   if(n < 3)   {      f = z < 0.5;   }   else   {      f = z < (static_cast<T>(n - 2) / static_cast<T>(n - 1));   }#ifdef BOOST_MSVC#  pragma warning(push)#  pragma warning(disable:4127) // conditional expression is constant#endif   if(n == 0)      result = exp(-z) / z;   else if((n == 1) && (Tag::value))   {      result = expint_1_rational(z, tag);   }   else if(f)      result = expint_as_series(n, z, pol);   else      result = expint_as_fraction(n, z, pol);#ifdef BOOST_MSVC#  pragma warning(pop)#endif   return result;}template <class T>struct expint_i_series{   typedef T result_type;   expint_i_series(T z_) : k(0), z_k(1), z(z_){}   T operator()()   {      z_k *= z / ++k;      return z_k / k;   }private:   unsigned k;   T z_k;   T z;};template <class T, class Policy>T expint_i_as_series(T z, const Policy& pol){   BOOST_MATH_STD_USING   T result = log(z); // (log(z) - log(1 / z)) / 2;   result += constants::euler<T>();   expint_i_series<T> s(z);   boost::uintmax_t max_iter = policies::get_max_series_iterations<Policy>();   result = tools::sum_series(s, policies::digits<T, Policy>(), max_iter, result);   policies::check_series_iterations("boost::math::expint_i_series<%1%>(%1%)", max_iter, pol);   return result;}template <class T, class Policy, class Tag>T expint_i_imp(T z, const Policy& pol, const Tag& tag){   static const char* function = "boost::math::expint<%1%>(%1%)";   if(z < 0)      return -expint_imp(1, -z, pol, tag);   if(z == 0)      return -policies::raise_overflow_error<T>(function, 0, pol);   return expint_i_as_series(z, pol);}template <class T, class Policy>T expint_i_imp(T z, const Policy& pol, const mpl::int_<53>& tag){   BOOST_MATH_STD_USING   static const char* function = "boost::math::expint<%1%>(%1%)";   if(z < 0)      return -expint_imp(1, -z, pol, tag);   if(z == 0)      return -policies::raise_overflow_error<T>(function, 0, pol);   T result;   if(z <= 6)   {      // Maximum Deviation Found:                     2.852e-18      // Expected Error Term:                         2.852e-18      // Max Error found at double precision =        Poly: 2.636335e-16   Cheb: 4.187027e-16      static const T P[10] = {             2.98677224343598593013L,         0.356343618769377415068L,         0.780836076283730801839L,         0.114670926327032002811L,         0.0499434773576515260534L,         0.00726224593341228159561L,         0.00115478237227804306827L,         0.000116419523609765200999L,         0.798296365679269702435e-5L,         0.2777056254402008721e-6L      };      static const T Q[8] = {             1L,         -1.17090412365413911947L,         0.62215109846016746276L,         -0.195114782069495403315L,         0.0391523431392967238166L,         -0.00504800158663705747345L,         0.000389034007436065401822L,         -0.138972589601781706598e-4L      };      static const T r1 = static_cast<T>(1677624236387711.0L) / 4503599627370496uLL;      static const T r2 = 0.131401834143860282009280387409357165515556574352422001206362e-16L;      static const T r = static_cast<T>(0.372507410781366634461991866580119133535689497771654051555657435242200120636201854384926049951548942392L);      T t = (z / 3) - 1;      result = tools::evaluate_polynomial(P, t)          / tools::evaluate_polynomial(Q, t);      t = (z - r1) - r2;      result *= t;      if(fabs(t) < 0.1)      {         result += boost::math::log1p(t / r);      }      else      {         result += log(z / r);      }   }   else if (z <= 10)   {      // Maximum Deviation Found:                     6.546e-17      // Expected Error Term:                         6.546e-17      // Max Error found at double precision =        Poly: 6.890169e-17   Cheb: 6.772128e-17      static const T Y = 1.158985137939453125F;      static const T P[8] = {             0.00139324086199402804173L,         -0.0349921221823888744966L,         -0.0264095520754134848538L,         -0.00761224003005476438412L,         -0.00247496209592143627977L,         -0.000374885917942100256775L,         -0.554086272024881826253e-4L,         -0.396487648924804510056e-5L      };      static const T Q[8] = {             1L,         0.744625566823272107711L,         0.329061095011767059236L,         0.100128624977313872323L,         0.0223851099128506347278L,         0.00365334190742316650106L,         0.000402453408512476836472L,         0.263649630720255691787e-4L      };      T t = z / 2 - 4;      result = Y + tools::evaluate_polynomial(P, t)         / tools::evaluate_polynomial(Q, t);      result *= exp(z) / z;      result += z;   }   else if(z <= 20)   {      // Maximum Deviation Found:                     1.843e-17      // Expected Error Term:                         -1.842e-17      // Max Error found at double precision =        Poly: 4.375868e-17   Cheb: 5.860967e-17      static const T Y = 1.0869731903076171875F;      static const T P[9] = {             -0.00893891094356945667451L,         -0.0484607730127134045806L,         -0.0652810444222236895772L,         -0.0478447572647309671455L,         -0.0226059218923777094596L,         -0.00720603636917482065907L,         -0.00155941947035972031334L,         -0.000209750022660200888349L,         -0.138652200349182596186e-4L      };      static const T Q[9] = {             1L,         1.97017214039061194971L,         1.86232465043073157508L,         1.09601437090337519977L,         0.438873285773088870812L,         0.122537731979686102756L,         0.0233458478275769288159L,         0.00278170769163303669021L,         0.000159150281166108755531L      };      T t = z / 5 - 3;      result = Y + tools::evaluate_polynomial(P, t)         / tools::evaluate_polynomial(Q, t);      result *= exp(z) / z;      result += z;   }   else if(z <= 40)   {      // Maximum Deviation Found:                     5.102e-18      // Expected Error Term:                         5.101e-18      // Max Error found at double precision =        Poly: 1.441088e-16   Cheb: 1.864792e-16      static const T Y = 1.03937530517578125F;      static const T P[9] = {             -0.00356165148914447597995L,         -0.0229930320357982333406L,         -0.0449814350482277917716L,         -0.0453759383048193402336L,         -0.0272050837209380717069L,         -0.00994403059883350813295L,         -0.00207592267812291726961L,         -0.000192178045857733706044L,         -0.113161784705911400295e-9L      };      static const T Q[9] = {             1L,         2.84354408840148561131L,         3.6599610090072393012L,         2.75088464344293083595L,         1.2985244073998398643L,         0.383213198510794507409L,         0.0651165455496281337831L,         0.00488071077519227853585L      };      T t = z / 10 - 3;      result = Y + tools::evaluate_polynomial(P, t)         / tools::evaluate_polynomial(Q, t);      result *= exp(z) / z;      result += z;   }   else   {      // Max Error found at double precision =        3.381886e-17      static const T exp40 = static_cast<T>(2.35385266837019985407899910749034804508871617254555467236651e17L);      static const T Y= 1.013065338134765625F;      static const T P[6] = {             -0.0130653381347656243849L,         0.19029710559486576682L,         94.7365094537197236011L,         -2516.35323679844256203L,         18932.0850014925993025L,         -38703.1431362056714134L      };      static const T Q[7] = {             1L,         61.9733592849439884145L,         -2354.56211323420194283L,         22329.1459489893079041L,         -70126.245140396567133L,         54738.2833147775537106L,         8297.16296356518409347L      };      T t = 1 / z;      result = Y + tools::evaluate_polynomial(P, t)         / tools::evaluate_polynomial(Q, t);      if(z < 41)         result *= exp(z) / z;      else      {         // Avoid premature overflow if we can:         t = z - 40;         if(t > tools::log_max_value<T>())         {            result = policies::raise_overflow_error<T>(function, 0, pol);         }         else         {            result *= exp(z - 40) / z;            if(result > tools::max_value<T>() / exp40)            {               result = policies::raise_overflow_error<T>(function, 0, pol);            }            else            {               result *= exp40;            }         }      }      result += z;   }   return result;}template <class T, class Policy>T expint_i_imp(T z, const Policy& pol, const mpl::int_<64>& tag){   BOOST_MATH_STD_USING   static const char* function = "boost::math::expint<%1%>(%1%)";   if(z < 0)      return -expint_imp(1, -z, pol, tag);   if(z == 0)      return -policies::raise_overflow_error<T>(function, 0, pol);   T result;   if(z <= 6)   {      // Maximum Deviation Found:                     3.883e-21      // Expected Error Term:                         3.883e-21      // Max Error found at long double precision =   Poly: 3.344801e-19   Cheb: 4.989937e-19      static const T P[11] = {             2.98677224343598593764L,         0.25891613550886736592L,         0.789323584998672832285L,         0.092432587824602399339L,         0.0514236978728625906656L,         0.00658477469745132977921L,         0.00124914538197086254233L,         0.000131429679565472408551L,         0.11293331317982763165e-4L,         0.629499283139417444244e-6L,         0.177833045143692498221e-7L      };      static const T Q[9] = {             1L,

⌨️ 快捷键说明

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