1 #ifndef STAN__PROB__DISTRIBUTIONS__DOUBLE_EXPONENTIAL_HPP
2 #define STAN__PROB__DISTRIBUTIONS__DOUBLE_EXPONENTIAL_HPP
4 #include <boost/random/uniform_01.hpp>
5 #include <boost/random/variate_generator.hpp>
21 template <
bool propto,
22 typename T_y,
typename T_loc,
typename T_scale>
23 typename return_type<T_y,T_loc,T_scale>::type
25 const T_loc& mu,
const T_scale& sigma) {
26 static const char*
function
27 =
"stan::prob::double_exponential_log(%1%)";
51 "Random variable",
"Location parameter",
52 "Shape parameter",&logp);
68 inv_sigma_squared(
length(sigma));
71 for (
size_t i = 0; i <
length(sigma); i++) {
72 const double sigma_dbl =
value_of(sigma_vec[i]);
74 inv_sigma[i] = 1.0 / sigma_dbl;
78 inv_sigma_squared[i] = inv_sigma[i] * inv_sigma[i];
82 for (
size_t n = 0; n < N; n++) {
83 const double y_dbl =
value_of(y_vec[n]);
84 const double mu_dbl =
value_of(mu_vec[n]);
87 const double y_m_mu = y_dbl - mu_dbl;
88 const double fabs_y_m_mu =
fabs(y_m_mu);
96 logp -= fabs_y_m_mu * inv_sigma[n];
99 double sign_y_m_mu_times_inv_sigma(0);
101 sign_y_m_mu_times_inv_sigma =
sign(y_m_mu) * inv_sigma[n];
103 operands_and_partials.
d_x1[n] -= sign_y_m_mu_times_inv_sigma;
106 operands_and_partials.
d_x2[n] += sign_y_m_mu_times_inv_sigma;
109 operands_and_partials.
d_x3[n] += -inv_sigma[n] + fabs_y_m_mu * inv_sigma_squared[n];
111 return operands_and_partials.
to_var(logp);
115 template <
typename T_y,
typename T_loc,
typename T_scale>
118 const T_scale& sigma) {
119 return double_exponential_log<false>(y,mu,sigma);
136 template <
typename T_y,
typename T_loc,
typename T_scale>
139 const T_loc& mu,
const T_scale& sigma) {
140 static const char*
function
141 =
"stan::prob::double_exponential_cdf(%1%)";
152 using boost::math::tools::promote_args;
160 operands_and_partials(y, mu, sigma);
168 for (
size_t n = 0; n < N; n++) {
169 const double y_dbl =
value_of(y_vec[n]);
170 const double mu_dbl =
value_of(mu_vec[n]);
171 const double sigma_dbl =
value_of(sigma_vec[n]);
172 const double scaled_diff = (y_dbl - mu_dbl) / (sigma_dbl);
173 const double exp_scaled_diff =
exp(scaled_diff);
176 cdf *= exp_scaled_diff * 0.5;
179 cdf *= 1.0 - 0.5 / exp_scaled_diff;
183 for (
size_t n = 0; n < N; n++) {
184 const double y_dbl =
value_of(y_vec[n]);
185 const double mu_dbl =
value_of(mu_vec[n]);
186 const double sigma_dbl =
value_of(sigma_vec[n]);
187 const double scaled_diff = (y_dbl - mu_dbl) / sigma_dbl;
188 const double exp_scaled_diff =
exp(scaled_diff);
189 const double inv_sigma = 1.0 / sigma_dbl;
193 operands_and_partials.
d_x1[n] += inv_sigma * cdf;
195 operands_and_partials.
d_x2[n] -= inv_sigma * cdf;
197 operands_and_partials.
d_x3[n] -= scaled_diff * inv_sigma * cdf;
200 const double rep_deriv = cdf * inv_sigma / (2.0 * exp_scaled_diff
203 operands_and_partials.
d_x1[n] += rep_deriv;
205 operands_and_partials.
d_x2[n] -= rep_deriv;
207 operands_and_partials.
d_x3[n] -= rep_deriv * scaled_diff;
210 return operands_and_partials.
to_var(cdf);
213 template <
typename T_y,
typename T_loc,
typename T_scale>
216 const T_scale& sigma) {
217 static const char*
function
218 =
"stan::prob::double_exponential_cdf_log(%1%)";
235 check_finite(
function, mu,
"Location parameter", &cdf_log);
238 "Random variable",
"Location parameter",
239 "Scale Parameter", &cdf_log);
245 operands_and_partials(y, mu, sigma);
250 const double log_half =
std::log(0.5);
253 for (
size_t n = 0; n < N; n++) {
254 const double y_dbl =
value_of(y_vec[n]);
255 const double mu_dbl =
value_of(mu_vec[n]);
256 const double sigma_dbl =
value_of(sigma_vec[n]);
257 const double scaled_diff = (y_dbl - mu_dbl) / sigma_dbl;
258 const double inv_sigma = 1.0 / sigma_dbl;
261 cdf_log += log_half + scaled_diff;
265 operands_and_partials.
d_x1[n] += inv_sigma;
267 operands_and_partials.
d_x2[n] -= inv_sigma;
269 operands_and_partials.
d_x3[n] -= scaled_diff * inv_sigma;
273 cdf_log +=
log(1.0 - 0.5 *
exp(-scaled_diff));
276 const double rep_deriv = 1.0 / (2.0 *
exp(scaled_diff) - 1.0);
278 operands_and_partials.
d_x1[n] += rep_deriv * inv_sigma;
280 operands_and_partials.
d_x2[n] -= rep_deriv * inv_sigma;
282 operands_and_partials.
d_x3[n] -= rep_deriv * scaled_diff
286 return operands_and_partials.
to_var(cdf_log);
289 template <
typename T_y,
typename T_loc,
typename T_scale>
292 const T_scale& sigma) {
293 static const char*
function
294 =
"stan::prob::double_exponential_ccdf_log(%1%)";
302 double ccdf_log(0.0);
311 check_finite(
function, mu,
"Location parameter", &ccdf_log);
314 "Random variable",
"Location parameter",
315 "Scale Parameter", &ccdf_log);
321 operands_and_partials(y, mu, sigma);
326 const double log_half =
std::log(0.5);
329 for (
size_t n = 0; n < N; n++) {
330 const double y_dbl =
value_of(y_vec[n]);
331 const double mu_dbl =
value_of(mu_vec[n]);
332 const double sigma_dbl =
value_of(sigma_vec[n]);
333 const double scaled_diff = (y_dbl - mu_dbl) / sigma_dbl;
334 const double inv_sigma = 1.0 / sigma_dbl;
337 ccdf_log +=
log(1.0 - 0.5 *
exp(scaled_diff));
340 const double rep_deriv = 1.0 / (2.0 *
exp(-scaled_diff) - 1.0);
342 operands_and_partials.
d_x1[n] -= rep_deriv * inv_sigma;
344 operands_and_partials.
d_x2[n] += rep_deriv * inv_sigma;
346 operands_and_partials.
d_x3[n] += rep_deriv * scaled_diff
351 ccdf_log += log_half - scaled_diff;
355 operands_and_partials.
d_x1[n] -= inv_sigma;
357 operands_and_partials.
d_x2[n] += inv_sigma;
359 operands_and_partials.
d_x3[n] += scaled_diff * inv_sigma;
362 return operands_and_partials.
to_var(ccdf_log);
370 using boost::variate_generator;
371 using boost::random::uniform_01;
375 static const char*
function
376 =
"stan::prob::double_exponential_rng(%1%)";
381 check_finite(
function, mu,
"Location parameter", (
double*)0);
384 variate_generator<RNG&, uniform_01<> >
385 rng_unit_01(rng, uniform_01<>());
387 double laplaceRN = rng_unit_01();
388 if(0.5 - laplaceRN > 0)
390 else if(0.5 - laplaceRN < 0)
392 return mu - sigma * a *
log(1 - 2 *
abs(0.5 - laplaceRN));
fvar< T > fabs(const fvar< T > &x)
T_return_type to_var(double logp)
bool check_positive_finite(const char *function, const T_y &y, const char *name, T_result *result)
return_type< T_y, T_loc, T_scale >::type double_exponential_log(const T_y &y, const T_loc &mu, const T_scale &sigma)
DoubleVectorView allocates double values to be used as intermediate values.
bool check_finite(const char *function, const T_y &y, const char *name, T_result *result)
Checks if the variable y is finite.
T value_of(const fvar< T > &v)
Return the value of the specified variable.
return_type< T_y, T_loc, T_scale >::type double_exponential_ccdf_log(const T_y &y, const T_loc &mu, const T_scale &sigma)
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
Metaprogram to determine if a type has a base scalar type that can be assigned to type double...
double value_of(const T x)
Return the value of the specified scalar argument converted to a double value.
Template metaprogram to calculate whether a summand needs to be included in a proportional (log) prob...
VectorView< double *, is_vector< T2 >::value, is_constant_struct< T2 >::value > d_x2
fvar< T > abs(const fvar< T > &x)
return_type< T_y, T_loc, T_scale >::type double_exponential_cdf(const T_y &y, const T_loc &mu, const T_scale &sigma)
Calculates the double exponential cumulative density function.
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)
return_type< T_y, T_loc, T_scale >::type double_exponential_cdf_log(const T_y &y, const T_loc &mu, const T_scale &sigma)
double double_exponential_rng(const double mu, const double sigma, RNG &rng)
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
fvar< T > log(const fvar< T > &x)
VectorView is a template metaprogram that takes its argument and allows it to be used like a vector...
fvar< T > exp(const fvar< T > &x)