Stan  2.5.0
probability, sampling & optimization
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
gamma.hpp
Go to the documentation of this file.
1 #ifndef STAN__PROB__DISTRIBUTIONS__UNIVARIATE__CONTINUOUS__GAMMA_HPP
2 #define STAN__PROB__DISTRIBUTIONS__UNIVARIATE__CONTINUOUS__GAMMA_HPP
3 
4 #include <boost/random/gamma_distribution.hpp>
5 #include <boost/random/variate_generator.hpp>
6 
12 #include <stan/meta/traits.hpp>
13 #include <stan/prob/constants.hpp>
14 #include <stan/prob/traits.hpp>
16 
17 namespace stan {
18 
19  namespace prob {
20 
43  template <bool propto,
44  typename T_y, typename T_shape, typename T_inv_scale>
45  typename return_type<T_y,T_shape,T_inv_scale>::type
46  gamma_log(const T_y& y, const T_shape& alpha, const T_inv_scale& beta) {
47  static const char* function = "stan::prob::gamma_log(%1%)";
48 
55 
56  // check if any vectors are zero length
57  if (!(stan::length(y)
58  && stan::length(alpha)
59  && stan::length(beta)))
60  return 0.0;
61 
62  // set up return value accumulator
63  double logp(0.0);
64 
65  // validate args (here done over var, which should be OK)
66  check_not_nan(function, y, "Random variable", &logp);
67  check_positive_finite(function, alpha, "Shape parameter", &logp);
68  check_positive_finite(function, beta, "Inverse scale parameter", &logp);
69  check_consistent_sizes(function,
70  y,alpha,beta,
71  "Random variable","Shape parameter",
72  "Inverse scale parameter",
73  &logp);
74 
75  // check if no variables are involved and prop-to
77  return 0.0;
78 
79  // set up template expressions wrapping scalars into vector views
80  VectorView<const T_y> y_vec(y);
81  VectorView<const T_shape> alpha_vec(alpha);
82  VectorView<const T_inv_scale> beta_vec(beta);
83 
84  for (size_t n = 0; n < length(y); n++) {
85  const double y_dbl = value_of(y_vec[n]);
86  if (y_dbl < 0)
87  return LOG_ZERO;
88  }
89 
90  size_t N = max_size(y, alpha, beta);
91  agrad::OperandsAndPartials<T_y, T_shape, T_inv_scale> operands_and_partials(y, alpha, beta);
92 
93  using boost::math::lgamma;
96 
98  log_y(length(y));
100  for(size_t n = 0; n < length(y); n++) {
101  if (value_of(y_vec[n]) > 0)
102  log_y[n] = log(value_of(y_vec[n]));
103  }
104 
106  lgamma_alpha(length(alpha));
108  digamma_alpha(length(alpha));
109  for (size_t n = 0; n < length(alpha); n++) {
111  lgamma_alpha[n] = lgamma(value_of(alpha_vec[n]));
113  digamma_alpha[n] = digamma(value_of(alpha_vec[n]));
114  }
115 
117  log_beta(length(beta));
119  for (size_t n = 0; n < length(beta); n++)
120  log_beta[n] = log(value_of(beta_vec[n]));
121 
122  for (size_t n = 0; n < N; n++) {
123  // pull out values of arguments
124  const double y_dbl = value_of(y_vec[n]);
125  const double alpha_dbl = value_of(alpha_vec[n]);
126  const double beta_dbl = value_of(beta_vec[n]);
127 
129  logp -= lgamma_alpha[n];
131  logp += alpha_dbl * log_beta[n];
133  logp += (alpha_dbl-1.0) * log_y[n];
135  logp -= beta_dbl * y_dbl;
136 
137  // gradients
139  operands_and_partials.d_x1[n] += (alpha_dbl-1)/y_dbl - beta_dbl;
141  operands_and_partials.d_x2[n] += -digamma_alpha[n] + log_beta[n] + log_y[n];
143  operands_and_partials.d_x3[n] += alpha_dbl / beta_dbl - y_dbl;
144  }
145  return operands_and_partials.to_var(logp);
146  }
147 
148  template <typename T_y, typename T_shape, typename T_inv_scale>
149  inline
151  gamma_log(const T_y& y, const T_shape& alpha, const T_inv_scale& beta) {
152  return gamma_log<false>(y,alpha,beta);
153  }
154 
155 
170  template <typename T_y, typename T_shape, typename T_inv_scale>
172  gamma_cdf(const T_y& y, const T_shape& alpha, const T_inv_scale& beta) {
173  // Size checks
174  if (!(stan::length(y) && stan::length(alpha) && stan::length(beta)))
175  return 1.0;
176 
177  // Error checks
178  static const char* function = "stan::prob::gamma_cdf(%1%)";
179 
186  using stan::math::value_of;
187  using boost::math::tools::promote_args;
188 
189  double P(1.0);
190 
191  check_positive_finite(function, alpha, "Shape parameter", &P);
192  check_positive_finite(function, beta, "Scale parameter", &P);
193  check_not_nan(function, y, "Random variable", &P);
194  check_nonnegative(function, y, "Random variable", &P);
195  check_consistent_sizes(function, y, alpha, beta,
196  "Random variable", "Shape parameter",
197  "Scale Parameter",
198  &P);
199 
200  // Wrap arguments in vectors
201  VectorView<const T_y> y_vec(y);
202  VectorView<const T_shape> alpha_vec(alpha);
203  VectorView<const T_inv_scale> beta_vec(beta);
204  size_t N = max_size(y, alpha, beta);
205 
207  operands_and_partials(y, alpha, beta);
208 
209  // Explicit return for extreme values
210  // The gradients are technically ill-defined, but treated as zero
211 
212  for (size_t i = 0; i < stan::length(y); i++) {
213  if (value_of(y_vec[i]) == 0)
214  return operands_and_partials.to_var(0.0);
215  }
216 
217  // Compute CDF and its gradients
218  using boost::math::gamma_p_derivative;
219  using boost::math::gamma_p;
220  using boost::math::digamma;
221  using boost::math::tgamma;
222 
223  // Cache a few expensive function calls if nu is a parameter
226  gamma_vec(stan::length(alpha));
229  digamma_vec(stan::length(alpha));
230 
232  for (size_t i = 0; i < stan::length(alpha); i++) {
233  const double alpha_dbl = value_of(alpha_vec[i]);
234  gamma_vec[i] = tgamma(alpha_dbl);
235  digamma_vec[i] = digamma(alpha_dbl);
236  }
237  }
238 
239  // Compute vectorized CDF and gradient
240  for (size_t n = 0; n < N; n++) {
241  // Explicit results for extreme values
242  // The gradients are technically ill-defined, but treated as zero
243  if (value_of(y_vec[n]) == std::numeric_limits<double>::infinity())
244  continue;
245 
246  // Pull out values
247  const double y_dbl = value_of(y_vec[n]);
248  const double alpha_dbl = value_of(alpha_vec[n]);
249  const double beta_dbl = value_of(beta_vec[n]);
250 
251  // Compute
252  const double Pn = gamma_p(alpha_dbl, beta_dbl * y_dbl);
253 
254  P *= Pn;
255 
257  operands_and_partials.d_x1[n]
258  += beta_dbl * gamma_p_derivative(alpha_dbl, beta_dbl * y_dbl)
259  / Pn;
261  operands_and_partials.d_x2[n]
262  -= stan::math::gradRegIncGamma(alpha_dbl, beta_dbl
263  * y_dbl, gamma_vec[n],
264  digamma_vec[n]) / Pn;
266  operands_and_partials.d_x3[n]
267  += y_dbl * gamma_p_derivative(alpha_dbl, beta_dbl * y_dbl) / Pn;
268  }
269 
271  for (size_t n = 0; n < stan::length(y); ++n)
272  operands_and_partials.d_x1[n] *= P;
274  for (size_t n = 0; n < stan::length(alpha); ++n)
275  operands_and_partials.d_x2[n] *= P;
277  for (size_t n = 0; n < stan::length(beta); ++n)
278  operands_and_partials.d_x3[n] *= P;
279 
280  return operands_and_partials.to_var(P);
281  }
282 
283  template <typename T_y, typename T_shape, typename T_inv_scale>
285  gamma_cdf_log(const T_y& y, const T_shape& alpha, const T_inv_scale& beta) {
286  // Size checks
287  if (!(stan::length(y) && stan::length(alpha) && stan::length(beta)))
288  return 0.0;
289 
290  // Error checks
291  static const char* function = "stan::prob::gamma_cdf_log(%1%)";
292 
299  using stan::math::value_of;
300  using boost::math::tools::promote_args;
301 
302  double P(0.0);
303 
304  check_positive_finite(function, alpha, "Shape parameter", &P);
305  check_positive_finite(function, beta, "Scale parameter", &P);
306  check_not_nan(function, y, "Random variable", &P);
307  check_nonnegative(function, y, "Random variable", &P);
308  check_consistent_sizes(function, y, alpha, beta,
309  "Random variable", "Shape parameter",
310  "Scale Parameter",
311  &P);
312 
313  // Wrap arguments in vectors
314  VectorView<const T_y> y_vec(y);
315  VectorView<const T_shape> alpha_vec(alpha);
316  VectorView<const T_inv_scale> beta_vec(beta);
317  size_t N = max_size(y, alpha, beta);
318 
320  operands_and_partials(y, alpha, beta);
321 
322  // Explicit return for extreme values
323  // The gradients are technically ill-defined, but treated as zero
324 
325  for (size_t i = 0; i < stan::length(y); i++) {
326  if (value_of(y_vec[i]) == 0)
327  return operands_and_partials.to_var(stan::math::negative_infinity());
328  }
329 
330  // Compute cdf_log and its gradients
331  using boost::math::gamma_p_derivative;
332  using boost::math::gamma_p;
333  using boost::math::digamma;
334  using boost::math::tgamma;
335 
336  // Cache a few expensive function calls if nu is a parameter
339  gamma_vec(stan::length(alpha));
342  digamma_vec(stan::length(alpha));
343 
345  for (size_t i = 0; i < stan::length(alpha); i++) {
346  const double alpha_dbl = value_of(alpha_vec[i]);
347  gamma_vec[i] = tgamma(alpha_dbl);
348  digamma_vec[i] = digamma(alpha_dbl);
349  }
350  }
351 
352  // Compute vectorized cdf_log and gradient
353  for (size_t n = 0; n < N; n++) {
354  // Explicit results for extreme values
355  // The gradients are technically ill-defined, but treated as zero
356  if (value_of(y_vec[n]) == std::numeric_limits<double>::infinity())
357  return operands_and_partials.to_var(0.0);
358 
359  // Pull out values
360  const double y_dbl = value_of(y_vec[n]);
361  const double alpha_dbl = value_of(alpha_vec[n]);
362  const double beta_dbl = value_of(beta_vec[n]);
363 
364  // Compute
365  const double Pn = gamma_p(alpha_dbl, beta_dbl * y_dbl);
366 
367  P += log(Pn);
368 
370  operands_and_partials.d_x1[n]
371  += beta_dbl * gamma_p_derivative(alpha_dbl, beta_dbl * y_dbl)
372  / Pn;
374  operands_and_partials.d_x2[n]
375  -= stan::math::gradRegIncGamma(alpha_dbl, beta_dbl
376  * y_dbl, gamma_vec[n],
377  digamma_vec[n]) / Pn;
379  operands_and_partials.d_x3[n]
380  += y_dbl * gamma_p_derivative(alpha_dbl, beta_dbl * y_dbl) / Pn;
381  }
382 
383  return operands_and_partials.to_var(P);
384  }
385 
386  template <typename T_y, typename T_shape, typename T_inv_scale>
388  gamma_ccdf_log(const T_y& y, const T_shape& alpha, const T_inv_scale& beta) {
389  // Size checks
390  if (!(stan::length(y) && stan::length(alpha) && stan::length(beta)))
391  return 0.0;
392 
393  // Error checks
394  static const char* function = "stan::prob::gamma_ccdf_log(%1%)";
395 
402  using stan::math::value_of;
403  using boost::math::tools::promote_args;
404 
405  double P(0.0);
406 
407  check_positive_finite(function, alpha, "Shape parameter", &P);
408  check_positive_finite(function, beta, "Scale parameter", &P);
409  check_not_nan(function, y, "Random variable", &P);
410  check_nonnegative(function, y, "Random variable", &P);
411  check_consistent_sizes(function, y, alpha, beta,
412  "Random variable", "Shape parameter",
413  "Scale Parameter",
414  &P);
415 
416  // Wrap arguments in vectors
417  VectorView<const T_y> y_vec(y);
418  VectorView<const T_shape> alpha_vec(alpha);
419  VectorView<const T_inv_scale> beta_vec(beta);
420  size_t N = max_size(y, alpha, beta);
421 
423  operands_and_partials(y, alpha, beta);
424 
425  // Explicit return for extreme values
426  // The gradients are technically ill-defined, but treated as zero
427 
428  for (size_t i = 0; i < stan::length(y); i++) {
429  if (value_of(y_vec[i]) == 0)
430  return operands_and_partials.to_var(0.0);
431  }
432 
433  // Compute ccdf_log and its gradients
434  using boost::math::gamma_p_derivative;
435  using boost::math::gamma_p;
436  using boost::math::digamma;
437  using boost::math::tgamma;
438 
439  // Cache a few expensive function calls if nu is a parameter
442  gamma_vec(stan::length(alpha));
445  digamma_vec(stan::length(alpha));
446 
448  for (size_t i = 0; i < stan::length(alpha); i++) {
449  const double alpha_dbl = value_of(alpha_vec[i]);
450  gamma_vec[i] = tgamma(alpha_dbl);
451  digamma_vec[i] = digamma(alpha_dbl);
452  }
453  }
454 
455  // Compute vectorized ccdf_log and gradient
456  for (size_t n = 0; n < N; n++) {
457  // Explicit results for extreme values
458  // The gradients are technically ill-defined, but treated as zero
459  if (value_of(y_vec[n]) == std::numeric_limits<double>::infinity())
460  return operands_and_partials.to_var(stan::math::negative_infinity());
461 
462  // Pull out values
463  const double y_dbl = value_of(y_vec[n]);
464  const double alpha_dbl = value_of(alpha_vec[n]);
465  const double beta_dbl = value_of(beta_vec[n]);
466 
467  // Compute
468  const double Pn = 1.0 - gamma_p(alpha_dbl, beta_dbl * y_dbl);
469 
470  P += log(Pn);
471 
473  operands_and_partials.d_x1[n]
474  -= beta_dbl * gamma_p_derivative(alpha_dbl, beta_dbl * y_dbl)
475  / Pn;
477  operands_and_partials.d_x2[n]
478  += stan::math::gradRegIncGamma(alpha_dbl, beta_dbl
479  * y_dbl, gamma_vec[n],
480  digamma_vec[n]) / Pn;
482  operands_and_partials.d_x3[n]
483  -= y_dbl * gamma_p_derivative(alpha_dbl, beta_dbl * y_dbl) / Pn;
484  }
485 
486  return operands_and_partials.to_var(P);
487  }
488 
489  template <class RNG>
490  inline double
491  gamma_rng(const double alpha,
492  const double beta,
493  RNG& rng) {
494  using boost::variate_generator;
495  using boost::gamma_distribution;
496 
497  static const char* function = "stan::prob::gamma_rng(%1%)";
498 
500 
501  check_positive_finite(function, alpha, "Shape parameter", (double*)0);
502  check_positive_finite(function, beta, "Inverse scale parameter",
503  (double*)0);
504 
505  /*
506  the boost gamma distribution is defined by
507  shape and scale, whereas the stan one is defined
508  by shape and rate
509  */
510  variate_generator<RNG&, gamma_distribution<> >
511  gamma_rng(rng, gamma_distribution<>(alpha, 1.0 / beta));
512  return gamma_rng();
513  }
514 
515  }
516 }
517 
518 #endif
fvar< T > tgamma(const fvar< T > &x)
Definition: tgamma.hpp:15
T_return_type to_var(double logp)
bool check_positive_finite(const char *function, const T_y &y, const char *name, T_result *result)
boost::math::tools::promote_args< T_a, T_b >::type multiply_log(const T_a a, const T_b b)
Calculated the value of the first argument times log of the second argument while behaving properly w...
size_t length(const T &)
Definition: traits.hpp:159
DoubleVectorView allocates double values to be used as intermediate values.
Definition: traits.hpp:358
return_type< T_y, T_shape, T_inv_scale >::type gamma_cdf_log(const T_y &y, const T_shape &alpha, const T_inv_scale &beta)
Definition: gamma.hpp:285
T value_of(const fvar< T > &v)
Return the value of the specified variable.
Definition: value_of.hpp:16
return_type< T_y, T_shape, T_inv_scale >::type gamma_cdf(const T_y &y, const T_shape &alpha, const T_inv_scale &beta)
The cumulative density function for a gamma distribution for y with the specified shape and inverse s...
Definition: gamma.hpp:172
fvar< T > lgamma(const fvar< T > &x)
Definition: lgamma.hpp:15
A variable implementation that stores operands and derivatives with respect to the variable...
boost::math::tools::promote_args< typename scalar_type< T1 >::type, typename scalar_type< T2 >::type, typename scalar_type< T3 >::type, typename scalar_type< T4 >::type, typename scalar_type< T5 >::type, typename scalar_type< T6 >::type >::type type
Definition: traits.hpp:406
Metaprogram to determine if a type has a base scalar type that can be assigned to type double...
Definition: traits.hpp:57
double value_of(const T x)
Return the value of the specified scalar argument converted to a double value.
Definition: value_of.hpp:24
Template metaprogram to calculate whether a summand needs to be included in a proportional (log) prob...
Definition: traits.hpp:35
VectorView< double *, is_vector< T2 >::value, is_constant_struct< T2 >::value > d_x2
double gradRegIncGamma(double a, double z, double g, double dig, double precision=1e-6)
bool check_nonnegative(const char *function, const T_y &y, const char *name, T_result *result)
bool check_consistent_sizes(const char *function, const T1 &x1, const T2 &x2, const char *name1, const char *name2, T_result *result)
size_t max_size(const T1 &x1, const T2 &x2)
Definition: traits.hpp:191
fvar< T > gamma_p(const fvar< T > &x1, const fvar< T > &x2)
Definition: gamma_p.hpp:16
bool check_less_or_equal(const char *function, const T_y &y, const T_high &high, const char *name, T_result *result)
bool check_not_nan(const char *function, const T_y &y, const char *name, T_result *result)
Checks if the variable y is nan.
fvar< T > digamma(const fvar< T > &x)
Definition: digamma.hpp:16
return_type< T_y, T_shape, T_inv_scale >::type gamma_ccdf_log(const T_y &y, const T_shape &alpha, const T_inv_scale &beta)
Definition: gamma.hpp:388
return_type< T_y, T_shape, T_inv_scale >::type gamma_log(const T_y &y, const T_shape &alpha, const T_inv_scale &beta)
The log of a gamma density for y with the specified shape and inverse scale parameters.
Definition: gamma.hpp:46
VectorView< double *, is_vector< T1 >::value, is_constant_struct< T1 >::value > d_x1
VectorView< double *, is_vector< T3 >::value, is_constant_struct< T3 >::value > d_x3
fvar< T > log(const fvar< T > &x)
Definition: log.hpp:15
VectorView is a template metaprogram that takes its argument and allows it to be used like a vector...
Definition: traits.hpp:275
double gamma_rng(const double alpha, const double beta, RNG &rng)
Definition: gamma.hpp:491
bool check_greater_or_equal(const char *function, const T_y &y, const T_low &low, const char *name, T_result *result)
double negative_infinity()
Return negative infinity.
Definition: constants.hpp:123

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