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 lbeta(double a, double b) {
63 if (isnan(a) || isnan(b)) {
64 return a;
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 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:15
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