Stan  1.3
probability, sampling & optimization
 All Classes Namespaces Files Functions Variables Typedefs Enumerator Friends Macros Pages
inv_chi_square.hpp
Go to the documentation of this file.
1 #ifndef __STAN__PROB__DIST__UNI__CONTINUOUS__INV_CHI_SQUARE_HPP__
2 #define __STAN__PROB__DIST__UNI__CONTINUOUS__INV_CHI_SQUARE_HPP__
3 
4 #include <boost/random/chi_squared_distribution.hpp>
5 #include <boost/random/variate_generator.hpp>
6 
7 #include <stan/agrad.hpp>
10 #include <stan/meta/traits.hpp>
11 #include <stan/prob/constants.hpp>
12 #include <stan/prob/traits.hpp>
14 
15 namespace stan {
16 
17  namespace prob {
18 
38  template <bool propto,
39  typename T_y, typename T_dof,
40  class Policy>
41  typename return_type<T_y,T_dof>::type
42  inv_chi_square_log(const T_y& y, const T_dof& nu,
43  const Policy&) {
44  static const char* function = "stan::prob::inv_chi_square_log(%1%)";
45 
46  // check if any vectors are zero length
47  if (!(stan::length(y)
48  && stan::length(nu)))
49  return 0.0;
50 
56 
57  double logp(0.0);
58  if (!check_finite(function, nu, "Degrees of freedom parameter", &logp, Policy()))
59  return logp;
60  if (!check_positive(function, nu, "Degrees of freedom parameter", &logp, Policy()))
61  return logp;
62  if (!check_not_nan(function, y, "Random variable", &logp, Policy()))
63  return logp;
64 
65  if (!(check_consistent_sizes(function,
66  y,nu,
67  "Random variable","Degrees of freedom parameter",
68  &logp, Policy())))
69  return logp;
70 
71 
72  // set up template expressions wrapping scalars into vector views
73  VectorView<const T_y> y_vec(y);
74  VectorView<const T_dof> nu_vec(nu);
75  size_t N = max_size(y, nu);
76 
77  for (size_t n = 0; n < length(y); n++)
78  if (value_of(y_vec[n]) <= 0)
79  return LOG_ZERO;
80 
81  using boost::math::digamma;
82  using boost::math::lgamma;
84 
86  is_vector<T_y>::value> log_y(length(y));
87  for (size_t i = 0; i < length(y); i++)
89  log_y[i] = log(value_of(y_vec[i]));
90 
92  is_vector<T_y>::value> inv_y(length(y));
93  for (size_t i = 0; i < length(y); i++)
95  inv_y[i] = 1.0 / value_of(y_vec[i]);
96 
98  is_vector<T_dof>::value> lgamma_half_nu(length(nu));
100  is_vector<T_dof>::value> digamma_half_nu_over_two(length(nu));
101  for (size_t i = 0; i < length(nu); i++) {
102  double half_nu = 0.5 * value_of(nu_vec[i]);
104  lgamma_half_nu[i] = lgamma(half_nu);
106  digamma_half_nu_over_two[i] = digamma(half_nu) * 0.5;
107  }
108 
109  agrad::OperandsAndPartials<T_y, T_dof> operands_and_partials(y, nu);
110  for (size_t n = 0; n < N; n++) {
111  const double nu_dbl = value_of(nu_vec[n]);
112  const double half_nu = 0.5 * nu_dbl;
113 
115  logp += nu_dbl * NEG_LOG_TWO_OVER_TWO - lgamma_half_nu[n];
117  logp -= (half_nu+1.0) * log_y[n];
119  logp -= 0.5 * inv_y[n];
120 
122  operands_and_partials.d_x1[n]
123  += -(half_nu+1.0) * inv_y[n] + 0.5 * inv_y[n] * inv_y[n];
124  }
126  operands_and_partials.d_x2[n]
127  += NEG_LOG_TWO_OVER_TWO - digamma_half_nu_over_two[n] - 0.5*log_y[n];
128  }
129  }
130  return operands_and_partials.to_var(logp);
131  }
132 
133  template <bool propto,
134  typename T_y, typename T_dof>
135  inline
137  inv_chi_square_log(const T_y& y, const T_dof& nu) {
138  return inv_chi_square_log<propto>(y,nu,stan::math::default_policy());
139  }
140 
141  template <typename T_y, typename T_dof,
142  class Policy>
143  inline
145  inv_chi_square_log(const T_y& y, const T_dof& nu,
146  const Policy&) {
147  return inv_chi_square_log<false>(y,nu,Policy());
148  }
149 
150 
151  template <typename T_y, typename T_dof>
152  inline
154  inv_chi_square_log(const T_y& y, const T_dof& nu) {
155  return inv_chi_square_log<false>(y,nu,stan::math::default_policy());
156  }
157 
158  template <typename T_y, typename T_dof, class Policy>
160  inv_chi_square_cdf(const T_y& y, const T_dof& nu, const Policy&) {
161 
162  // Size checks
163  if ( !( stan::length(y) && stan::length(nu) ) ) return 1.0;
164 
165  // Error checks
166  static const char* function = "stan::prob::inv_chi_square_cdf(%1%)";
167 
173 
174  using boost::math::tools::promote_args;
175  using stan::math::value_of;
176 
177  double P(1.0);
178 
179  if (!check_finite(function, nu, "Degrees of freedom parameter", &P, Policy()))
180  return P;
181 
182  if (!check_positive(function, nu, "Degrees of freedom parameter", &P, Policy()))
183  return P;
184 
185  if (!check_not_nan(function, y, "Random variable", &P, Policy()))
186  return P;
187 
188  if (!check_nonnegative(function, y, "Random variable", &P, Policy()))
189  return P;
190 
191  if (!(check_consistent_sizes(function, y, nu,
192  "Random variable", "Degrees of freedom parameter",
193  &P, Policy())))
194  return P;
195 
196  // Wrap arguments in vectors
197  VectorView<const T_y> y_vec(y);
198  VectorView<const T_dof> nu_vec(nu);
199  size_t N = max_size(y, nu);
200 
201  agrad::OperandsAndPartials<T_y, T_dof> operands_and_partials(y, nu);
202 
203  std::fill(operands_and_partials.all_partials,
204  operands_and_partials.all_partials + operands_and_partials.nvaris, 0.0);
205 
206  // Explicit return for extreme values
207  // The gradients are technically ill-defined, but treated as zero
208 
209  for (size_t i = 0; i < stan::length(y); i++)
210  if (value_of(y_vec[i]) == 0)
211  return operands_and_partials.to_var(0.0);
212 
213  // Compute CDF and its gradients
214  using boost::math::gamma_p_derivative;
215  using boost::math::gamma_q;
216  using boost::math::tgamma;
217  using boost::math::digamma;
218 
219  // Cache a few expensive function calls if nu is a parameter
221  is_vector<T_dof>::value> gamma_vec(stan::length(nu));
223  is_vector<T_dof>::value> digamma_vec(stan::length(nu));
224 
226 
227  for (size_t i = 0; i < stan::length(nu); i++) {
228  const double nu_dbl = value_of(nu_vec[i]);
229  gamma_vec[i] = tgamma(0.5 * nu_dbl);
230  digamma_vec[i] = digamma(0.5 * nu_dbl);
231  }
232 
233  }
234 
235  // Compute vectorized CDF and gradient
236  for (size_t n = 0; n < N; n++) {
237 
238  // Explicit results for extreme values
239  // The gradients are technically ill-defined, but treated as zero
240  if (value_of(y_vec[n]) == std::numeric_limits<double>::infinity()) {
241  continue;
242  }
243 
244  // Pull out values
245  const double y_dbl = value_of(y_vec[n]);
246  const double y_inv_dbl = 1.0 / y_dbl;
247  const double nu_dbl = value_of(nu_vec[n]);
248 
249  // Compute
250  const double Pn = gamma_q(0.5 * nu_dbl, 0.5 * y_inv_dbl);
251 
252  P *= Pn;
253 
255  operands_and_partials.d_x1[n]
256  += 0.5 * y_inv_dbl * y_inv_dbl
257  * gamma_p_derivative(0.5 * nu_dbl, 0.5 * y_inv_dbl) / Pn;
258 
260  operands_and_partials.d_x2[n]
261  += 0.5 * stan::math::gradRegIncGamma(0.5 * nu_dbl,
262  0.5 * y_inv_dbl,
263  gamma_vec[n],
264  digamma_vec[n]) / Pn;
265 
266  }
267 
269  for (size_t n = 0; n < stan::length(y); ++n)
270  operands_and_partials.d_x1[n] *= P;
271 
273  for (size_t n = 0; n < stan::length(nu); ++n)
274  operands_and_partials.d_x2[n] *= P;
275 
276  return operands_and_partials.to_var(P);
277  }
278 
279  template <typename T_y, typename T_dof>
280  inline typename return_type<T_y,T_dof>::type
281  inv_chi_square_cdf(const T_y& y, const T_dof& nu) {
283  }
284 
285  template <class RNG>
286  inline double
287  inv_chi_square_rng(const double nu,
288  RNG& rng) {
289  using boost::variate_generator;
290  using boost::random::chi_squared_distribution;
291  variate_generator<RNG&, chi_squared_distribution<> >
292  chi_square_rng(rng, chi_squared_distribution<>(nu));
293  return 1 / chi_square_rng();
294  }
295 
296  }
297 }
298 
299 #endif
300 

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