Stan  1.3
probability, sampling & optimization
 All Classes Namespaces Files Functions Variables Typedefs Enumerator Friends Macros Pages
cauchy.hpp
Go to the documentation of this file.
1 #ifndef __STAN__PROB__DISTRIBUTIONS__UNIVARIATE__CAUCHY_HPP__
2 #define __STAN__PROB__DISTRIBUTIONS__UNIVARIATE__CAUCHY_HPP__
3 
4 #include <boost/random/cauchy_distribution.hpp>
5 #include <boost/random/variate_generator.hpp>
6 
7 #include <stan/agrad.hpp>
8 #include <stan/prob/traits.hpp>
12 #include <stan/prob/constants.hpp>
13 
14 namespace stan {
15 
16  namespace prob {
17 
36  template <bool propto,
37  typename T_y, typename T_loc, typename T_scale,
38  class Policy>
39  typename return_type<T_y,T_loc,T_scale>::type
40  cauchy_log(const T_y& y, const T_loc& mu, const T_scale& sigma,
41  const Policy&) {
42  static const char* function = "stan::prob::cauchy_log(%1%)";
43 
50 
51  // check if any vectors are zero length
52  if (!(stan::length(y)
53  && stan::length(mu)
54  && stan::length(sigma)))
55  return 0.0;
56 
57  // set up return value accumulator
58  double logp(0.0);
59 
60  // validate args (here done over var, which should be OK)
61  if (!check_not_nan(function, y, "Random variable", &logp, Policy()))
62  return logp;
63  if (!check_finite(function, mu, "Location parameter",
64  &logp, Policy()))
65  return logp;
66  if (!check_positive(function, sigma, "Scale parameter",
67  &logp, Policy()))
68  return logp;
69  if (!check_finite(function, sigma, "Scale parameter",
70  &logp, Policy()))
71  return logp;
72  if (!(check_consistent_sizes(function,
73  y,mu,sigma,
74  "Random variable","Location parameter","Scale parameter",
75  &logp, Policy())))
76  return logp;
77 
78  // check if no variables are involved and prop-to
80  return 0.0;
81 
82  using stan::math::log1p;
83  using stan::math::square;
84 
85  // set up template expressions wrapping scalars into vector views
86  VectorView<const T_y> y_vec(y);
87  VectorView<const T_loc> mu_vec(mu);
88  VectorView<const T_scale> sigma_vec(sigma);
89  size_t N = max_size(y, mu, sigma);
90 
94  for (size_t i = 0; i < length(sigma); i++) {
95  const double sigma_dbl = value_of(sigma_vec[i]);
96  inv_sigma[i] = 1.0 / sigma_dbl;
97  sigma_squared[i] = sigma_dbl * sigma_dbl;
99  log_sigma[i] = log(sigma_dbl);
100  }
101  }
102 
103  agrad::OperandsAndPartials<T_y, T_loc, T_scale> operands_and_partials(y, mu, sigma);
104 
105  for (size_t n = 0; n < N; n++) {
106  // pull out values of arguments
107  const double y_dbl = value_of(y_vec[n]);
108  const double mu_dbl = value_of(mu_vec[n]);
109 
110  // reusable subexpression values
111  const double y_minus_mu
112  = y_dbl - mu_dbl;
113  const double y_minus_mu_squared
114  = y_minus_mu * y_minus_mu;
115  const double y_minus_mu_over_sigma
116  = y_minus_mu * inv_sigma[n];
117  const double y_minus_mu_over_sigma_squared
118  = y_minus_mu_over_sigma * y_minus_mu_over_sigma;
119 
120  // log probability
122  logp += NEG_LOG_PI;
124  logp -= log_sigma[n];
126  logp -= log1p(y_minus_mu_over_sigma_squared);
127 
128  // gradients
130  operands_and_partials.d_x1[n] -= 2 * y_minus_mu / (sigma_squared[n] + y_minus_mu_squared);
132  operands_and_partials.d_x2[n] += 2 * y_minus_mu / (sigma_squared[n] + y_minus_mu_squared);
134  operands_and_partials.d_x3[n] += (y_minus_mu_squared - sigma_squared[n]) * inv_sigma[n] / (sigma_squared[n] + y_minus_mu_squared);
135  }
136  return operands_and_partials.to_var(logp);
137  }
138 
139 
140  template <bool propto,
141  typename T_y, typename T_loc, typename T_scale>
142  inline
144  cauchy_log(const T_y& y, const T_loc& mu, const T_scale& sigma) {
145  return cauchy_log<propto>(y,mu,sigma,stan::math::default_policy());
146  }
147 
148  template <typename T_y, typename T_loc, typename T_scale,
149  class Policy>
150  inline
152  cauchy_log(const T_y& y, const T_loc& mu, const T_scale& sigma,
153  const Policy&) {
154  return cauchy_log<false>(y,mu,sigma,Policy());
155  }
156 
157  template <typename T_y, typename T_loc, typename T_scale>
158  inline
160  cauchy_log(const T_y& y, const T_loc& mu, const T_scale& sigma) {
161  return cauchy_log<false>(y,mu,sigma,stan::math::default_policy());
162  }
163 
164 
180  template <typename T_y, typename T_loc, typename T_scale, class Policy>
182  cauchy_cdf(const T_y& y, const T_loc& mu, const T_scale& sigma, const Policy&) {
183 
184  // Size checks
185  if ( !( stan::length(y) && stan::length(mu) && stan::length(sigma) ) ) return 1.0;
186 
187  static const char* function = "stan::prob::cauchy_cdf(%1%)";
188 
193  using boost::math::tools::promote_args;
194  using stan::math::value_of;
195 
196  double P(1.0);
197 
198  if(!check_not_nan(function, y, "Random variable", &P, Policy()))
199  return P;
200 
201  if(!check_finite(function, mu, "Location parameter", &P, Policy()))
202  return P;
203 
204  if(!check_finite(function, sigma, "Scale parameter", &P, Policy()))
205  return P;
206 
207  if(!check_positive(function, sigma, "Scale parameter", &P, Policy()))
208  return P;
209 
210  if (!(check_consistent_sizes(function, y, mu, sigma,
211  "Random variable", "Location parameter", "Scale Parameter",
212  &P, Policy())))
213  return P;
214 
215  // Wrap arguments in vectors
216  VectorView<const T_y> y_vec(y);
217  VectorView<const T_loc> mu_vec(mu);
218  VectorView<const T_scale> sigma_vec(sigma);
219  size_t N = max_size(y, mu, sigma);
220 
221  agrad::OperandsAndPartials<T_y, T_loc, T_scale> operands_and_partials(y, mu, sigma);
222 
223  std::fill(operands_and_partials.all_partials,
224  operands_and_partials.all_partials + operands_and_partials.nvaris, 0.0);
225 
226  // Explicit return for extreme values
227  // The gradients are technically ill-defined, but treated as zero
228  for (size_t i = 0; i < stan::length(y); i++) {
229  if (value_of(y_vec[i]) == -std::numeric_limits<double>::infinity())
230  return operands_and_partials.to_var(0.0);
231  }
232 
233  // Compute CDF and its gradients
234  using std::atan;
235  using stan::math::pi;
236 
237  // Compute vectorized CDF and gradient
238  for (size_t n = 0; n < N; n++) {
239 
240  // Explicit results for extreme values
241  // The gradients are technically ill-defined, but treated as zero
242  if (value_of(y_vec[n]) == std::numeric_limits<double>::infinity()) {
243  continue;
244  }
245 
246  // Pull out values
247  const double y_dbl = value_of(y_vec[n]);
248  const double mu_dbl = value_of(mu_vec[n]);
249  const double sigma_inv_dbl = 1.0 / value_of(sigma_vec[n]);
250 
251  const double z = (y_dbl - mu_dbl) * sigma_inv_dbl;
252 
253  // Compute
254  const double Pn = atan(z) / pi() + 0.5;
255 
256  P *= Pn;
257 
259  operands_and_partials.d_x1[n]
260  += sigma_inv_dbl / (pi() * (1.0 + z * z) * Pn);
261 
263  operands_and_partials.d_x2[n]
264  += - sigma_inv_dbl / (pi() * (1.0 + z * z) * Pn);
265 
267  operands_and_partials.d_x3[n]
268  += - z * sigma_inv_dbl / (pi() * (1.0 + z * z) * Pn);
269 
270  }
271 
273  for(size_t n = 0; n < stan::length(y); ++n) operands_and_partials.d_x1[n] *= P;
274  }
275 
277  for(size_t n = 0; n < stan::length(mu); ++n) operands_and_partials.d_x2[n] *= P;
278  }
279 
281  for(size_t n = 0; n < stan::length(sigma); ++n) operands_and_partials.d_x3[n] *= P;
282  }
283 
284  return operands_and_partials.to_var(P);
285  }
286 
287  template <typename T_y, typename T_loc, typename T_scale>
289  cauchy_cdf(const T_y& y, const T_loc& mu, const T_scale& sigma) {
290  return cauchy_cdf(y, mu, sigma, stan::math::default_policy());
291  }
292 
293  template <class RNG>
294  inline double
295  cauchy_rng(const double mu,
296  const double sigma,
297  RNG& rng) {
298  using boost::variate_generator;
299  using boost::random::cauchy_distribution;
300  variate_generator<RNG&, cauchy_distribution<> >
301  cauchy_rng(rng, cauchy_distribution<>(mu, sigma));
302  return cauchy_rng();
303  }
304  }
305 }
306 #endif

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