Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reuse intermediate computations in distributions part 2 #1752

Closed
wants to merge 9 commits into from
38 changes: 19 additions & 19 deletions stan/math/prim/prob/chi_square_cdf.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ return_type_t<T_y, T_dof> chi_square_cdf(const T_y& y, const T_dof& nu) {

scalar_seq_view<T_y> y_vec(y);
scalar_seq_view<T_dof> nu_vec(nu);
size_t size_nu = stan::math::size(nu);
size_t N = max_size(y, nu);

operands_and_partials<T_y, T_dof> ops_partials(y, nu);
Expand All @@ -65,16 +66,17 @@ return_type_t<T_y, T_dof> chi_square_cdf(const T_y& y, const T_dof& nu) {
using std::exp;
using std::pow;

VectorBuilder<!is_constant_all<T_y, T_dof>::value, T_partials_return, T_dof>
tgamma_vec(size_nu);
VectorBuilder<!is_constant_all<T_dof>::value, T_partials_return, T_dof>
gamma_vec(size(nu));
VectorBuilder<!is_constant_all<T_dof>::value, T_partials_return, T_dof>
digamma_vec(size(nu));

if (!is_constant_all<T_dof>::value) {
for (size_t i = 0; i < stan::math::size(nu); i++) {
const T_partials_return alpha_dbl = value_of(nu_vec[i]) * 0.5;
gamma_vec[i] = tgamma(alpha_dbl);
digamma_vec[i] = digamma(alpha_dbl);
digamma_vec(size_nu);
if (!is_constant_all<T_y, T_dof>::value) {
for (size_t i = 0; i < size_nu; i++) {
const T_partials_return half_nu_dbl = 0.5 * value_of(nu_vec[i]);
tgamma_vec[i] = tgamma(half_nu_dbl);
if (!is_constant_all<T_dof>::value) {
digamma_vec[i] = digamma(half_nu_dbl);
}
}
}

Expand All @@ -85,23 +87,21 @@ return_type_t<T_y, T_dof> chi_square_cdf(const T_y& y, const T_dof& nu) {
continue;
}

const T_partials_return y_dbl = value_of(y_vec[n]);
const T_partials_return alpha_dbl = value_of(nu_vec[n]) * 0.5;
const T_partials_return beta_dbl = 0.5;

const T_partials_return Pn = gamma_p(alpha_dbl, beta_dbl * y_dbl);
const T_partials_return half_nu_dbl = 0.5 * value_of(nu_vec[n]);
const T_partials_return half_y_dbl = 0.5 * value_of(y_vec[n]);
const T_partials_return Pn = gamma_p(half_nu_dbl, half_y_dbl);

cdf *= Pn;

if (!is_constant_all<T_y>::value) {
ops_partials.edge1_.partials_[n] += beta_dbl * exp(-beta_dbl * y_dbl)
* pow(beta_dbl * y_dbl, alpha_dbl - 1)
/ tgamma(alpha_dbl) / Pn;
ops_partials.edge1_.partials_[n] += 0.5 * exp(-half_y_dbl)
* pow(half_y_dbl, half_nu_dbl - 1)
/ (tgamma_vec[n] * Pn);
}
if (!is_constant_all<T_dof>::value) {
ops_partials.edge2_.partials_[n]
-= 0.5
* grad_reg_inc_gamma(alpha_dbl, beta_dbl * y_dbl, gamma_vec[n],
* grad_reg_inc_gamma(half_nu_dbl, half_y_dbl, tgamma_vec[n],
digamma_vec[n])
/ Pn;
}
Expand All @@ -113,7 +113,7 @@ return_type_t<T_y, T_dof> chi_square_cdf(const T_y& y, const T_dof& nu) {
}
}
if (!is_constant_all<T_dof>::value) {
for (size_t n = 0; n < stan::math::size(nu); ++n) {
for (size_t n = 0; n < size_nu; ++n) {
ops_partials.edge2_.partials_[n] *= cdf;
}
}
Expand Down
49 changes: 24 additions & 25 deletions stan/math/prim/prob/chi_square_lccdf.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,59 +51,58 @@ return_type_t<T_y, T_dof> chi_square_lccdf(const T_y& y, const T_dof& nu) {

scalar_seq_view<T_y> y_vec(y);
scalar_seq_view<T_dof> nu_vec(nu);
size_t size_nu = stan::math::size(nu);
size_t N = max_size(y, nu);

operands_and_partials<T_y, T_dof> ops_partials(y, nu);

// Explicit return for extreme values
// The gradients are technically ill-defined, but treated as zero
for (size_t i = 0; i < stan::math::size(y); i++) {
if (value_of(y_vec[i]) == 0) {
const T_partials_return y_dbl = value_of(y_vec[i]);
if (y_dbl == 0) {
return ops_partials.build(0.0);
}
if (y_dbl == INFTY) {
return ops_partials.build(NEGATIVE_INFTY);
}
}

using std::exp;
using std::log;
using std::pow;

VectorBuilder<true, T_partials_return, T_dof> half_nu(size_nu);
VectorBuilder<!is_constant_all<T_y, T_dof>::value, T_partials_return, T_dof>
tgamma_vec(size_nu);
VectorBuilder<!is_constant_all<T_dof>::value, T_partials_return, T_dof>
gamma_vec(size(nu));
VectorBuilder<!is_constant_all<T_dof>::value, T_partials_return, T_dof>
digamma_vec(size(nu));

if (!is_constant_all<T_dof>::value) {
bbbales2 marked this conversation as resolved.
Show resolved Hide resolved
for (size_t i = 0; i < stan::math::size(nu); i++) {
const T_partials_return alpha_dbl = value_of(nu_vec[i]) * 0.5;
gamma_vec[i] = tgamma(alpha_dbl);
digamma_vec[i] = digamma(alpha_dbl);
digamma_vec(size_nu);
for (size_t i = 0; i < size_nu; i++) {
const T_partials_return half_nu_dbl = 0.5 * value_of(nu_vec[i]);
half_nu[i] = half_nu_dbl;
if (!is_constant_all<T_y, T_dof>::value) {
tgamma_vec[i] = tgamma(half_nu[i]);
}
if (!is_constant_all<T_dof>::value) {
digamma_vec[i] = digamma(half_nu_dbl);
}
}

for (size_t n = 0; n < N; n++) {
// Explicit results for extreme values
// The gradients are technically ill-defined, but treated as zero
if (value_of(y_vec[n]) == INFTY) {
return ops_partials.build(negative_infinity());
}

const T_partials_return y_dbl = value_of(y_vec[n]);
const T_partials_return alpha_dbl = value_of(nu_vec[n]) * 0.5;
const T_partials_return beta_dbl = 0.5;

const T_partials_return Pn = gamma_q(alpha_dbl, beta_dbl * y_dbl);
const T_partials_return half_y_dbl = 0.5 * value_of(y_vec[n]);
const T_partials_return Pn = gamma_q(half_nu[n], half_y_dbl);

ccdf_log += log(Pn);

if (!is_constant_all<T_y>::value) {
ops_partials.edge1_.partials_[n] -= beta_dbl * exp(-beta_dbl * y_dbl)
* pow(beta_dbl * y_dbl, alpha_dbl - 1)
/ tgamma(alpha_dbl) / Pn;
ops_partials.edge1_.partials_[n] -= 0.5 * exp(-half_y_dbl)
* pow(half_y_dbl, half_nu[n] - 1)
/ (tgamma_vec[n] * Pn);
}
if (!is_constant_all<T_dof>::value) {
ops_partials.edge2_.partials_[n]
+= 0.5
* grad_reg_inc_gamma(alpha_dbl, beta_dbl * y_dbl, gamma_vec[n],
* grad_reg_inc_gamma(half_nu[n], half_y_dbl, tgamma_vec[n],
digamma_vec[n])
/ Pn;
}
Expand Down
51 changes: 25 additions & 26 deletions stan/math/prim/prob/chi_square_lcdf.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,59 +51,58 @@ return_type_t<T_y, T_dof> chi_square_lcdf(const T_y& y, const T_dof& nu) {

scalar_seq_view<T_y> y_vec(y);
scalar_seq_view<T_dof> nu_vec(nu);
size_t size_nu = stan::math::size(nu);
size_t N = max_size(y, nu);

operands_and_partials<T_y, T_dof> ops_partials(y, nu);

// Explicit return for extreme values
// The gradients are technically ill-defined, but treated as zero
for (size_t i = 0; i < stan::math::size(y); i++) {
if (value_of(y_vec[i]) == 0) {
return ops_partials.build(negative_infinity());
const T_partials_return y_dbl = value_of(y_vec[i]);
if (y_dbl == 0) {
return ops_partials.build(NEGATIVE_INFTY);
}
if (y_dbl == INFTY) {
return ops_partials.build(0.0);
}
}

using std::exp;
using std::log;
using std::pow;

VectorBuilder<true, T_partials_return, T_dof> half_nu(size_nu);
VectorBuilder<!is_constant_all<T_y, T_dof>::value, T_partials_return, T_dof>
tgamma_vec(size_nu);
VectorBuilder<!is_constant_all<T_dof>::value, T_partials_return, T_dof>
gamma_vec(size(nu));
VectorBuilder<!is_constant_all<T_dof>::value, T_partials_return, T_dof>
digamma_vec(size(nu));

if (!is_constant_all<T_dof>::value) {
bbbales2 marked this conversation as resolved.
Show resolved Hide resolved
for (size_t i = 0; i < stan::math::size(nu); i++) {
const T_partials_return alpha_dbl = value_of(nu_vec[i]) * 0.5;
gamma_vec[i] = tgamma(alpha_dbl);
digamma_vec[i] = digamma(alpha_dbl);
digamma_vec(size_nu);
for (size_t i = 0; i < size_nu; i++) {
const T_partials_return half_nu_dbl = 0.5 * value_of(nu_vec[i]);
half_nu[i] = half_nu_dbl;
if (!is_constant_all<T_y, T_dof>::value) {
tgamma_vec[i] = tgamma(half_nu[i]);
}
if (!is_constant_all<T_dof>::value) {
digamma_vec[i] = digamma(half_nu_dbl);
}
}

for (size_t n = 0; n < N; n++) {
// Explicit results for extreme values
// The gradients are technically ill-defined, but treated as zero
if (value_of(y_vec[n]) == INFTY) {
return ops_partials.build(0.0);
}

const T_partials_return y_dbl = value_of(y_vec[n]);
const T_partials_return alpha_dbl = value_of(nu_vec[n]) * 0.5;
const T_partials_return beta_dbl = 0.5;

const T_partials_return Pn = gamma_p(alpha_dbl, beta_dbl * y_dbl);
const T_partials_return half_y_dbl = 0.5 * value_of(y_vec[n]);
const T_partials_return Pn = gamma_p(half_nu[n], half_y_dbl);

cdf_log += log(Pn);

if (!is_constant_all<T_y>::value) {
ops_partials.edge1_.partials_[n] += beta_dbl * exp(-beta_dbl * y_dbl)
* pow(beta_dbl * y_dbl, alpha_dbl - 1)
/ tgamma(alpha_dbl) / Pn;
ops_partials.edge1_.partials_[n] += 0.5 * exp(-half_y_dbl)
* pow(half_y_dbl, half_nu[n] - 1)
/ (tgamma_vec[n] * Pn);
}
if (!is_constant_all<T_dof>::value) {
ops_partials.edge2_.partials_[n]
-= 0.5
* grad_reg_inc_gamma(alpha_dbl, beta_dbl * y_dbl, gamma_vec[n],
* grad_reg_inc_gamma(half_nu[n], half_y_dbl, tgamma_vec[n],
digamma_vec[n])
/ Pn;
}
Expand Down
18 changes: 0 additions & 18 deletions stan/math/prim/prob/chi_square_log.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,7 @@ namespace stan {
namespace math {

/** \ingroup prob_dists
* The log of a chi-squared density for y with the specified
* degrees of freedom parameter.
* The degrees of freedom prarameter must be greater than 0.
* y must be greater than or equal to 0.
*
\f{eqnarray*}{
y &\sim& \chi^2_\nu \\
\log (p (y \, |\, \nu)) &=& \log \left( \frac{2^{-\nu / 2}}{\Gamma (\nu / 2)}
y^{\nu / 2 - 1} \exp^{- y / 2} \right) \\
&=& - \frac{\nu}{2} \log(2) - \log (\Gamma (\nu / 2)) + (\frac{\nu}{2} - 1)
\log(y) - \frac{y}{2} \\ & & \mathrm{ where } \; y \ge 0 \f}
*
* @deprecated use <code>chi_square_lpdf</code>
* @param y A scalar variable.
* @param nu Degrees of freedom.
* @throw std::domain_error if nu is not greater than or equal to 0
* @throw std::domain_error if y is not greater than or equal to 0.
* @tparam T_y Type of scalar.
* @tparam T_dof Type of degrees of freedom.
*/
template <bool propto, typename T_y, typename T_dof>
return_type_t<T_y, T_dof> chi_square_log(const T_y& y, const T_dof& nu) {
Expand Down
Loading