13inline bool rational_integer(exact_rational
const& x) {
return mpz_cmp_ui(mpq_denref(x.native_handle()), 1) == 0; }
14inline unsigned long exact_nonnegative_order(exact_rational
const& x)
16 auto q = x.native_handle();
17 if (!rational_integer(x) || mpq_sgn(q) < 0)
18 throw std::domain_error(
"special function requires a nonnegative integer order");
19 if (!mpz_fits_slong_p(mpq_numref(q)))
throw std::out_of_range(
"special function order does not fit int64_t");
20 return mpz_get_ui(mpq_numref(q));
22inline exact_rational exact_factorial(
unsigned long n)
24 return mpreal_access::rational_result([&](mpq_ptr out) { mpz_fac_ui(mpq_numref(out), n); });
26inline mpreal exact_gamma(exact_rational
const& x)
28 if (x > 0 && rational_integer(x))
return mpreal(exact_factorial(exact_nonnegative_order(x - exact_rational{1})));
29 throw std::logic_error(
"Gamma requires finite precision unless its input is a positive integer");
31inline mpreal exact_zeta(exact_rational
const& x)
33 if (x == 0)
return mpreal(exact_rational{-1} / exact_rational{2});
34 if (x < 0 && rational_integer(x))
36 if (mpz_even_p(mpq_numref(x.native_handle())))
return mpreal{};
39 auto order = exact_nonnegative_order(-x) + 1;
40 return mpreal(-exact_bernoulli(order) / exact_rational{order});
42 throw std::logic_error(
"Zeta requires finite precision except at nonpositive integers");
45template <auto Operation> mpreal special_unary(mpreal
const& x)
47 auto p = x.precision();
50 auto const& q = x.exact_value();
51 if constexpr (same_function_v<Operation, mpfr_gamma>)
52 return exact_gamma(q);
53 else if constexpr (same_function_v<Operation, mpfr_zeta>)
55 else if constexpr (same_function_v<Operation, mpfr_erf> || same_function_v<Operation, mpfr_li2>)
57 if (q == 0)
return mpreal{};
59 else if constexpr (same_function_v<Operation, mpfr_erfc>)
61 if (q == 0)
return mpreal{1};
63 throw std::logic_error(
"special function requires finite working precision");
65 return mpreal_access::finite_result(
p, [&](mpfr_ptr out) { Operation(out, x.native_handle(), MPFR_RNDN); });
67template <auto Operation> mpreal special_unary(mpreal
const& x, Precision
p)
70 return special_unary<Operation>(x.at(
p));
73inline mpreal exact_beta(exact_rational
const& a, exact_rational
const& b)
75 if (a > 0 && b > 0 && (rational_integer(a) || rational_integer(b)))
79 bool const use_a = rational_integer(a) && (!rational_integer(b) || a <= b);
80 auto n = exact_nonnegative_order(use_a ? a : b);
81 auto x = use_a ? b : a;
84 exact_rational result = exact_rational{1} / x;
85 for (
unsigned long k = 1; k < n; ++k)
86 result = result * exact_rational{k} / (x + exact_rational{k});
87 return mpreal(result);
89 throw std::logic_error(
"Beta requires finite precision except for positive rational/integer pairs");
91template <auto Operation> mpreal special_binary(mpreal
const& a, mpreal
const& b)
96 if constexpr (same_function_v<Operation, mpfr_beta>)
97 return exact_beta(a.exact_value(), b.exact_value());
98 else if constexpr (same_function_v<Operation, mpfr_gamma_inc>)
100 if (b == 0)
return exact_gamma(a.exact_value());
102 else if constexpr (same_function_v<Operation, mpfr_agm>)
104 if (a >= 0 && b >= 0)
106 if (a == b)
return a;
107 if (a == 0 || b == 0)
return mpreal{};
110 throw std::logic_error(
"special function requires finite working precision");
112 auto av = a.at(
p), bv = b.at(
p);
113 return mpreal_access::finite_result(
114 p, [&](mpfr_ptr out) { Operation(out, av.native_handle(), bv.native_handle(), MPFR_RNDN); });
116template <auto Operation> mpreal special_binary(mpreal
const& a, mpreal
const& b, Precision
p)
119 return special_binary<Operation>(a.at(
p), b.at(
p));
173 return detail::special_binary<mpfr_gamma_inc>(a, x,
p);
189 if (x == 1 || x == 2)
return {
mpreal{}, 1};
190 throw std::logic_error(
"log-Gamma requires finite precision except at one and two");
193 auto value = detail::mpreal_access::finite_result(
194 p, [&](mpfr_ptr out) { mpfr_lgamma(out, &sign, x.
native_handle(), MPFR_RNDN); });
196 return {std::move(
value), sign};
211template <auto Operation> mpreal integer_bessel(mpreal
const& x, std::int64_t order)
213 auto p = x.precision();
216 if constexpr (same_function_v<Operation, mpfr_jn>)
217 if (x == 0)
return mpreal{order == 0 ? 1 : 0};
218 throw std::logic_error(
"Bessel function requires finite working precision");
220 static_assert(
sizeof(long) >=
sizeof(std::int64_t));
221 return mpreal_access::finite_result(
222 p, [&](mpfr_ptr out) { Operation(out,
static_cast<long>(order), x.native_handle(), MPFR_RNDN); });
229 return detail::integer_bessel<mpfr_jn>(x, detail::math_integer(n));
241 return detail::integer_bessel<mpfr_yn>(x, detail::math_integer(n));
255 auto order = detail::math_integer(n);
256 if (order < 0)
throw std::domain_error(
"factorial requires a nonnegative order");
257 if (
p.is_exact())
return mpreal(detail::exact_factorial(
static_cast<unsigned long>(order)));
258 return detail::mpreal_access::finite_result(
259 p, [&](mpfr_ptr out) { mpfr_fac_ui(out,
static_cast<unsigned long>(order), MPFR_RNDN); });
Exact arithmetic or an explicit binary working precision.
Definition core/precision.hpp:13
Owning exact rational or finite-precision MPFR real, with eager arithmetic.
Definition mpreal.hpp:74
mpreal at(Precision p) const
Definition mpreal.hpp:206
mpfr_srcptr native_handle() const
Borrow an approximate MPFR value; exact and unset states require explicit materialization first.
Definition mpreal.hpp:184
Precision precision() const
Return exact state or the working precision stored by MPFR.
Definition mpreal.hpp:178
locale_t value
Definition data_table.cpp:49
Definition data_table.cpp:8
Definition async/async.hpp:26
bool isnan(mpcomplex const &z)
Definition mpcomplex.hpp:499
mpreal expint(mpreal const &x)
Real exponential integral Ei, with its real principal-value meaning.
Definition mpreal_special.hpp:149
mpreal tgamma(mpreal const &x)
Real Gamma function; exact positive integers produce exact factorials.
Definition mpreal_special.hpp:124
mpreal erf(mpreal const &x)
Error function, retaining exact zero or the input precision.
Definition mpreal_special.hpp:134
mpreal dilog_real(mpreal const &x)
Real part of the dilogarithm; this is not a complex branch-valued API.
Definition mpreal_special.hpp:154
mpreal airy_ai(mpreal const &x)
Real Airy Ai; MPFR recommends arguments with magnitude below about 500.
Definition mpreal_special.hpp:159
R factorial(I n)
Factorial of a checked nonnegative integer, with an explicit native result type.
Definition factorial.hpp:15
bool isinf(mpcomplex const &z)
Definition mpcomplex.hpp:500
mpreal bessel_j(I n, mpreal const &x)
Bessel function of the first kind, with a checked signed integer order.
Definition mpreal_special.hpp:227
lgamma_result< mpreal > lgamma_sign(mpreal const &x)
Log(abs(Gamma(x))) and the sign of Gamma, as owning values.
Definition mpreal_special.hpp:184
mpreal upper_gamma(mpreal const &a, mpreal const &x)
Upper incomplete Gamma, with shape a and lower integration endpoint x.
Definition mpreal_special.hpp:169
constexpr Precision common_precision(Precision a, Precision b)
Combine precisions, treating exact values as neutral and rejecting unequal finite precisions.
Definition core/precision.hpp:57
mpreal zeta(mpreal const &x)
Riemann zeta; nonpositive integer arguments retain exact rational results.
Definition mpreal_special.hpp:144
mpreal erfc(mpreal const &x)
Complementary error function, evaluated without subtracting erf from one.
Definition mpreal_special.hpp:139
mpreal agm(mpreal const &a, mpreal const &x)
Nonnegative real arithmetic-geometric mean.
Definition mpreal_special.hpp:177
mpreal beta(mpreal const &a, mpreal const &x)
Real Beta function; positive rational/integer pairs retain exact values.
Definition mpreal_special.hpp:164
mpreal digamma(mpreal const &x)
Logarithmic derivative of Gamma; finite working precision is required.
Definition mpreal_special.hpp:129
mpreal bessel_y(I n, mpreal const &x)
Bessel function of the second kind, with a checked signed integer order.
Definition mpreal_special.hpp:239
mpreal lgamma(mpreal const &x)
Natural logarithm of abs(Gamma(x)), including negative Gamma values.
Definition mpreal_special.hpp:205
Logarithm of the absolute Gamma value and Gamma's sign.
Definition math_results.hpp:43