1 #ifndef __STAN__PROB__DISTRIBUTIONS__UNIVARIATE__CONTINUOUS__SCALED_INV_CHI_SQUARE_HPP__
2 #define __STAN__PROB__DISTRIBUTIONS__UNIVARIATE__CONTINUOUS__SCALED_INV_CHI_SQUARE_HPP__
4 #include <boost/random/chi_squared_distribution.hpp>
5 #include <boost/random/variate_generator.hpp>
39 template <
bool propto,
40 typename T_y,
typename T_dof,
typename T_scale,
42 typename return_type<T_y,T_dof,T_scale>::type
45 static const char*
function
46 =
"stan::prob::scaled_inv_chi_square_log(%1%)";
61 if (!
check_not_nan(
function, y,
"Random variable", &logp, Policy()))
63 if (!
check_finite(
function, nu,
"Degrees of freedom parameter",
69 if (!
check_finite(
function, s,
"Scale parameter", &logp, Policy()))
71 if (!
check_positive(
function, s,
"Scale parameter", &logp, Policy()))
76 "Degrees of freedom parameter",
90 for (
size_t n = 0; n < N; n++) {
96 using boost::math::digamma;
102 for (
size_t i = 0; i <
length(nu); i++)
104 half_nu[i] = 0.5 *
value_of(nu_vec[i]);
108 for (
size_t i = 0; i <
length(y); i++)
114 for (
size_t i = 0; i <
length(y); i++)
116 inv_y[i] = 1.0 /
value_of(y_vec[i]);
120 for (
size_t i = 0; i <
length(s); i++)
130 for (
size_t i = 0; i <
length(nu); i++) {
132 lgamma_half_nu[i] =
lgamma(half_nu[i]);
134 log_half_nu[i] =
log(half_nu[i]);
136 digamma_half_nu_over_two[i] = digamma(half_nu[i]) * 0.5;
140 operands_and_partials(y, nu, s);
141 for (
size_t n = 0; n < N; n++) {
142 const double s_dbl =
value_of(s_vec[n]);
143 const double nu_dbl =
value_of(nu_vec[n]);
145 logp += half_nu[n] * log_half_nu[n] - lgamma_half_nu[n];
147 logp += nu_dbl * log_s[n];
149 logp -= (half_nu[n]+1.0) * log_y[n];
151 logp -= half_nu[n] * s_dbl*s_dbl * inv_y[n];
154 operands_and_partials.
d_x1[n]
155 += -(half_nu[n] + 1.0) * inv_y[n]
156 + half_nu[n] * s_dbl*s_dbl * inv_y[n]*inv_y[n];
159 operands_and_partials.
d_x2[n]
160 += 0.5 * log_half_nu[n] + 0.5
161 - digamma_half_nu_over_two[n]
164 - 0.5* s_dbl*s_dbl * inv_y[n];
167 operands_and_partials.
d_x3[n]
168 += nu_dbl / s_dbl - nu_dbl * inv_y[n] * s_dbl;
171 return operands_and_partials.
to_var(logp);
174 template <
bool propto,
175 typename T_y,
typename T_dof,
typename T_scale>
180 return scaled_inv_chi_square_log<propto>(y,nu,s,
184 template <
typename T_y,
typename T_dof,
typename T_scale,
190 return scaled_inv_chi_square_log<false>(y,nu,s,Policy());
193 template <
typename T_y,
typename T_dof,
typename T_scale>
197 return scaled_inv_chi_square_log<false>(y,nu,s,
215 template <
typename T_y,
typename T_dof,
typename T_scale,
class Policy>
218 const T_scale& s,
const Policy&) {
223 static const char*
function
224 =
"stan::prob::scaled_inv_chi_square_log(%1%)";
235 if (!
check_not_nan(
function, y,
"Random variable", &P, Policy()))
241 if (!
check_finite(
function, nu,
"Degrees of freedom parameter",
249 if (!
check_finite(
function, s,
"Scale parameter", &P, Policy()))
252 if (!
check_positive(
function, s,
"Scale parameter", &P, Policy()))
257 "Degrees of freedom parameter",
269 operands_and_partials(y, nu, s);
273 + operands_and_partials.
nvaris, 0.0);
280 return operands_and_partials.
to_var(0.0);
284 using boost::math::gamma_p_derivative;
285 using boost::math::gamma_q;
286 using boost::math::digamma;
298 const double half_nu_dbl = 0.5 *
value_of(nu_vec[i]);
299 gamma_vec[i] =
tgamma(half_nu_dbl);
300 digamma_vec[i] = digamma(half_nu_dbl);
306 for (
size_t n = 0; n < N; n++) {
310 if (
value_of(y_vec[n]) == std::numeric_limits<double>::infinity()) {
315 const double y_dbl =
value_of(y_vec[n]);
316 const double y_inv_dbl = 1.0 / y_dbl;
317 const double half_nu_dbl = 0.5 *
value_of(nu_vec[n]);
318 const double s_dbl =
value_of(s_vec[n]);
319 const double half_s2_overx_dbl = 0.5 * s_dbl * s_dbl * y_inv_dbl;
320 const double half_nu_s2_overx_dbl
321 = 2.0 * half_nu_dbl * half_s2_overx_dbl;
324 const double Pn = gamma_q(half_nu_dbl, half_nu_s2_overx_dbl);
329 operands_and_partials.
d_x1[n]
330 += half_nu_s2_overx_dbl * y_inv_dbl
331 * gamma_p_derivative(half_nu_dbl, half_nu_s2_overx_dbl) / Pn;
334 operands_and_partials.
d_x2[n]
336 half_nu_s2_overx_dbl,
337 gamma_vec[n], digamma_vec[n])
339 * gamma_p_derivative(half_nu_dbl, half_nu_s2_overx_dbl) )
343 operands_and_partials.
d_x3[n]
344 += - 2.0 * half_nu_dbl * s_dbl * y_inv_dbl
345 * gamma_p_derivative(half_nu_dbl, half_nu_s2_overx_dbl) / Pn;
351 operands_and_partials.
d_x1[n] *= P;
355 operands_and_partials.
d_x2[n] *= P;
359 operands_and_partials.
d_x3[n] *= P;
361 return operands_and_partials.
to_var(P);
366 template <
typename T_y,
typename T_dof,
typename T_scale>
379 using boost::variate_generator;
380 using boost::random::chi_squared_distribution;
381 variate_generator<RNG&, chi_squared_distribution<> >