Stan  2.5.0
probability, sampling & optimization
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
rayleigh.hpp
Go to the documentation of this file.
1 #ifndef STAN__PROB__DISTRIBUTIONS__UNIVARIATE__CONTINUOUS__RAYLEIGH_HPP
2 #define STAN__PROB__DISTRIBUTIONS__UNIVARIATE__CONTINUOUS__RAYLEIGH_HPP
3 
4 #include <boost/random/uniform_real_distribution.hpp>
5 #include <boost/random/variate_generator.hpp>
6 
8 #include <stan/math.hpp>
10 #include <stan/meta/traits.hpp>
11 #include <stan/prob/constants.hpp>
12 #include <stan/prob/traits.hpp>
13 
14 namespace stan {
15 
16  namespace prob {
17 
18  template <bool propto,
19  typename T_y, typename T_scale>
20  typename return_type<T_y,T_scale>::type
21  rayleigh_log(const T_y& y, const T_scale& sigma) {
22  static const char* function = "stan::prob::rayleigh_log(%1%)";
23 
24  using std::log;
31 
32  // check if any vectors are zero length
33  if (!(stan::length(y) && stan::length(sigma)))
34  return 0.0;
35 
36  // set up return value accumulator
37  double logp(0.0);
38 
39  // validate args (here done over var, which should be OK)
40  check_not_nan(function, y, "Random variable", &logp);
41  check_positive(function, sigma, "Scale parameter", &logp);
42  check_positive(function, y, "Random variable", &logp);
43  check_consistent_sizes(function,
44  y,sigma,
45  "Random variable","Scale parameter",
46  &logp);
47 
48  // check if no variables are involved and prop-to
50  return 0.0;
51 
52  // set up template expressions wrapping scalars into vector views
53  agrad::OperandsAndPartials<T_y, T_scale> operands_and_partials(y, sigma);
54 
55  VectorView<const T_y> y_vec(y);
56  VectorView<const T_scale> sigma_vec(sigma);
57  size_t N = max_size(y, sigma);
58 
61  is_vector<T_scale>::value> log_sigma(length(sigma));
62  for (size_t i = 0; i < length(sigma); i++) {
63  inv_sigma[i] = 1.0 / value_of(sigma_vec[i]);
65  log_sigma[i] = log(value_of(sigma_vec[i]));
66  }
67 
68  for (size_t n = 0; n < N; n++) {
69  // pull out values of arguments
70  const double y_dbl = value_of(y_vec[n]);
71 
72  // reusable subexpression values
73  const double y_over_sigma = y_dbl * inv_sigma[n];
74 
75  static double NEGATIVE_HALF = -0.5;
76 
77  // log probability
79  logp -= 2.0 * log_sigma[n];
81  logp += log(y_dbl);
82  // if (include_summand<propto,T_y,T_scale>::value)
83  logp += NEGATIVE_HALF * y_over_sigma * y_over_sigma;
84 
85  // gradients
86  double scaled_diff = inv_sigma[n] * y_over_sigma;
88  operands_and_partials.d_x1[n] += 1.0 / y_dbl - scaled_diff;
90  operands_and_partials.d_x2[n]
91  += y_over_sigma * scaled_diff - 2.0 * inv_sigma[n];
92  }
93  return operands_and_partials.to_var(logp);
94  }
95 
96  template <typename T_y, typename T_scale>
97  inline
99  rayleigh_log(const T_y& y, const T_scale& sigma) {
100  return rayleigh_log<false>(y,sigma);
101  }
102 
103  template <typename T_y, typename T_scale>
105  rayleigh_cdf(const T_y& y, const T_scale& sigma) {
106  static const char* function = "stan::prob::rayleigh_cdf(%1%)";
107 
114  using stan::math::square;
115  using stan::math::value_of;
116 
117  double cdf(1.0);
118 
119  // check if any vectors are zero length
120  if (!(stan::length(y) && stan::length(sigma)))
121  return cdf;
122 
123  check_not_nan(function, y, "Random variable", &cdf);
124  check_nonnegative(function, y, "Random variable", &cdf);
125  check_not_nan(function, sigma, "Scale parameter", &cdf);
126  check_positive(function, sigma, "Scale parameter", &cdf);
127  check_consistent_sizes(function,
128  y,sigma,
129  "Random variable","Scale parameter",
130  &cdf);
131 
132 
133  // set up template expressions wrapping scalars into vector views
134  agrad::OperandsAndPartials<T_y, T_scale> operands_and_partials(y, sigma);
135 
136  VectorView<const T_y> y_vec(y);
137  VectorView<const T_scale> sigma_vec(sigma);
138  size_t N = max_size(y, sigma);
139 
141  for (size_t i = 0; i < length(sigma); i++) {
142  inv_sigma[i] = 1.0 / value_of(sigma_vec[i]);
143  }
144 
145  for (size_t n = 0; n < N; n++) {
146  const double y_dbl = value_of(y_vec[n]);
147  const double y_sqr = y_dbl * y_dbl;
148  const double inv_sigma_sqr = inv_sigma[n] * inv_sigma[n];
149  const double exp_val = exp(-0.5 * y_sqr * inv_sigma_sqr);
150 
152  cdf *= (1.0 - exp_val);
153  }
154 
155  //gradients
156  for (size_t n = 0; n < N; n++) {
157  const double y_dbl = value_of(y_vec[n]);
158  const double y_sqr = square(y_dbl);
159  const double inv_sigma_sqr = square(inv_sigma[n]);
160  const double exp_val = exp(-0.5 * y_sqr * inv_sigma_sqr);
161  const double exp_div_1m_exp = exp_val / (1.0 - exp_val);
162 
164  operands_and_partials.d_x1[n] += y_dbl * inv_sigma_sqr
165  * exp_div_1m_exp * cdf;
167  operands_and_partials.d_x2[n] -= y_sqr * inv_sigma_sqr
168  * inv_sigma[n] * exp_div_1m_exp * cdf;
169  }
170 
171  return operands_and_partials.to_var(cdf);
172  }
173 
174  template <typename T_y, typename T_scale>
176  rayleigh_cdf_log(const T_y& y, const T_scale& sigma) {
177  static const char* function = "stan::prob::rayleigh_cdf_log(%1%)";
178 
185  using stan::math::square;
186  using stan::math::value_of;
187 
188  double cdf_log(0.0);
189 
190  // check if any vectors are zero length
191  if (!(stan::length(y) && stan::length(sigma)))
192  return cdf_log;
193 
194  check_not_nan(function, y, "Random variable", &cdf_log);
195  check_nonnegative(function, y, "Random variable", &cdf_log);
196  check_not_nan(function, sigma, "Scale parameter", &cdf_log);
197  check_positive(function, sigma, "Scale parameter", &cdf_log);
198  check_consistent_sizes(function,
199  y,sigma,
200  "Random variable","Scale parameter",
201  &cdf_log);
202 
203 
204  // set up template expressions wrapping scalars into vector views
205  agrad::OperandsAndPartials<T_y, T_scale> operands_and_partials(y, sigma);
206 
207  VectorView<const T_y> y_vec(y);
208  VectorView<const T_scale> sigma_vec(sigma);
209  size_t N = max_size(y, sigma);
210 
212  for (size_t i = 0; i < length(sigma); i++) {
213  inv_sigma[i] = 1.0 / value_of(sigma_vec[i]);
214  }
215 
216  for (size_t n = 0; n < N; n++) {
217  const double y_dbl = value_of(y_vec[n]);
218  const double y_sqr = y_dbl * y_dbl;
219  const double inv_sigma_sqr = inv_sigma[n] * inv_sigma[n];
220  const double exp_val = exp(-0.5 * y_sqr * inv_sigma_sqr);
221  const double exp_div_1m_exp = exp_val / (1.0 - exp_val);
222 
224  cdf_log += log(1.0 - exp_val);
225 
227  operands_and_partials.d_x1[n] += y_dbl * inv_sigma_sqr
228  * exp_div_1m_exp;
230  operands_and_partials.d_x2[n] -= y_sqr * inv_sigma_sqr
231  * inv_sigma[n] * exp_div_1m_exp;
232  }
233 
234  return operands_and_partials.to_var(cdf_log);
235  }
236 
237  template <typename T_y, typename T_scale>
239  rayleigh_ccdf_log(const T_y& y, const T_scale& sigma) {
240  static const char* function = "stan::prob::rayleigh_ccdf_log(%1%)";
241 
248  using stan::math::square;
249  using stan::math::value_of;
250 
251  double ccdf_log(0.0);
252 
253  // check if any vectors are zero length
254  if (!(stan::length(y) && stan::length(sigma)))
255  return ccdf_log;
256 
257  check_not_nan(function, y, "Random variable", &ccdf_log);
258  check_nonnegative(function, y, "Random variable", &ccdf_log);
259  check_not_nan(function, sigma, "Scale parameter", &ccdf_log);
260  check_positive(function, sigma, "Scale parameter", &ccdf_log);
261  check_consistent_sizes(function,
262  y,sigma,
263  "Random variable","Scale parameter",
264  &ccdf_log);
265 
266 
267  // set up template expressions wrapping scalars into vector views
268  agrad::OperandsAndPartials<T_y, T_scale> operands_and_partials(y, sigma);
269 
270  VectorView<const T_y> y_vec(y);
271  VectorView<const T_scale> sigma_vec(sigma);
272  size_t N = max_size(y, sigma);
273 
275  for (size_t i = 0; i < length(sigma); i++) {
276  inv_sigma[i] = 1.0 / value_of(sigma_vec[i]);
277  }
278 
279  for (size_t n = 0; n < N; n++) {
280  const double y_dbl = value_of(y_vec[n]);
281  const double y_sqr = y_dbl * y_dbl;
282  const double inv_sigma_sqr = inv_sigma[n] * inv_sigma[n];
283 
285  ccdf_log += -0.5 * y_sqr * inv_sigma_sqr;
286 
288  operands_and_partials.d_x1[n] -= y_dbl * inv_sigma_sqr;
290  operands_and_partials.d_x2[n] += y_sqr * inv_sigma_sqr
291  * inv_sigma[n];
292  }
293 
294  return operands_and_partials.to_var(ccdf_log);
295  }
296 
297  template <class RNG>
298  inline double
299  rayleigh_rng(const double sigma,
300  RNG& rng) {
301  using boost::variate_generator;
302  using boost::random::uniform_real_distribution;
303 
304  static const char* function = "stan::prob::rayleigh_rng(%1%)";
305 
307 
308  check_positive(function, sigma, "Scale parameter", (double*)0);
309 
310  variate_generator<RNG&, uniform_real_distribution<> >
311  uniform_rng(rng, uniform_real_distribution<>(0.0, 1.0));
312  return sigma * std::sqrt(-2.0 * std::log(uniform_rng()));
313  }
314  }
315 }
316 #endif
T square(const T x)
Return the square of the specified argument.
Definition: square.hpp:22
return_type< T_y, T_scale >::type rayleigh_cdf(const T_y &y, const T_scale &sigma)
Definition: rayleigh.hpp:105
T_return_type to_var(double logp)
size_t length(const T &)
Definition: traits.hpp:159
fvar< T > square(const fvar< T > &x)
Definition: square.hpp:15
DoubleVectorView allocates double values to be used as intermediate values.
Definition: traits.hpp:358
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
return_type< T_y, T_scale >::type rayleigh_ccdf_log(const T_y &y, const T_scale &sigma)
Definition: rayleigh.hpp:239
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
fvar< T > sqrt(const fvar< T > &x)
Definition: sqrt.hpp:15
VectorView< double *, is_vector< T2 >::value, is_constant_struct< T2 >::value > d_x2
double uniform_rng(const double alpha, const double beta, RNG &rng)
Definition: uniform.hpp:339
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
bool check_positive(const char *function, const T_y &y, const char *name, T_result *result)
return_type< T_y, T_scale >::type rayleigh_cdf_log(const T_y &y, const T_scale &sigma)
Definition: rayleigh.hpp:176
return_type< T_y, T_scale >::type rayleigh_log(const T_y &y, const T_scale &sigma)
Definition: rayleigh.hpp:21
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
double rayleigh_rng(const double sigma, RNG &rng)
Definition: rayleigh.hpp:299
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 > exp(const fvar< T > &x)
Definition: exp.hpp:16

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