Stan  1.1
probability, sampling & optimization
 All Classes Namespaces Files Functions Variables Typedefs Enumerator Friends Macros Pages
inv_gamma.hpp
Go to the documentation of this file.
1 #ifndef __STAN__PROB__DISTRIBUTIONS__UNIVARIATE__CONTINUOUS__INV_GAMMA_HPP__
2 #define __STAN__PROB__DISTRIBUTIONS__UNIVARIATE__CONTINUOUS__INV_GAMMA_HPP__
3 
4 #include <stan/agrad.hpp>
7 #include <stan/meta/traits.hpp>
9 #include <stan/prob/traits.hpp>
11 
12 namespace stan {
13 
14  namespace prob {
15 
32  template <bool propto,
33  typename T_y, typename T_shape, typename T_scale,
34  class Policy>
35  typename return_type<T_y,T_shape,T_scale>::type
36  inv_gamma_log(const T_y& y, const T_shape& alpha, const T_scale& beta,
37  const Policy&) {
38  static const char* function = "stan::prob::inv_gamma_log(%1%)";
39 
44  using boost::math::tools::promote_args;
47 
48  // check if any vectors are zero length
49  if (!(stan::length(y)
50  && stan::length(alpha)
51  && stan::length(beta)))
52  return 0.0;
53 
54  // set up return value accumulator
55  double logp(0.0);
56 
57  if (!check_not_nan(function, y, "Random variable", &logp, Policy()))
58  return logp;
59  if (!check_finite(function, alpha, "Shape parameter",
60  &logp, Policy()))
61  return logp;
62  if (!check_positive(function, alpha, "Shape parameter",
63  &logp, Policy()))
64  return logp;
65  if (!check_finite(function, beta, "Scale parameter",
66  &logp, Policy()))
67  return logp;
68  if (!check_positive(function, beta, "Scale parameter",
69  &logp, Policy()))
70  return logp;
71  if (!(check_consistent_sizes(function,
72  y,alpha,beta,
73  "Random variable","Shape parameter","Scale parameter",
74  &logp, Policy())))
75  return logp;
76 
77  // check if no variables are involved and prop-to
79  return 0.0;
80 
81  // set up template expressions wrapping scalars into vector views
82  VectorView<const T_y> y_vec(y);
83  VectorView<const T_shape> alpha_vec(alpha);
84  VectorView<const T_scale> beta_vec(beta);
85 
86  for (size_t n = 0; n < length(y); n++) {
87  const double y_dbl = value_of(y_vec[n]);
88  if (y_dbl <= 0)
89  return LOG_ZERO;
90  }
91 
92  size_t N = max_size(y, alpha, beta);
93  agrad::OperandsAndPartials<T_y, T_shape, T_scale> operands_and_partials(y, alpha, beta);
94 
95  using boost::math::lgamma;
97  using boost::math::digamma;
98 
100  log_y(length(y));
102  inv_y(length(y));
103  for(size_t n = 0; n < length(y); n++) {
105  if (value_of(y_vec[n]) > 0)
106  log_y[n] = log(value_of(y_vec[n]));
108  inv_y[n] = 1.0 / value_of(y_vec[n]);
109  }
110 
112  lgamma_alpha(length(alpha));
114  digamma_alpha(length(alpha));
115  for (size_t n = 0; n < length(alpha); n++) {
117  lgamma_alpha[n] = lgamma(value_of(alpha_vec[n]));
119  digamma_alpha[n] = digamma(value_of(alpha_vec[n]));
120  }
121 
123  log_beta(length(beta));
125  for (size_t n = 0; n < length(beta); n++)
126  log_beta[n] = log(value_of(beta_vec[n]));
127 
128  for (size_t n = 0; n < N; n++) {
129  // pull out values of arguments
130  const double alpha_dbl = value_of(alpha_vec[n]);
131  const double beta_dbl = value_of(beta_vec[n]);
132 
134  logp -= lgamma_alpha[n];
136  logp += alpha_dbl * log_beta[n];
138  logp -= (alpha_dbl+1.0) * log_y[n];
140  logp -= beta_dbl * inv_y[n];
141 
142  // gradients
143  if (!is_constant<typename is_vector<T_y>::type>::value)
144  operands_and_partials.d_x1[n] += -(alpha_dbl+1) * inv_y[n] + beta_dbl * inv_y[n] * inv_y[n];
145  if (!is_constant<typename is_vector<T_shape>::type>::value)
146  operands_and_partials.d_x2[n] += -digamma_alpha[n] + log_beta[n] - log_y[n];
147  if (!is_constant<typename is_vector<T_scale>::type>::value)
148  operands_and_partials.d_x3[n] += alpha_dbl / beta_dbl - inv_y[n];
149  }
150  return operands_and_partials.to_var(logp);
151  }
152 
153  template <bool propto,
154  typename T_y, typename T_shape, typename T_scale>
155  inline
157  inv_gamma_log(const T_y& y, const T_shape& alpha, const T_scale& beta) {
158  return inv_gamma_log<propto>(y,alpha,beta,stan::math::default_policy());
159  }
160 
161  template <typename T_y, typename T_shape, typename T_scale,
162  class Policy>
163  inline
165  inv_gamma_log(const T_y& y, const T_shape& alpha, const T_scale& beta,
166  const Policy&) {
167  return inv_gamma_log<false>(y,alpha,beta,Policy());
168  }
169 
170  template <typename T_y, typename T_shape, typename T_scale>
171  inline
173  inv_gamma_log(const T_y& y, const T_shape& alpha, const T_scale& beta) {
174  return inv_gamma_log<false>(y,alpha,beta,stan::math::default_policy());
175  }
176 
192  template <typename T_y, typename T_shape, typename T_scale, class Policy>
194  inv_gamma_cdf(const T_y& y, const T_shape& alpha, const T_scale& beta, const Policy&) {
195 
196  // Size checks
197  if ( !( stan::length(y) && stan::length(alpha) && stan::length(beta) ) ) return 0.0;
198 
199  // Error checks
200  static const char* function = "stan::prob::inv_gamma_cdf(%1%)";
201 
208 
209  using boost::math::tools::promote_args;
210 
211  double P(1.0);
212 
213  if (!check_finite(function, alpha, "Shape parameter", &P, Policy()))
214  return P;
215 
216  if (!check_positive(function, alpha, "Shape parameter", &P, Policy()))
217  return P;
218 
219  if (!check_finite(function, beta, "Scale parameter", &P, Policy()))
220  return P;
221 
222  if (!check_positive(function, beta, "Scale parameter", &P, Policy()))
223  return P;
224 
225  if (!check_not_nan(function, y, "Random variable", &P, Policy()))
226  return P;
227 
228  if (!check_positive(function, y, "Random variable", &P, Policy()))
229  return P;
230 
231  if (!(check_consistent_sizes(function, y, alpha, beta,
232  "Random variable", "Shape parameter", "Scale Parameter",
233  &P, Policy())))
234  return P;
235 
236  // Wrap arguments in vectors
237  VectorView<const T_y> y_vec(y);
238  VectorView<const T_shape> alpha_vec(alpha);
239  VectorView<const T_scale> beta_vec(beta);
240  size_t N = max_size(y, alpha, beta);
241 
242  agrad::OperandsAndPartials<T_y, T_shape, T_scale> operands_and_partials(y, alpha, beta);
243 
244  std::fill(operands_and_partials.all_partials,
245  operands_and_partials.all_partials + operands_and_partials.nvaris, 0.0);
246 
247  // Compute CDF and its gradients
248  using stan::math::value_of;
249  using boost::math::gamma_p_derivative;
250  using boost::math::gamma_q;
251  using boost::math::digamma;
252  using boost::math::tgamma;
253 
254  // Cache a few expensive function calls if nu is a parameter
257 
259 
260  for (size_t i = 0; i < stan::length(alpha); i++) {
261  const double alpha_dbl = value_of(alpha_vec[i]);
262  gamma_vec[i] = tgamma(alpha_dbl);
263  digamma_vec[i] = digamma(alpha_dbl);
264  }
265 
266  }
267 
268  // Compute vectorized CDF and gradient
269  for (size_t n = 0; n < N; n++) {
270 
271  // Pull out values
272  const double y_dbl = value_of(y_vec[n]);
273  const double y_inv_dbl = 1.0 / y_dbl;
274  const double alpha_dbl = value_of(alpha_vec[n]);
275  const double beta_dbl = value_of(beta_vec[n]);
276 
277  // Compute
278  const double Pn = gamma_q(alpha_dbl, beta_dbl * y_inv_dbl);
279 
280  P *= Pn;
281 
283  operands_and_partials.d_x1[n]
284  += beta_dbl * y_inv_dbl * y_inv_dbl * gamma_p_derivative(alpha_dbl, beta_dbl * y_inv_dbl) / Pn;
285 
287  operands_and_partials.d_x2[n]
288  += stan::math::gradRegIncGamma(alpha_dbl, beta_dbl * y_inv_dbl, gamma_vec[n], digamma_vec[n]) / Pn;
289 
291  operands_and_partials.d_x3[n]
292  += - y_inv_dbl * gamma_p_derivative(alpha_dbl, beta_dbl * y_inv_dbl) / Pn;
293 
294  }
295 
296  for (size_t n = 0; n < N; n++) {
297 
299  operands_and_partials.d_x1[n] *= P;
300 
302  operands_and_partials.d_x2[n] *= P;
303 
305  operands_and_partials.d_x3[n] *= P;
306 
307  }
308 
309  return operands_and_partials.to_var(P);
310 
311  }
312 
313  template <typename T_y, typename T_shape, typename T_scale>
315  inv_gamma_cdf(const T_y& y, const T_shape& alpha, const T_scale& beta) {
316  return inv_gamma_cdf(y, alpha, beta, stan::math::default_policy());
317  }
318 
319  }
320 }
321 
322 #endif

     [ Stan Home Page ] © 2011–2013, Stan Development Team.