1 #ifndef __STAN__AGRAD__AGRAD__H__
2 #define __STAN__AGRAD__AGRAD__H__
19 struct var_allocator {
22 inline void* alloc(
size_t nbytes) {
25 inline void recover() {
33 #ifdef AGRAD_THREAD_SAFE
36 var_allocator* allocator_;
84 allocator_->var_stack_.push_back(
this);
104 static inline void*
operator new(
size_t nbytes) {
106 allocator_ =
new var_allocator();
107 return allocator_->alloc(nbytes);
114 return allocator_->recover();
137 std::vector<vari*>::iterator it = allocator_->var_stack_.end();
138 std::vector<vari*>::iterator begin = allocator_->var_stack_.begin();
140 for (; (it >= begin) && (*it != vi); --it)
144 for (; it >= begin; --it)
152 class op_v_vari :
public vari {
156 op_v_vari(
double f, vari* avi) :
162 class op_vv_vari :
public vari {
167 op_vv_vari(
double f, vari* avi, vari* bvi):
174 class op_vd_vari :
public vari {
179 op_vd_vari(
double f, vari* avi,
double b) :
186 class op_dv_vari :
public vari {
191 op_dv_vari(
double f,
double a, vari* bvi) :
198 class op_vvv_vari :
public vari {
204 op_vvv_vari(
double f, vari* avi, vari* bvi, vari* cvi) :
212 class op_vvd_vari :
public vari {
218 op_vvd_vari(
double f, vari* avi, vari* bvi,
double c) :
226 class op_vdv_vari :
public vari {
232 op_vdv_vari(
double f, vari* avi,
double b, vari* cvi) :
240 class op_vdd_vari :
public vari {
246 op_vdd_vari(
double f, vari* avi,
double b,
double c) :
254 class op_dvv_vari :
public vari {
260 op_dvv_vari(
double f,
double a, vari* bvi, vari* cvi) :
268 class op_dvd_vari :
public vari {
274 op_dvd_vari(
double f,
double a, vari* bvi,
double c) :
282 class op_ddv_vari :
public vari {
288 op_ddv_vari(
double f,
double a,
double b, vari* cvi) :
296 class neg_vari :
public op_v_vari {
298 neg_vari(vari* avi) :
299 op_v_vari(-(avi->val_), avi) {
307 class add_vv_vari :
public op_vv_vari {
309 add_vv_vari(vari* avi, vari* bvi) :
310 op_vv_vari(avi->val_ + bvi->val_, avi, bvi) {
318 class add_vd_vari :
public op_vd_vari {
320 add_vd_vari(vari* avi,
double b) :
321 op_vd_vari(avi->val_ + b, avi, b) {
328 class increment_vari :
public op_v_vari {
330 increment_vari(vari* avi) :
331 op_v_vari(avi->val_ + 1.0, avi) {
338 class decrement_vari :
public op_v_vari {
340 decrement_vari(vari* avi) :
341 op_v_vari(avi->val_ - 1.0, avi) {
348 class subtract_vv_vari :
public op_vv_vari {
350 subtract_vv_vari(vari* avi, vari* bvi) :
351 op_vv_vari(avi->val_ - bvi->val_, avi, bvi) {
359 class subtract_vd_vari :
public op_vd_vari {
361 subtract_vd_vari(vari* avi,
double b) :
362 op_vd_vari(avi->val_ - b, avi, b) {
369 class subtract_dv_vari :
public op_dv_vari {
371 subtract_dv_vari(
double a, vari* bvi) :
372 op_dv_vari(a - bvi->val_, a, bvi) {
379 class multiply_vv_vari :
public op_vv_vari {
381 multiply_vv_vari(vari* avi, vari* bvi) :
382 op_vv_vari(avi->val_ * bvi->val_, avi, bvi) {
390 class multiply_vd_vari :
public op_vd_vari {
392 multiply_vd_vari(vari* avi,
double b) :
393 op_vd_vari(avi->val_ * b, avi, b) {
401 class divide_vv_vari :
public op_vv_vari {
403 divide_vv_vari(vari* avi, vari* bvi) :
404 op_vv_vari(avi->val_ / bvi->val_, avi, bvi) {
412 class divide_vd_vari :
public op_vd_vari {
414 divide_vd_vari(vari* avi,
double b) :
415 op_vd_vari(avi->val_ / b, avi, b) {
422 class divide_dv_vari :
public op_dv_vari {
424 divide_dv_vari(
double a, vari* bvi) :
425 op_dv_vari(a / bvi->val_, a, bvi) {
432 class exp_vari :
public op_v_vari {
434 exp_vari(vari* avi) :
435 op_v_vari(std::
exp(avi->val_),avi) {
438 avi_->adj_ += adj_ * val_;
442 class log_vari :
public op_v_vari {
444 log_vari(vari* avi) :
445 op_v_vari(std::
log(avi->val_),avi) {
454 class log10_vari :
public op_v_vari {
457 log10_vari(vari* avi) :
458 op_v_vari(std::
log10(avi->val_),avi),
466 class sqrt_vari :
public op_v_vari {
468 sqrt_vari(vari* avi) :
469 op_v_vari(std::
sqrt(avi->val_),avi) {
472 avi_->adj_ += adj_ / (2.0 * val_);
476 class pow_vv_vari :
public op_vv_vari {
478 pow_vv_vari(vari* avi, vari* bvi) :
479 op_vv_vari(std::
pow(avi->val_,bvi->val_),avi,bvi) {
482 if (
avi_->val_ == 0.0)
return;
488 class pow_vd_vari :
public op_vd_vari {
490 pow_vd_vari(vari* avi,
double b) :
491 op_vd_vari(std::
pow(avi->val_,b),avi,b) {
494 if (
avi_->val_ == 0.0)
return;
499 class pow_dv_vari :
public op_dv_vari {
501 pow_dv_vari(
double a, vari* bvi) :
502 op_dv_vari(std::
pow(a,bvi->val_),a,bvi) {
505 if (
ad_ == 0.0)
return;
510 class cos_vari :
public op_v_vari {
512 cos_vari(vari* avi) :
513 op_v_vari(std::
cos(avi->val_),avi) {
520 class sin_vari :
public op_v_vari {
522 sin_vari(vari* avi) :
523 op_v_vari(std::
sin(avi->val_),avi) {
530 class tan_vari :
public op_v_vari {
532 tan_vari(vari* avi) :
533 op_v_vari(std::
tan(avi->val_),avi) {
536 avi_->adj_ += adj_ * (1.0 + val_ * val_);
540 class acos_vari :
public op_v_vari {
542 acos_vari(vari* avi) :
543 op_v_vari(std::
acos(avi->val_),avi) {
550 class asin_vari :
public op_v_vari {
552 asin_vari(vari* avi) :
553 op_v_vari(std::
asin(avi->val_),avi) {
560 class atan_vari :
public op_v_vari {
562 atan_vari(vari* avi) :
563 op_v_vari(std::
atan(avi->val_),avi) {
570 class atan2_vv_vari :
public op_vv_vari {
572 atan2_vv_vari(vari* avi, vari* bvi) :
573 op_vv_vari(std::
atan2(avi->val_,bvi->val_),avi,bvi) {
576 double a_sq_plus_b_sq = (
avi_->val_ *
avi_->val_) + (
bvi_->val_ *
bvi_->val_);
577 avi_->adj_ +=
bvi_->val_ / a_sq_plus_b_sq;
578 bvi_->adj_ -=
avi_->val_ / a_sq_plus_b_sq;
582 class atan2_vd_vari :
public op_vd_vari {
584 atan2_vd_vari(vari* avi,
double b) :
585 op_vd_vari(std::
atan2(avi->val_,b),avi,b) {
589 avi_->adj_ += bd_ / a_sq_plus_b_sq;
593 class atan2_dv_vari :
public op_dv_vari {
595 atan2_dv_vari(
double a, vari* bvi) :
596 op_dv_vari(std::
atan2(a,bvi->val_),a,bvi) {
600 bvi_->adj_ -=
ad_ / a_sq_plus_b_sq;
604 class cosh_vari :
public op_v_vari {
606 cosh_vari(vari* avi) :
607 op_v_vari(std::
cosh(avi->val_),avi) {
614 class sinh_vari :
public op_v_vari {
616 sinh_vari(vari* avi) :
617 op_v_vari(std::
sinh(avi->val_),avi) {
624 class tanh_vari :
public op_v_vari {
626 tanh_vari(vari* avi) :
627 op_v_vari(std::
tanh(avi->val_),avi) {
636 class floor_vari :
public vari {
638 floor_vari(vari* avi) :
639 vari(std::
floor(avi->val_)) {
643 class ceil_vari :
public vari {
645 ceil_vari(vari* avi) :
646 vari(std::
ceil(avi->val_)) {
650 class fmod_vv_vari :
public op_vv_vari {
652 fmod_vv_vari(vari* avi, vari* bvi) :
653 op_vv_vari(std::
fmod(avi->val_,bvi->val_),avi,bvi) {
657 bvi_->adj_ -= adj_ *
static_cast<int>(
avi_->val_ /
bvi_->val_);
661 class fmod_vd_vari :
public op_v_vari {
663 fmod_vd_vari(vari* avi,
double b) :
664 op_v_vari(std::
fmod(avi->val_,b),avi) {
671 class fmod_dv_vari :
public op_dv_vari {
673 fmod_dv_vari(
double a, vari* bvi) :
674 op_dv_vari(std::
fmod(a,bvi->val_),a,bvi) {
677 int d =
static_cast<int>(
ad_ /
bvi_->val_);
678 bvi_->adj_ -= adj_ * d;
740 vi_(new
vari(static_cast<double>(b))) {
750 vi_(new
vari(static_cast<double>(c))) {
760 vi_(new
vari(static_cast<double>(n))) {
770 vi_(new
vari(static_cast<double>(n))) {
780 vi_(new
vari(static_cast<double>(n))) {
790 vi_(new
vari(static_cast<double>(n))) {
800 vi_(new
vari(static_cast<double>(n))) {
809 var(
unsigned long int n) :
810 vi_(new
vari(static_cast<double>(n))) {
820 vi_(new
vari(static_cast<double>(x))) {
839 vi_(new
vari(static_cast<double>(x))) {
847 inline double val()
const {
864 std::vector<double>& g) {
867 for (
size_t i = 0U; i < x.size(); ++i)
868 g.push_back(x[i].vi_->adj_);
906 vi_ =
new add_vv_vari(
vi_,b.vi_);
921 vi_ =
new add_vd_vari(
vi_,b);
937 vi_ =
new subtract_vv_vari(
vi_,b.vi_);
953 vi_ =
new subtract_vd_vari(
vi_,b);
969 vi_ =
new multiply_vv_vari(
vi_,b.vi_);
985 vi_ =
new multiply_vd_vari(
vi_,b);
1000 vi_ =
new divide_vv_vari(
vi_,b.vi_);
1016 vi_ =
new divide_vd_vari(
vi_,b);
1033 inline bool operator==(
const var& a,
const var& b) {
1034 return a.val() == b.val();
1047 return a.val() == b;
1059 return a == b.val();
1070 inline bool operator!=(
const var& a,
const var& b) {
1071 return a.val() != b.val();
1084 return a.val() != b;
1097 return a != b.val();
1107 inline bool operator<(
const var& a,
const var& b) {
1108 return a.val() < b.val();
1142 inline bool operator>(
const var& a,
const var& b) {
1143 return a.val() > b.val();
1179 inline bool operator<=(
const var& a,
const var& b) {
1180 return a.val() <= b.val();
1193 return a.val() <= b;
1206 return a <= b.val();
1218 inline bool operator>=(
const var& a,
const var& b) {
1219 return a.val() >= b.val();
1232 return a.val() >= b;
1245 return a >= b.val();
1297 return var(
new neg_vari(a.vi_));
1313 inline var
operator+(
const var& a,
const var& b) {
1314 return var(
new add_vv_vari(a.vi_,b.vi_));
1330 return var(
new add_vd_vari(a.vi_,b));
1345 return var(
new add_vd_vari(b.vi_,a));
1362 inline var
operator-(
const var& a,
const var& b) {
1363 return var(
new subtract_vv_vari(a.vi_,b.vi_));
1378 return var(
new subtract_vd_vari(a.vi_,b));
1393 return var(
new subtract_dv_vari(a,b.vi_));
1409 inline var
operator*(
const var& a,
const var& b) {
1410 return var(
new multiply_vv_vari(a.vi_,b.vi_));
1425 return var(
new multiply_vd_vari(a.vi_,b));
1440 return var(
new multiply_vd_vari(b.vi_,a));
1457 inline var
operator/(
const var& a,
const var& b) {
1458 return var(
new divide_vv_vari(a.vi_,b.vi_));
1473 return var(
new divide_vd_vari(a.vi_,b));
1488 return var(
new divide_dv_vari(a,b.vi_));
1501 a.vi_ =
new increment_vari(a.vi_);
1520 a.vi_ =
new increment_vari(a.vi_);
1538 a.vi_ =
new decrement_vari(a.vi_);
1557 a.vi_ =
new decrement_vari(a.vi_);
1569 inline var
exp(
const var& a) {
1570 return var(
new exp_vari(a.vi_));
1583 inline var
log(
const var& a) {
1584 return var(
new log_vari(a.vi_));
1597 inline var
log10(
const var& a) {
1598 return var(
new log10_vari(a.vi_));
1614 inline var
sqrt(
const var& a) {
1615 return var(
new sqrt_vari(a.vi_));
1631 inline var
pow(
const var& base,
const var& exponent) {
1632 return var(
new pow_vv_vari(base.vi_,exponent.vi_));
1648 return var(
new pow_vd_vari(base.vi_,exponent));
1664 return var(
new pow_dv_vari(base,exponent.vi_));
1680 inline var
cos(
const var& a) {
1681 return var(
new cos_vari(a.vi_));
1694 inline var
sin(
const var& a) {
1695 return var(
new sin_vari(a.vi_));
1708 inline var
tan(
const var& a) {
1709 return var(
new tan_vari(a.vi_));
1723 inline var
acos(
const var& a) {
1724 return var(
new acos_vari(a.vi_));
1738 inline var
asin(
const var& a) {
1739 return var(
new asin_vari(a.vi_));
1753 inline var
atan(
const var& a) {
1754 return var(
new atan_vari(a.vi_));
1772 inline var
atan2(
const var& a,
const var& b) {
1773 return var(
new atan2_vv_vari(a.vi_,b.vi_));
1789 return var(
new atan2_vd_vari(a.vi_,b));
1805 return var(
new atan2_dv_vari(a,b.vi_));
1820 inline var
cosh(
const var& a) {
1821 return var(
new cosh_vari(a.vi_));
1834 inline var
sinh(
const var& a) {
1835 return var(
new sinh_vari(a.vi_));
1848 inline var
tanh(
const var& a) {
1849 return var(
new tanh_vari(a.vi_));
1871 inline var
fabs(
const var& a) {
1876 return var(
new neg_vari(a.vi_));
1877 return var(
new vari(0.0));
1898 inline var
floor(
const var& a) {
1899 return var(
new floor_vari(a.vi_));
1920 inline var
ceil(
const var& a) {
1921 return var(
new ceil_vari(a.vi_));
1941 inline var
fmod(
const var& a,
const var& b) {
1942 return var(
new fmod_vv_vari(a.vi_,b.vi_));
1959 return var(
new fmod_vd_vari(a.vi_,b));
1976 return var(
new fmod_dv_vari(a,b.vi_));
1996 inline var
abs(
const var& a) {
2001 return var(
new neg_vari(a.vi_));
2002 return var(
new vari(0.0));