Automatic Differentiation
 
Loading...
Searching...
No Matches
lbeta.hpp
Go to the documentation of this file.
1#ifndef STAN_MATH_OPENCL_KERNELS_DEVICE_FUNCTIONS_LBETA_HPP
2#define STAN_MATH_OPENCL_KERNELS_DEVICE_FUNCTIONS_LBETA_HPP
3#ifdef STAN_OPENCL
4
6#include <string>
7
8namespace stan {
9namespace math {
10namespace opencl_kernels {
11
12// \cond
13static constexpr const char* lbeta_device_function
14 = "\n"
15 "#ifndef STAN_MATH_OPENCL_KERNELS_DEVICE_FUNCTIONS_LBETA\n"
16 "#define STAN_MATH_OPENCL_KERNELS_DEVICE_FUNCTIONS_LBETA\n" STRINGIFY(
17 // \endcond
62 double stan_lbeta(double a, double b) {
63 if (isnan(a) || isnan(b)) {
64 return NAN;
65 }
66
67 double x; // x is the smaller of the two
68 double y;
69 if (a < b) {
70 x = a;
71 y = b;
72 } else {
73 x = b;
74 y = a;
75 }
76
77 // Special cases
78 if (x == 0) {
79 return INFINITY;
80 }
81 if (isinf(y)) {
82 return -INFINITY;
83 }
84
85 // For large x or y, separate the lgamma values into Stirling
86 // approximations and appropriate corrections. The Stirling
87 // approximations allow for analytic simplification and the
88 // corrections are added later.
89 //
90 // The overall approach is inspired by the code in R, where the
91 // algorithm is credited to W. Fullerton of Los Alamos Scientific
92 // Laboratory
93 if (y < LGAMMA_STIRLING_DIFF_USEFUL) {
94 // both small
95 return lgamma(x) + lgamma(y) - lgamma(x + y);
96 }
97 double x_over_xy = x / (x + y);
98 double log_xpy = log(x + y);
99 if (x < LGAMMA_STIRLING_DIFF_USEFUL) {
100 // y large, x small
101 double stirling_diff
103 double stirling
104 = (y - 0.5) * log1p(-x_over_xy) + x * (1 - log_xpy);
105 return stirling + lgamma(x) + stirling_diff;
106 }
107
108 // both large
109 double stirling_diff = lgamma_stirling_diff(x)
111 - lgamma_stirling_diff(x + y);
112 double stirling = (x - 0.5) * (log(x) - log_xpy)
113 + y * log1p(-x_over_xy)
114 + 0.5 * (M_LN2 + log(M_PI)) - 0.5 * log(y);
115 return stirling + stirling_diff;
116 }
117 // \cond
118 ) "\n#endif\n"; // NOLINT
119// \endcond
120
121} // namespace opencl_kernels
122} // namespace math
123} // namespace stan
124
125#endif
126#endif
double lgamma_stirling_diff(double x)
Return the difference between log of the gamma function and its Stirling approximation.
double stan_lbeta(double a, double b)
Return the log of the beta function applied to the specified arguments.
Definition lbeta.hpp:62
fvar< T > log(const fvar< T > &x)
Definition log.hpp:18
fvar< T > log1p(const fvar< T > &x)
Definition log1p.hpp:12
fvar< T > lgamma(const fvar< T > &x)
Return the natural logarithm of the gamma function applied to the specified argument.
Definition lgamma.hpp:21
The lgamma implementation in stan-math is based on either the reentrant safe lgamma_r implementation ...
#define STRINGIFY(...)
Definition stringify.hpp:9