void hyp2F1(T& result, const T& a, const T& b, const T& c, const T& x) { // Compute the series representation of hyperg_2f1 taken from // Abramowitz and Stegun 15.1.1. // There are no checks on input range or parameter boundaries. typedef typename boost::multiprecision::detail::canonical<boost::uint32_t, T>::type ui_type; T x_pow_n_div_n_fact(x); T pochham_a (a); T pochham_b (b); T pochham_c (c); T ap (a); T bp (b); T cp (c); eval_multiply(result, pochham_a, pochham_b); eval_divide(result, pochham_c); eval_multiply(result, x_pow_n_div_n_fact); eval_add(result, ui_type(1)); T lim; eval_ldexp(lim, result, 1 - boost::multiprecision::detail::digits2<number<T, et_on> >::value); if(eval_get_sign(lim) < 0) lim.negate(); ui_type n; T term; static const unsigned series_limit = boost::multiprecision::detail::digits2<number<T, et_on> >::value < 100 ? 100 : boost::multiprecision::detail::digits2<number<T, et_on> >::value; // Series expansion of hyperg_2f1(a, b; c; x). for(n = 2; n < series_limit; ++n) { eval_multiply(x_pow_n_div_n_fact, x); eval_divide(x_pow_n_div_n_fact, n); eval_increment(ap); eval_multiply(pochham_a, ap); eval_increment(bp); eval_multiply(pochham_b, bp); eval_increment(cp); eval_multiply(pochham_c, cp); eval_multiply(term, pochham_a, pochham_b); eval_divide(term, pochham_c); eval_multiply(term, x_pow_n_div_n_fact); eval_add(result, term); if(eval_get_sign(term) < 0) term.negate(); if(lim.compare(term) >= 0) break; } if(n > series_limit) BOOST_THROW_EXCEPTION(std::runtime_error("H2F1 failed to converge.")); }
void hyp0F1(T& result, const T& b, const T& x) { typedef typename boost::multiprecision::detail::canonical<boost::int32_t, T>::type si_type; typedef typename boost::multiprecision::detail::canonical<boost::uint32_t, T>::type ui_type; typedef typename T::exponent_type exp_type; typedef typename boost::multiprecision::detail::canonical<exp_type, T>::type canonical_exp_type; typedef typename mpl::front<typename T::float_types>::type fp_type; // Compute the series representation of Hypergeometric0F1 taken from // http://functions.wolfram.com/HypergeometricFunctions/Hypergeometric0F1/06/01/01/ // There are no checks on input range or parameter boundaries. T x_pow_n_div_n_fact(x); T pochham_b (b); T bp (b); eval_divide(result, x_pow_n_div_n_fact, pochham_b); eval_add(result, ui_type(1)); si_type n; T tol; tol = ui_type(1); eval_ldexp(tol, tol, 1 - boost::multiprecision::detail::digits2<number<T, et_on> >::value); eval_multiply(tol, result); if(eval_get_sign(tol) < 0) tol.negate(); T term; static const unsigned series_limit = boost::multiprecision::detail::digits2<number<T, et_on> >::value < 100 ? 100 : boost::multiprecision::detail::digits2<number<T, et_on> >::value; // Series expansion of hyperg_0f1(; b; x). for(n = 2; n < series_limit; ++n) { eval_multiply(x_pow_n_div_n_fact, x); eval_divide(x_pow_n_div_n_fact, n); eval_increment(bp); eval_multiply(pochham_b, bp); eval_divide(term, x_pow_n_div_n_fact, pochham_b); eval_add(result, term); bool neg_term = eval_get_sign(term) < 0; if(neg_term) term.negate(); if(term.compare(tol) <= 0) break; } if(n >= series_limit) BOOST_THROW_EXCEPTION(std::runtime_error("H0F1 Failed to Converge")); }
void hyp1F0(T& H1F0, const T& a, const T& x) { // Compute the series representation of Hypergeometric1F0 taken from // http://functions.wolfram.com/HypergeometricFunctions/Hypergeometric1F0/06/01/01/ // and also see the corresponding section for the power function (i.e. x^a). // There are no checks on input range or parameter boundaries. typedef typename boost::multiprecision::detail::canonical<int, T>::type si_type; typedef typename boost::multiprecision::detail::canonical<unsigned, T>::type ui_type; typedef typename T::exponent_type exp_type; typedef typename boost::multiprecision::detail::canonical<exp_type, T>::type canonical_exp_type; typedef typename mpl::front<typename T::float_types>::type fp_type; BOOST_ASSERT(&H1F0 != &x); BOOST_ASSERT(&H1F0 != &a); T x_pow_n_div_n_fact(x); T pochham_a (a); T ap (a); eval_multiply(H1F0, pochham_a, x_pow_n_div_n_fact); eval_add(H1F0, si_type(1)); T lim; eval_ldexp(lim, H1F0, 1 - boost::multiprecision::detail::digits2<number<T, et_on> >::value); if(eval_get_sign(lim) < 0) lim.negate(); si_type n; T term, part; static const unsigned series_limit = boost::multiprecision::detail::digits2<number<T, et_on> >::value < 100 ? 100 : boost::multiprecision::detail::digits2<number<T, et_on> >::value; // Series expansion of hyperg_1f0(a; ; x). for(n = 2; n < series_limit; n++) { eval_multiply(x_pow_n_div_n_fact, x); eval_divide(x_pow_n_div_n_fact, n); eval_increment(ap); eval_multiply(pochham_a, ap); eval_multiply(term, pochham_a, x_pow_n_div_n_fact); eval_add(H1F0, term); if(eval_get_sign(term) < 0) term.negate(); if(lim.compare(term) >= 0) break; } if(n >= series_limit) BOOST_THROW_EXCEPTION(std::runtime_error("H1F0 failed to converge")); }