1 #ifndef STAN__PROB__DISTRIBUTIONS__UNIVARIATE__CONTINUOUS__EXP__MOD__NORMAL__HPP
2 #define STAN__PROB__DISTRIBUTIONS__UNIVARIATE__CONTINUOUS__EXP__MOD__NORMAL__HPP
4 #include <boost/random/normal_distribution.hpp>
5 #include <boost/math/special_functions/fpclassify.hpp>
6 #include <boost/random/variate_generator.hpp>
22 template <
bool propto,
23 typename T_y,
typename T_loc,
typename T_scale,
25 typename return_type<T_y,T_loc,T_scale, T_inv_scale>::type
27 const T_inv_scale& lambda) {
28 static const char*
function =
"stan::prob::exp_mod_normal_log(%1%)";
55 "Random variable",
"Location parameter",
56 "Scale parameter",
"Inv_scale paramter",
65 operands_and_partials(y, mu, sigma,lambda);
71 size_t N =
max_size(y, mu, sigma, lambda);
73 for (
size_t n = 0; n < N; n++) {
75 const double y_dbl =
value_of(y_vec[n]);
76 const double mu_dbl =
value_of(mu_vec[n]);
77 const double sigma_dbl =
value_of(sigma_vec[n]);
78 const double lambda_dbl =
value_of(lambda_vec[n]);
80 const double pi_dbl = boost::math::constants::pi<double>();
86 logp +=
log(lambda_dbl);
89 * (mu_dbl + 0.5 * lambda_dbl * sigma_dbl * sigma_dbl - y_dbl)
95 const double deriv_logerfc
97 *
exp(-(mu_dbl + lambda_dbl * sigma_dbl * sigma_dbl - y_dbl)
99 * (mu_dbl + lambda_dbl * sigma_dbl * sigma_dbl - y_dbl)
106 operands_and_partials.
d_x1[n]
108 + deriv_logerfc * -1.0 / (sigma_dbl *
std::sqrt(2.0));
110 operands_and_partials.
d_x2[n]
112 + deriv_logerfc / (sigma_dbl *
std::sqrt(2.0));
114 operands_and_partials.
d_x3[n]
115 += sigma_dbl * lambda_dbl * lambda_dbl
117 * (-mu_dbl / (sigma_dbl * sigma_dbl *
std::sqrt(2.0))
119 + y_dbl / (sigma_dbl * sigma_dbl *
std::sqrt(2.0)));
121 operands_and_partials.
d_x4[n]
122 += 1 / lambda_dbl + lambda_dbl * sigma_dbl * sigma_dbl
123 + mu_dbl - y_dbl + deriv_logerfc * sigma_dbl /
std::sqrt(2.0);
125 return operands_and_partials.
to_var(logp);
128 template <
typename T_y,
typename T_loc,
typename T_scale,
129 typename T_inv_scale>
133 const T_inv_scale& lambda) {
134 return exp_mod_normal_log<false>(y,mu,sigma,lambda);
137 template <
typename T_y,
typename T_loc,
typename T_scale,
138 typename T_inv_scale>
141 const T_inv_scale& lambda) {
142 static const char*
function =
"stan::prob::exp_mod_normal_cdf(%1%)";
163 check_not_nan(
function, lambda,
"Inv_scale parameter", &cdf);
166 "Random variable",
"Location parameter",
167 "Scale parameter",
"Inv_scale paramter",
171 operands_and_partials(y, mu, sigma,lambda);
179 size_t N =
max_size(y, mu, sigma, lambda);
181 for (
size_t n = 0; n < N; n++) {
185 return operands_and_partials.
to_var(0.0);
188 const double y_dbl =
value_of(y_vec[n]);
189 const double mu_dbl =
value_of(mu_vec[n]);
190 const double sigma_dbl =
value_of(sigma_vec[n]);
191 const double lambda_dbl =
value_of(lambda_vec[n]);
192 const double u = lambda_dbl * (y_dbl - mu_dbl);
193 const double v = lambda_dbl * sigma_dbl ;
194 const double v_sq = v * v;
195 const double scaled_diff = (y_dbl - mu_dbl) / (
SQRT_2 * sigma_dbl);
196 const double scaled_diff_sq = scaled_diff * scaled_diff;
197 const double erf_calc = 0.5 * (1 +
erf(-v /
SQRT_2 + scaled_diff));
198 const double deriv_1 = lambda_dbl *
exp(0.5 * v_sq - u) * erf_calc;
199 const double deriv_2 =
SQRT_2 / sqrt_pi * 0.5 *
exp(0.5 * v_sq
201 - (v /
SQRT_2)) * (scaled_diff
202 - (v /
SQRT_2)) - u) / sigma_dbl;
203 const double deriv_3 =
SQRT_2 / sqrt_pi * 0.5 *
exp(-scaled_diff_sq)
206 const double cdf_ = 0.5 * (1 +
erf(u / (v *
SQRT_2)))
207 -
exp(-u + v_sq * 0.5) * (erf_calc);
212 operands_and_partials.
d_x1[n] += (deriv_1 - deriv_2 + deriv_3)
215 operands_and_partials.
d_x2[n] += (-deriv_1 + deriv_2 - deriv_3)
218 operands_and_partials.
d_x3[n] += (-deriv_1 * v - deriv_3
219 * scaled_diff * SQRT_2 - deriv_2 * sigma_dbl * SQRT_2 * (-SQRT_2
220 * 0.5 * (-lambda_dbl + scaled_diff * SQRT_2 / sigma_dbl) - SQRT_2
221 * lambda_dbl)) / cdf_;
223 operands_and_partials.
d_x4[n] +=
exp(0.5 * v_sq - u) * (SQRT_2
224 / sqrt_pi * 0.5 * sigma_dbl *
exp(-(v / SQRT_2 - scaled_diff) * (v
225 / SQRT_2 - scaled_diff)) - (v * sigma_dbl + mu_dbl - y_dbl)
231 operands_and_partials.
d_x1[n] *= cdf;
235 operands_and_partials.
d_x2[n] *= cdf;
239 operands_and_partials.
d_x3[n] *= cdf;
243 operands_and_partials.
d_x4[n] *= cdf;
246 return operands_and_partials.
to_var(cdf);
249 template <
typename T_y,
typename T_loc,
typename T_scale,
250 typename T_inv_scale>
253 const T_inv_scale& lambda) {
254 static const char*
function =
"stan::prob::exp_mod_normal_cdf_log(%1%)";
271 check_finite(
function, mu,
"Location parameter", &cdf_log);
275 check_not_nan(
function, lambda,
"Inv_scale parameter", &cdf_log);
278 "Random variable",
"Location parameter",
279 "Scale parameter",
"Inv_scale paramter",
283 operands_and_partials(y, mu, sigma,lambda);
292 size_t N =
max_size(y, mu, sigma, lambda);
294 for (
size_t n = 0; n < N; n++) {
300 return operands_and_partials.
to_var(0.0);
303 const double y_dbl =
value_of(y_vec[n]);
304 const double mu_dbl =
value_of(mu_vec[n]);
305 const double sigma_dbl =
value_of(sigma_vec[n]);
306 const double lambda_dbl =
value_of(lambda_vec[n]);
307 const double u = lambda_dbl * (y_dbl - mu_dbl);
308 const double v = lambda_dbl * sigma_dbl ;
309 const double v_sq = v * v;
310 const double scaled_diff = (y_dbl - mu_dbl) / (
SQRT_2 * sigma_dbl);
311 const double scaled_diff_sq = scaled_diff * scaled_diff;
312 const double erf_calc1 = 0.5 * (1 +
erf(u / (v *
SQRT_2)));
313 const double erf_calc2 = 0.5 * (1 +
erf(u / (v * SQRT_2) - v / SQRT_2));
314 const double deriv_1 = lambda_dbl *
exp(0.5 * v_sq - u) * erf_calc2;
315 const double deriv_2 = SQRT_2 / sqrt_pi * 0.5
316 *
exp(0.5 * v_sq - (-scaled_diff + (v / SQRT_2))
317 * (-scaled_diff + (v / SQRT_2)) - u) / sigma_dbl;
318 const double deriv_3 = SQRT_2 / sqrt_pi * 0.5 *
exp(-scaled_diff_sq)
321 const double denom = erf_calc1 - erf_calc2 *
exp(0.5 * v_sq - u);
322 const double cdf_ = erf_calc1 -
exp(-u + v_sq * 0.5) * (erf_calc2);
324 cdf_log +=
log(cdf_);
327 operands_and_partials.
d_x1[n] += (deriv_1 - deriv_2 + deriv_3)
330 operands_and_partials.
d_x2[n] += (-deriv_1 + deriv_2 - deriv_3)
333 operands_and_partials.
d_x3[n]
334 += (-deriv_1 * v - deriv_3 * scaled_diff
335 * SQRT_2 - deriv_2 * sigma_dbl * SQRT_2
336 * (-SQRT_2 * 0.5 * (-lambda_dbl + scaled_diff * SQRT_2
338 - SQRT_2 * lambda_dbl))
341 operands_and_partials.
d_x4[n]
342 +=
exp(0.5 * v_sq - u)
343 * (SQRT_2 / sqrt_pi * 0.5 * sigma_dbl
344 *
exp(-(v / SQRT_2 - scaled_diff)
345 * (v / SQRT_2 - scaled_diff))
346 - (v * sigma_dbl + mu_dbl - y_dbl) * erf_calc2)
350 return operands_and_partials.
to_var(cdf_log);
353 template <
typename T_y,
typename T_loc,
typename T_scale,
354 typename T_inv_scale>
357 const T_inv_scale& lambda) {
358 static const char*
function =
"stan::prob::exp_mod_normal_ccdf_log(%1%)";
366 double ccdf_log(0.0);
375 check_finite(
function, mu,
"Location parameter", &ccdf_log);
376 check_not_nan(
function, sigma,
"Scale parameter", &ccdf_log);
379 check_not_nan(
function, lambda,
"Inv_scale parameter", &ccdf_log);
382 "Random variable",
"Location parameter",
383 "Scale parameter",
"Inv_scale paramter",
387 operands_and_partials(y, mu, sigma,lambda);
396 size_t N =
max_size(y, mu, sigma, lambda);
398 for (
size_t n = 0; n < N; n++) {
404 return operands_and_partials.
to_var(0.0);
407 const double y_dbl =
value_of(y_vec[n]);
408 const double mu_dbl =
value_of(mu_vec[n]);
409 const double sigma_dbl =
value_of(sigma_vec[n]);
410 const double lambda_dbl =
value_of(lambda_vec[n]);
411 const double u = lambda_dbl * (y_dbl - mu_dbl);
412 const double v = lambda_dbl * sigma_dbl ;
413 const double v_sq = v * v;
414 const double scaled_diff = (y_dbl - mu_dbl) / (
SQRT_2 * sigma_dbl);
415 const double scaled_diff_sq = scaled_diff * scaled_diff;
416 const double erf_calc1 = 0.5 * (1 +
erf(u / (v *
SQRT_2)));
417 const double erf_calc2 = 0.5 * (1 +
erf(u / (v * SQRT_2) - v / SQRT_2));
419 const double deriv_1 = lambda_dbl *
exp(0.5 * v_sq - u) * erf_calc2;
420 const double deriv_2 = SQRT_2 / sqrt_pi * 0.5
422 - (-scaled_diff + (v / SQRT_2)) * (-scaled_diff
425 const double deriv_3 = SQRT_2 / sqrt_pi * 0.5 *
exp(-scaled_diff_sq) / sigma_dbl;
427 const double ccdf_ = 1.0 - erf_calc1 +
exp(-u + v_sq * 0.5) * (erf_calc2);
429 ccdf_log +=
log(ccdf_);
432 operands_and_partials.
d_x1[n]
433 -= (deriv_1 - deriv_2 + deriv_3) / ccdf_;
435 operands_and_partials.
d_x2[n]
436 -= (-deriv_1 + deriv_2 - deriv_3) / ccdf_;
438 operands_and_partials.
d_x3[n]
439 -= (-deriv_1 * v - deriv_3 * scaled_diff * SQRT_2 - deriv_2
441 * (-SQRT_2 * 0.5 * (-lambda_dbl + scaled_diff * SQRT_2
443 - SQRT_2 * lambda_dbl))
446 operands_and_partials.
d_x4[n] -=
exp(0.5 * v_sq - u)
447 * (SQRT_2 / sqrt_pi * 0.5 * sigma_dbl
448 *
exp(-(v / SQRT_2 - scaled_diff) * (v / SQRT_2 - scaled_diff))
449 - (v * sigma_dbl + mu_dbl - y_dbl) * erf_calc2)
453 return operands_and_partials.
to_var(ccdf_log);
463 static const char*
function =
"stan::prob::exp_mod_normal_rng(%1%)";
468 check_finite(
function, mu,
"Location parameter", (
double*)0);
return_type< T_y, T_loc, T_scale, T_inv_scale >::type exp_mod_normal_cdf(const T_y &y, const T_loc &mu, const T_scale &sigma, const T_inv_scale &lambda)
fvar< T > erf(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)
fvar< T > erfc(const fvar< T > &x)
bool check_finite(const char *function, const T_y &y, const char *name, T_result *result)
Checks if the variable y is finite.
double exponential_rng(const double beta, RNG &rng)
T value_of(const fvar< T > &v)
Return the value of the specified variable.
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.
bool isinf(const stan::agrad::var &v)
Checks if the given number is infinite.
Template metaprogram to calculate whether a summand needs to be included in a proportional (log) prob...
const double SQRT_2
The value of the square root of 2, .
return_type< T_y, T_loc, T_scale, T_inv_scale >::type exp_mod_normal_log(const T_y &y, const T_loc &mu, const T_scale &sigma, const T_inv_scale &lambda)
fvar< T > sqrt(const fvar< T > &x)
VectorView< double *, is_vector< T2 >::value, is_constant_struct< T2 >::value > d_x2
return_type< T_y, T_loc, T_scale, T_inv_scale >::type exp_mod_normal_ccdf_log(const T_y &y, const T_loc &mu, const T_scale &sigma, const T_inv_scale &lambda)
bool check_consistent_sizes(const char *function, const T1 &x1, const T2 &x2, const char *name1, const char *name2, T_result *result)
double normal_rng(const double mu, const double sigma, RNG &rng)
size_t max_size(const T1 &x1, const T2 &x2)
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< T4 >::value, is_constant_struct< T4 >::value > d_x4
VectorView< double *, is_vector< T1 >::value, is_constant_struct< T1 >::value > d_x1
return_type< T_y, T_loc, T_scale, T_inv_scale >::type exp_mod_normal_cdf_log(const T_y &y, const T_loc &mu, const T_scale &sigma, const T_inv_scale &lambda)
VectorView< double *, is_vector< T3 >::value, is_constant_struct< T3 >::value > d_x3
double pi()
Return the value of pi.
double exp_mod_normal_rng(const double mu, const double sigma, const double lambda, RNG &rng)
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)
double negative_infinity()
Return negative infinity.