Stan  2.5.0
probability, sampling & optimization
 All Classes Namespaces Files Functions Variables Typedefs Enumerations 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 
8 #include <stan/prob/traits.hpp>
10 #include <stan/math/constants.hpp>
15 #include <stan/prob/constants.hpp>
16 
17 namespace stan {
18 
19  namespace prob {
20 
39  template <bool propto,
40  typename T_y, typename T_loc, typename T_scale>
41  typename return_type<T_y,T_loc,T_scale>::type
42  cauchy_log(const T_y& y, const T_loc& mu, const T_scale& sigma) {
43  static const char* function = "stan::prob::cauchy_log(%1%)";
44 
51 
52  // check if any vectors are zero length
53  if (!(stan::length(y)
54  && stan::length(mu)
55  && stan::length(sigma)))
56  return 0.0;
57 
58  // set up return value accumulator
59  double logp(0.0);
60 
61  // validate args (here done over var, which should be OK)
62  check_not_nan(function, y, "Random variable", &logp);
63  check_finite(function, mu, "Location parameter", &logp);
64  check_positive_finite(function, sigma, "Scale parameter", &logp);
65  check_consistent_sizes(function,
66  y,mu,sigma,
67  "Random variable","Location parameter",
68  "Scale parameter",
69  &logp);
70 
71  // check if no variables are involved and prop-to
73  return 0.0;
74 
75  using stan::math::log1p;
76  using stan::math::square;
77 
78  // set up template expressions wrapping scalars into vector views
79  VectorView<const T_y> y_vec(y);
80  VectorView<const T_loc> mu_vec(mu);
81  VectorView<const T_scale> sigma_vec(sigma);
82  size_t N = max_size(y, mu, sigma);
83 
87  is_vector<T_scale>::value> log_sigma(length(sigma));
88  for (size_t i = 0; i < length(sigma); i++) {
89  const double sigma_dbl = value_of(sigma_vec[i]);
90  inv_sigma[i] = 1.0 / sigma_dbl;
91  sigma_squared[i] = sigma_dbl * sigma_dbl;
93  log_sigma[i] = log(sigma_dbl);
94  }
95  }
96 
97  agrad::OperandsAndPartials<T_y, T_loc, T_scale> operands_and_partials(y, mu, sigma);
98 
99  for (size_t n = 0; n < N; n++) {
100  // pull out values of arguments
101  const double y_dbl = value_of(y_vec[n]);
102  const double mu_dbl = value_of(mu_vec[n]);
103 
104  // reusable subexpression values
105  const double y_minus_mu
106  = y_dbl - mu_dbl;
107  const double y_minus_mu_squared
108  = y_minus_mu * y_minus_mu;
109  const double y_minus_mu_over_sigma
110  = y_minus_mu * inv_sigma[n];
111  const double y_minus_mu_over_sigma_squared
112  = y_minus_mu_over_sigma * y_minus_mu_over_sigma;
113 
114  // log probability
116  logp += NEG_LOG_PI;
118  logp -= log_sigma[n];
120  logp -= log1p(y_minus_mu_over_sigma_squared);
121 
122  // gradients
124  operands_and_partials.d_x1[n] -= 2 * y_minus_mu / (sigma_squared[n] + y_minus_mu_squared);
126  operands_and_partials.d_x2[n] += 2 * y_minus_mu / (sigma_squared[n] + y_minus_mu_squared);
128  operands_and_partials.d_x3[n] += (y_minus_mu_squared - sigma_squared[n]) * inv_sigma[n] / (sigma_squared[n] + y_minus_mu_squared);
129  }
130  return operands_and_partials.to_var(logp);
131  }
132 
133  template <typename T_y, typename T_loc, typename T_scale>
134  inline
136  cauchy_log(const T_y& y, const T_loc& mu, const T_scale& sigma) {
137  return cauchy_log<false>(y,mu,sigma);
138  }
139 
140 
156  template <typename T_y, typename T_loc, typename T_scale>
158  cauchy_cdf(const T_y& y, const T_loc& mu, const T_scale& sigma) {
159 
160  // Size checks
161  if ( !( stan::length(y) && stan::length(mu)
162  && stan::length(sigma) ) )
163  return 1.0;
164 
165  static const char* function = "stan::prob::cauchy_cdf(%1%)";
166 
171  using boost::math::tools::promote_args;
172  using stan::math::value_of;
173 
174  double P(1.0);
175 
176  check_not_nan(function, y, "Random variable", &P);
177  check_finite(function, mu, "Location parameter", &P);
178  check_positive_finite(function, sigma, "Scale parameter", &P);
179  check_consistent_sizes(function, y, mu, sigma,
180  "Random variable", "Location parameter",
181  "Scale Parameter",
182  &P);
183 
184  // Wrap arguments in vectors
185  VectorView<const T_y> y_vec(y);
186  VectorView<const T_loc> mu_vec(mu);
187  VectorView<const T_scale> sigma_vec(sigma);
188  size_t N = max_size(y, mu, sigma);
189 
191  operands_and_partials(y, mu, sigma);
192 
193  // Explicit return for extreme values
194  // The gradients are technically ill-defined, but treated as zero
195  for (size_t i = 0; i < stan::length(y); i++) {
196  if (value_of(y_vec[i]) == -std::numeric_limits<double>::infinity())
197  return operands_and_partials.to_var(0.0);
198  }
199 
200  // Compute CDF and its gradients
201  using std::atan;
202  using stan::math::pi;
203 
204  // Compute vectorized CDF and gradient
205  for (size_t n = 0; n < N; n++) {
206 
207  // Explicit results for extreme values
208  // The gradients are technically ill-defined, but treated as zero
209  if (value_of(y_vec[n]) == std::numeric_limits<double>::infinity()) {
210  continue;
211  }
212 
213  // Pull out values
214  const double y_dbl = value_of(y_vec[n]);
215  const double mu_dbl = value_of(mu_vec[n]);
216  const double sigma_inv_dbl = 1.0 / value_of(sigma_vec[n]);
217 
218  const double z = (y_dbl - mu_dbl) * sigma_inv_dbl;
219 
220  // Compute
221  const double Pn = atan(z) / pi() + 0.5;
222 
223  P *= Pn;
224 
226  operands_and_partials.d_x1[n]
227  += sigma_inv_dbl / (pi() * (1.0 + z * z) * Pn);
229  operands_and_partials.d_x2[n]
230  += - sigma_inv_dbl / (pi() * (1.0 + z * z) * Pn);
232  operands_and_partials.d_x3[n]
233  += - z * sigma_inv_dbl / (pi() * (1.0 + z * z) * Pn);
234 
235  }
236 
238  for(size_t n = 0; n < stan::length(y); ++n)
239  operands_and_partials.d_x1[n] *= P;
240  }
242  for(size_t n = 0; n < stan::length(mu); ++n)
243  operands_and_partials.d_x2[n] *= P;
244  }
246  for(size_t n = 0; n < stan::length(sigma); ++n)
247  operands_and_partials.d_x3[n] *= P;
248  }
249 
250  return operands_and_partials.to_var(P);
251  }
252 
253  template <typename T_y, typename T_loc, typename T_scale>
255  cauchy_cdf_log(const T_y& y, const T_loc& mu, const T_scale& sigma) {
256 
257  // Size checks
258  if ( !( stan::length(y) && stan::length(mu)
259  && stan::length(sigma) ) )
260  return 0.0;
261 
262  static const char* function = "stan::prob::cauchy_cdf(%1%)";
263 
268  using boost::math::tools::promote_args;
269  using stan::math::value_of;
270 
271  double cdf_log(0.0);
272 
273  check_not_nan(function, y, "Random variable", &cdf_log);
274  check_finite(function, mu, "Location parameter", &cdf_log);
275  check_positive_finite(function, sigma, "Scale parameter", &cdf_log);
276  check_consistent_sizes(function, y, mu, sigma,
277  "Random variable", "Location parameter",
278  "Scale Parameter", &cdf_log);
279 
280  // Wrap arguments in vectors
281  VectorView<const T_y> y_vec(y);
282  VectorView<const T_loc> mu_vec(mu);
283  VectorView<const T_scale> sigma_vec(sigma);
284  size_t N = max_size(y, mu, sigma);
285 
287  operands_and_partials(y, mu, sigma);
288 
289  // Compute CDFLog and its gradients
290  using std::atan;
291  using stan::math::pi;
292 
293  // Compute vectorized CDF and gradient
294  for (size_t n = 0; n < N; n++) {
295 
296  // Pull out values
297  const double y_dbl = value_of(y_vec[n]);
298  const double mu_dbl = value_of(mu_vec[n]);
299  const double sigma_inv_dbl = 1.0 / value_of(sigma_vec[n]);
300  const double sigma_dbl = value_of(sigma_vec[n]);
301 
302  const double z = (y_dbl - mu_dbl) * sigma_inv_dbl;
303 
304  // Compute
305  const double Pn = atan(z) / pi() + 0.5;
306  cdf_log += log(Pn);
307 
308  const double rep_deriv = 1.0 / (pi() * Pn
309  * (z * z * sigma_dbl + sigma_dbl));
311  operands_and_partials.d_x1[n] += rep_deriv;
313  operands_and_partials.d_x2[n] -= rep_deriv;
315  operands_and_partials.d_x3[n] -= rep_deriv * z;
316  }
317  return operands_and_partials.to_var(cdf_log);
318  }
319 
320  template <typename T_y, typename T_loc, typename T_scale>
322  cauchy_ccdf_log(const T_y& y, const T_loc& mu, const T_scale& sigma) {
323 
324  // Size checks
325  if ( !( stan::length(y) && stan::length(mu)
326  && stan::length(sigma) ) )
327  return 0.0;
328 
329  static const char* function = "stan::prob::cauchy_cdf(%1%)";
330 
335  using boost::math::tools::promote_args;
336  using stan::math::value_of;
337 
338  double ccdf_log(0.0);
339 
340  check_not_nan(function, y, "Random variable", &ccdf_log);
341  check_finite(function, mu, "Location parameter", &ccdf_log);
342  check_positive_finite(function, sigma, "Scale parameter", &ccdf_log);
343  check_consistent_sizes(function, y, mu, sigma,
344  "Random variable", "Location parameter",
345  "Scale Parameter", &ccdf_log);
346 
347  // Wrap arguments in vectors
348  VectorView<const T_y> y_vec(y);
349  VectorView<const T_loc> mu_vec(mu);
350  VectorView<const T_scale> sigma_vec(sigma);
351  size_t N = max_size(y, mu, sigma);
352 
354  operands_and_partials(y, mu, sigma);
355 
356  // Compute CDFLog and its gradients
357  using std::atan;
358  using stan::math::pi;
359 
360  // Compute vectorized CDF and gradient
361  for (size_t n = 0; n < N; n++) {
362 
363  // Pull out values
364  const double y_dbl = value_of(y_vec[n]);
365  const double mu_dbl = value_of(mu_vec[n]);
366  const double sigma_inv_dbl = 1.0 / value_of(sigma_vec[n]);
367  const double sigma_dbl = value_of(sigma_vec[n]);
368  const double z = (y_dbl - mu_dbl) * sigma_inv_dbl;
369 
370  // Compute
371  const double Pn = 0.5 - atan(z) / pi();
372  ccdf_log += log(Pn);
373 
374  const double rep_deriv = 1.0 / (Pn * pi()
375  * (z * z * sigma_dbl + sigma_dbl));
377  operands_and_partials.d_x1[n] -= rep_deriv;
379  operands_and_partials.d_x2[n] += rep_deriv;
381  operands_and_partials.d_x3[n] += rep_deriv * z;
382  }
383  return operands_and_partials.to_var(ccdf_log);
384  }
385 
386  template <class RNG>
387  inline double
388  cauchy_rng(const double mu,
389  const double sigma,
390  RNG& rng) {
391  using boost::variate_generator;
392  using boost::random::cauchy_distribution;
393 
394  static const char* function = "stan::prob::cauchy_rng(%1%)";
395 
398 
399  check_finite(function, mu, "Location parameter", (double*)0);
400  check_positive_finite(function, sigma, "Scale parameter", (double*)0);
401 
402  variate_generator<RNG&, cauchy_distribution<> >
403  cauchy_rng(rng, cauchy_distribution<>(mu, sigma));
404  return cauchy_rng();
405  }
406  }
407 }
408 #endif
T square(const T x)
Return the square of the specified argument.
Definition: square.hpp:22
double cauchy_rng(const double mu, const double sigma, RNG &rng)
Definition: cauchy.hpp:388
boost::math::tools::promote_args< T >::type log1p(const T x)
Return the natural logarithm of one plus the specified value.
Definition: log1p.hpp:39
T_return_type to_var(double logp)
bool check_positive_finite(const char *function, const T_y &y, const char *name, T_result *result)
size_t length(const T &)
Definition: traits.hpp:159
DoubleVectorView allocates double values to be used as intermediate values.
Definition: traits.hpp:358
bool check_finite(const char *function, const T_y &y, const char *name, T_result *result)
Checks if the variable y is finite.
return_type< T_y, T_loc, T_scale >::type cauchy_cdf_log(const T_y &y, const T_loc &mu, const T_scale &sigma)
Definition: cauchy.hpp:255
T value_of(const fvar< T > &v)
Return the value of the specified variable.
Definition: value_of.hpp:16
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
fvar< T > atan(const fvar< T > &x)
Definition: atan.hpp:16
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
return_type< T_y, T_loc, T_scale >::type cauchy_ccdf_log(const T_y &y, const T_loc &mu, const T_scale &sigma)
Definition: cauchy.hpp:322
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
return_type< T_y, T_loc, T_scale >::type cauchy_log(const T_y &y, const T_loc &mu, const T_scale &sigma)
The log of the Cauchy density for the specified scalar(s) given the specified location parameter(s) a...
Definition: cauchy.hpp:42
bool check_not_nan(const char *function, const T_y &y, const char *name, T_result *result)
Checks if the variable y is nan.
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
double pi()
Return the value of pi.
Definition: constants.hpp:77
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
fvar< T > log1p(const fvar< T > &x)
Definition: log1p.hpp:16
return_type< T_y, T_loc, T_scale >::type cauchy_cdf(const T_y &y, const T_loc &mu, const T_scale &sigma)
Calculates the cauchy cumulative distribution function for the given variate, location, and scale.
Definition: cauchy.hpp:158

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