1 #ifndef __STAN__AGRAD__AGRAD_SPECIAL_FUNCTIONS__H__
2 #define __STAN__AGRAD__AGRAD_SPECIAL_FUNCTIONS__H__
5 #include <boost/math/special_functions.hpp>
17 class lgamma_vari :
public op_v_vari {
19 lgamma_vari(
double value, vari* avi) :
20 op_v_vari(value, avi) {
23 avi_->adj_ += adj_ * boost::math::digamma(
avi_->val_);
27 class tgamma_vari :
public op_v_vari {
29 tgamma_vari(vari* avi) :
30 op_v_vari(boost::math::
tgamma(avi->val_), avi) {
33 avi_->adj_ += adj_ * val_ * boost::math::digamma(
avi_->val_);
37 class log1p_vari :
public op_v_vari {
39 log1p_vari(vari* avi) :
40 op_v_vari(stan::math::
log1p(avi->val_),avi) {
43 avi_->adj_ += adj_ / (1 +
avi_->val_);
47 class log1m_vari :
public op_v_vari {
49 log1m_vari(vari* avi) :
50 op_v_vari(stan::math::
log1p(-avi->val_),avi) {
53 avi_->adj_ += adj_ / (
avi_->val_ - 1);
57 class binary_log_loss_1_vari :
public op_v_vari {
59 binary_log_loss_1_vari(vari* avi) :
60 op_v_vari(-std::
log(avi->val_),avi) {
67 class binary_log_loss_0_vari :
public op_v_vari {
69 binary_log_loss_0_vari(vari* avi) :
70 op_v_vari(-stan::math::
log1p(-avi->val_),avi) {
73 avi_->adj_ += adj_ / (1.0 -
avi_->val_);
77 class fdim_vv_vari :
public op_vv_vari {
79 fdim_vv_vari(vari* avi, vari* bvi) :
80 op_vv_vari(avi->val_ - bvi->val_, avi, bvi) {
88 class fdim_vd_vari :
public op_v_vari {
90 fdim_vd_vari(vari* avi,
double b) :
91 op_v_vari(avi->val_ - b, avi) {
98 class fdim_dv_vari :
public op_v_vari {
100 fdim_dv_vari(
double a, vari* bvi) :
101 op_v_vari(a - bvi->val_, bvi) {
109 class fma_vvv_vari :
public op_vvv_vari {
111 fma_vvv_vari(vari* avi, vari* bvi, vari* cvi) :
112 op_vvv_vari(avi->val_ * bvi->val_ + cvi->val_,
122 class fma_vvd_vari :
public op_vv_vari {
124 fma_vvd_vari(vari* avi, vari* bvi,
double c) :
125 op_vv_vari(avi->val_ * bvi->val_ + c,
134 class fma_vdv_vari :
public op_vdv_vari {
136 fma_vdv_vari(vari* avi,
double b, vari* cvi) :
137 op_vdv_vari(avi->val_ * b + cvi->val_,
146 class fma_vdd_vari :
public op_vd_vari {
148 fma_vdd_vari(vari* avi,
double b,
double c) :
149 op_vd_vari(avi->val_ * b + c,
157 class fma_ddv_vari :
public op_v_vari {
159 fma_ddv_vari(
double a,
double b, vari* cvi) :
160 op_v_vari(a * b + cvi->val_,
169 class inv_logit_vari :
public op_v_vari {
171 inv_logit_vari(vari* avi) :
172 op_v_vari(math::
inv_logit(avi->val_),avi) {
175 avi_->adj_ += adj_ * val_ * (1.0 - val_);
179 class acosh_vari :
public op_v_vari {
181 acosh_vari(vari* avi) :
182 op_v_vari(boost::math::
acosh(avi->val_),avi) {
189 class asinh_vari :
public op_v_vari {
191 asinh_vari(vari* avi) :
192 op_v_vari(boost::math::
asinh(avi->val_),avi) {
199 class atanh_vari :
public op_v_vari {
201 atanh_vari(vari* avi) :
202 op_v_vari(boost::math::
atanh(avi->val_),avi) {
209 const double TWO_OVER_SQRT_PI = 2.0 /
std::sqrt(boost::math::constants::pi<double>());
211 class erf_vari :
public op_v_vari {
213 erf_vari(vari* avi) :
214 op_v_vari(boost::math::
erf(avi->val_),avi) {
221 const double NEG_TWO_OVER_SQRT_PI = - TWO_OVER_SQRT_PI;
223 class erfc_vari :
public op_v_vari {
225 erfc_vari(vari* avi) :
226 op_v_vari(boost::math::
erfc(avi->val_),avi) {
235 class exp2_vari :
public op_v_vari {
237 exp2_vari(vari* avi) :
238 op_v_vari(std::
pow(2.0,avi->val_),avi) {
245 class expm1_vari :
public op_v_vari {
247 expm1_vari(vari* avi) :
248 op_v_vari(std::
exp(avi->val_) - 1.0,avi) {
251 avi_->adj_ += adj_ * val_;
255 class hypot_vv_vari :
public op_vv_vari {
257 hypot_vv_vari(vari* avi, vari* bvi) :
258 op_vv_vari(boost::math::
hypot(avi->val_,bvi->val_),
262 avi_->adj_ += adj_ *
avi_->val_ / val_;
263 bvi_->adj_ += adj_ *
bvi_->val_ / val_;
267 class hypot_vd_vari :
public op_v_vari {
269 hypot_vd_vari(vari* avi,
double b) :
270 op_v_vari(boost::math::
hypot(avi->val_,b),
274 avi_->adj_ += adj_ *
avi_->val_ / val_;
280 class log2_vari :
public op_v_vari {
282 log2_vari(vari* avi) :
283 op_v_vari(stan::math::
log2(avi->val_),avi) {
286 avi_->adj_ += adj_ / (LOG2 *
avi_->val_);
290 class cbrt_vari :
public op_v_vari {
292 cbrt_vari(vari* avi) :
293 op_v_vari(boost::math::
cbrt(avi->val_),avi) {
296 avi_->adj_ += adj_ / (3.0 * val_ * val_);
301 class round_vari :
public vari {
303 round_vari(vari* avi) :
304 vari(boost::math::
round(avi->val_)) {
309 class trunc_vari :
public vari {
311 trunc_vari(vari* avi) :
312 vari(boost::math::
trunc(avi->val_)) {
316 class inv_cloglog_vari :
public op_v_vari {
318 inv_cloglog_vari(vari* avi) :
319 op_v_vari(stan::math::
inv_cloglog(avi->val_), avi) {
326 class Phi_vari :
public op_v_vari {
328 Phi_vari(vari* avi) :
329 op_v_vari(stan::math::
Phi(avi->val_), avi) {
332 static const double NEG_HALF = -0.5;
333 static const double INV_SQRT_TWO_PI
334 = 1.0 /
std::sqrt(2.0 * boost::math::constants::pi<double>());
339 inline double calculate_chain(
const double& x,
const double& val) {
343 double log_sum_exp_as_double(
const std::vector<var>& x) {
344 using std::numeric_limits;
347 double max = -numeric_limits<double>::infinity();
348 for (
size_t i = 0; i < x.size(); ++i)
352 for (
size_t i = 0; i < x.size(); ++i)
353 if (x[i] != -numeric_limits<double>::infinity())
354 sum +=
exp(x[i].val() -
max);
355 return max +
log(sum);
358 class log1p_exp_v_vari :
public op_v_vari {
360 log1p_exp_v_vari(vari* avi) :
361 op_v_vari(stan::math::
log1p_exp(avi->val_),
365 avi_->adj_ += adj_ * calculate_chain(
avi_->val_, val_);
368 class log_sum_exp_vv_vari :
public op_vv_vari {
370 log_sum_exp_vv_vari(vari* avi, vari* bvi) :
371 op_vv_vari(stan::math::
log_sum_exp(avi->val_, bvi->val_),
375 avi_->adj_ += adj_ * calculate_chain(
avi_->val_, val_);
376 bvi_->adj_ += adj_ * calculate_chain(
bvi_->val_, val_);
379 class log_sum_exp_vd_vari :
public op_vd_vari {
381 log_sum_exp_vd_vari(vari* avi,
double b) :
386 avi_->adj_ += adj_ * calculate_chain(
avi_->val_, val_);
389 class log_sum_exp_dv_vari :
public op_dv_vari {
391 log_sum_exp_dv_vari(
double a, vari* bvi) :
396 bvi_->adj_ += adj_ * calculate_chain(
bvi_->val_, val_);
399 class log_sum_exp_vector_vari :
public op_vector_vari {
401 log_sum_exp_vector_vari(
const std::vector<var>& x) :
402 op_vector_vari(log_sum_exp_as_double(x), x) {
405 for (
size_t i = 0; i <
size_; ++i) {
406 vis_[i]->adj_ += adj_ * calculate_chain(
vis_[i]->val_, val_);
411 class square_vari :
public op_v_vari {
413 square_vari(vari* avi) :
414 op_v_vari(avi->val_ * avi->val_,avi) {
417 avi_->adj_ += adj_ * 2.0 *
avi_->val_;
421 class multiply_log_vv_vari :
public op_vv_vari {
423 multiply_log_vv_vari(vari* avi, vari* bvi) :
424 op_vv_vari(stan::math::
multiply_log(avi->val_,bvi->val_),avi,bvi) {
429 if (
bvi_->val_ == 0.0 &&
avi_->val_ == 0)
430 bvi_->adj_ += adj_ * std::numeric_limits<double>::infinity();
435 class multiply_log_vd_vari :
public op_vd_vari {
437 multiply_log_vd_vari(vari* avi,
double b) :
438 op_vd_vari(stan::math::
multiply_log(avi->val_,b),avi,b) {
445 class multiply_log_dv_vari :
public op_dv_vari {
447 multiply_log_dv_vari(
double a, vari* bvi) :
448 op_dv_vari(stan::math::
multiply_log(a,bvi->val_),a,bvi) {
451 if (
bvi_->val_ == 0.0 &&
ad_ == 0.0)
452 bvi_->adj_ += adj_ * std::numeric_limits<double>::infinity();
463 double ibeta_hypergeometric_helper(
double a,
double b,
double z,
double precision=1
e-8,
double max_steps=1000) {
477 class ibeta_vvv_vari :
public op_vvv_vari {
479 ibeta_vvv_vari(vari* avi, vari* bvi, vari* xvi) :
480 op_vvv_vari(stan::math::
ibeta(avi->val_,bvi->val_,xvi->val_),avi,bvi,xvi) {
483 double a =
avi_->val_;
484 double b =
bvi_->val_;
485 double c =
cvi_->val_;
492 using boost::math::digamma;
494 using stan::agrad::ibeta_hypergeometric_helper;
496 (
log(c) - digamma(a) + digamma(a+b)) * val_ -
500 +
ibeta(b, a, 1-c) * (digamma(b) - digamma(a+b) -
log(1-c)));
502 boost::math::ibeta_derivative(a,b,c);
505 class ibeta_vvd_vari :
public op_vvd_vari {
507 ibeta_vvd_vari(vari* avi, vari* bvi,
double x) :
508 op_vvd_vari(stan::math::
ibeta(avi->val_,bvi->val_,x),avi,bvi,x) {
511 double a =
avi_->val_;
512 double b =
bvi_->val_;
520 using boost::math::digamma;
522 using stan::agrad::ibeta_hypergeometric_helper;
524 (
log(c) - digamma(a) + digamma(a+b)) * val_ -
528 +
ibeta(b, a, 1-c) * (digamma(b) - digamma(a+b) -
log(1-c)));
531 class ibeta_vdv_vari :
public op_vdv_vari {
533 ibeta_vdv_vari(vari* avi,
double b, vari* xvi) :
534 op_vdv_vari(stan::math::
ibeta(avi->val_,b,xvi->val_),avi,b,xvi) {
537 double a =
avi_->val_;
539 double c =
cvi_->val_;
546 using boost::math::digamma;
548 using stan::agrad::ibeta_hypergeometric_helper;
550 (
log(c) - digamma(a) + digamma(a+b)) * val_ -
553 boost::math::ibeta_derivative(a,b,c);
556 class ibeta_vdd_vari :
public op_vdd_vari {
558 ibeta_vdd_vari(vari* avi,
double b,
double x) :
559 op_vdd_vari(stan::math::
ibeta(avi->val_,b,x),avi,b,x) {
562 double a =
avi_->val_;
571 using boost::math::digamma;
573 using stan::agrad::ibeta_hypergeometric_helper;
575 (
log(c) - digamma(a) + digamma(a+b)) * val_ -
579 class ibeta_dvv_vari :
public op_dvv_vari {
581 ibeta_dvv_vari(
double a, vari* bvi, vari* xvi) :
582 op_dvv_vari(stan::math::
ibeta(a,bvi->val_,xvi->val_),a,bvi,xvi) {
586 double b =
bvi_->val_;
587 double c =
cvi_->val_;
594 using boost::math::digamma;
596 using stan::agrad::ibeta_hypergeometric_helper;
599 +
ibeta(b, a, 1-c) * (digamma(b) - digamma(a+b) -
log(1-c)));
601 boost::math::ibeta_derivative(a,b,c);
604 class ibeta_dvd_vari :
public op_dvd_vari {
606 ibeta_dvd_vari(
double a, vari* bvi,
double x) :
607 op_dvd_vari(stan::math::
ibeta(a,bvi->val_,x),a,bvi,x) {
611 double b =
bvi_->val_;
619 using boost::math::digamma;
621 using stan::agrad::ibeta_hypergeometric_helper;
624 +
ibeta(b, a, 1-c) * (digamma(b) - digamma(a+b) -
log(1-c)));
627 class ibeta_ddv_vari :
public op_ddv_vari {
629 ibeta_ddv_vari(
double a,
double b, vari* xvi) :
630 op_ddv_vari(stan::math::
ibeta(a,b,xvi->val_),a,b,xvi) {
635 double c =
cvi_->val_;
638 boost::math::ibeta_derivative(a,b,c);
660 return var(
new acosh_vari(a.
vi_));
676 return var(
new asinh_vari(a.
vi_));
692 return var(
new atanh_vari(a.
vi_));
708 return var(
new erf_vari(a.
vi_));
724 return var(
new erfc_vari(a.
vi_));
740 return var(
new exp2_vari(a.
vi_));
756 return var(
new expm1_vari(a.
vi_));
771 return var(
new lgamma_vari(lgamma_a, a.
vi_));
785 return var(
new log1p_vari(a.
vi_));
799 return var(
new log1m_vari(a.
vi_));
849 return var(
new fma_vvd_vari(a.
vi_,b.
vi_,c));
873 return var(
new fma_vdv_vari(a.
vi_,b,c.
vi_));
895 return var(
new fma_vdd_vari(a.
vi_,b,c));
917 return var(
new fma_vdd_vari(b.
vi_,a,c));
939 return var(
new fma_ddv_vari(a,b,c.
vi_));
963 return var(
new fma_vdv_vari(b.
vi_,a,c.
vi_));
1107 return var(
new hypot_vv_vari(a.
vi_,b.
vi_));
1126 return var(
new hypot_vd_vari(a.
vi_,b));
1145 return var(
new hypot_vd_vari(b.
vi_,a));
1161 return var(
new log2_vari(a.
vi_));
1177 return var(
new cbrt_vari(a.
vi_));
1195 return var(
new round_vari(a.
vi_));
1212 return var(
new trunc_vari(a.
vi_));
1242 return var(
new fdim_vv_vari(a.
vi_,b.
vi_));
1267 ?
var(
new fdim_dv_vari(a,b.
vi_))
1290 ?
var(
new fdim_vd_vari(a.
vi_,b))
1291 : var(
new vari(0.0));
1311 return var(
new tgamma_vari(a.
vi_));
1349 return var(
new inv_cloglog_vari(a.
vi_));
1365 return var(
new Phi_vari(a.
vi_));
1381 return var(
new inv_logit_vari(a.
vi_));
1402 ?
var(
new binary_log_loss_0_vari(y_hat.
vi_))
1403 :
var(
new binary_log_loss_1_vari(y_hat.
vi_));
1411 return var(
new log1p_exp_v_vari(a.
vi_));
1419 return var(
new log_sum_exp_vv_vari(a.
vi_, b.
vi_));
1426 return var(
new log_sum_exp_vd_vari(a.
vi_, b));
1433 return var(
new log_sum_exp_dv_vari(a, b.
vi_));
1439 return var(
new log_sum_exp_vector_vari(x));
1452 return var(
new square_vari(x.
vi_));
1469 return var(
new multiply_log_vv_vari(a.
vi_,b.
vi_));
1482 return var(
new multiply_log_vd_vari(a.
vi_,b));
1498 return var(
new multiply_log_dv_vari(a,b.
vi_));
1511 return c ? y_true : y_false;
1541 return var(y_false);