Stan  1.1
probability, sampling & optimization
 All Classes Namespaces Files Functions Variables Typedefs Enumerator Friends Macros Pages
agrad.hpp
Go to the documentation of this file.
1 #ifndef __STAN__AGRAD__AGRAD_HPP__
2 #define __STAN__AGRAD__AGRAD_HPP__
3 
4 #include <cmath>
5 #include <cstddef>
6 #include <limits>
7 #include <stdexcept>
8 #include <vector>
9 #include <ostream>
10 #include <iostream>
11 
13 
14 namespace stan {
15 
16  namespace agrad {
17 
18  class chainable;
19  class vari;
20  class var;
21 
22  // FIXME: manage all this as a single singleton (thread local)
23  extern std::vector<chainable*> var_stack_;
24  extern std::vector<chainable*> var_nochain_stack_;
25  extern memory::stack_alloc memalloc_;
26 
27  static void recover_memory();
28 
29  static void grad(chainable* vi);
30 
35  class chainable {
36 
37  public:
38 
43  chainable() { }
44 
51  // handled automatically
52  }
53 
59  virtual void chain() {
60  }
61 
66  virtual void init_dependent() {
67  }
68 
73  virtual void set_zero_adjoint() {
74  }
75 
85  static inline void* operator new(size_t nbytes) {
86  return memalloc_.alloc(nbytes);
87  }
88 
89  };
90 
104  class vari : public chainable {
105  private:
106  friend class var;
107 
108  public:
109 
113  const double val_;
114 
119  double adj_;
120 
133  vari(const double x):
134  val_(x),
135  adj_(0.0) {
136  var_stack_.push_back(this);
137  }
138 
139  vari(const double x,bool stacked):
140  val_(x),
141  adj_(0.0) {
142  if (stacked)
143  var_stack_.push_back(this);
144  else
145  var_nochain_stack_.push_back(this);
146  }
147 
155  ~vari() {
156  throw std::logic_error("vari destruction handled automatically");
157  }
158 
164  virtual void init_dependent() {
165  adj_ = 1.0; // droot/droot = 1
166  }
167 
171  virtual void set_zero_adjoint() {
172  adj_ = 0.0;
173  }
174 
184  friend std::ostream& operator<<(std::ostream& os, const vari* v) {
185  return os << v << " " << v->val_ << " : " << v->adj_;
186  }
187 
188  };
189 
199  inline void print_stack(std::ostream& o) {
200  o << "STACK, size=" << var_stack_.size() << std::endl;
201  for (size_t i = 0; i < var_stack_.size(); ++i)
202  o << i
203  << " " << var_stack_[i]
204  << " " << (static_cast<vari*>(var_stack_[i]))->val_
205  << " : " << (static_cast<vari*>(var_stack_[i]))->adj_
206  << std::endl;
207  }
208 
209 
223  class var {
224  public:
225 
226  // FIXME: doc what this is for
227  typedef double Scalar;
228 
237 
248  return (vi_ == static_cast<vari*>(0U));
249  }
250 
256  explicit var(vari* vi)
257  : vi_(vi)
258  { }
259 
267  var()
268  : vi_(static_cast<vari*>(0U))
269  { }
270 
277  var(bool b) :
278  vi_(new vari(static_cast<double>(b))) {
279  }
280 
287  var(char c) :
288  vi_(new vari(static_cast<double>(c))) {
289  }
290 
297  var(short n) :
298  vi_(new vari(static_cast<double>(n))) {
299  }
300 
307  var(unsigned short n) :
308  vi_(new vari(static_cast<double>(n))) {
309  }
310 
317  var(int n) :
318  vi_(new vari(static_cast<double>(n))) {
319  }
320 
327  var(unsigned int n) :
328  vi_(new vari(static_cast<double>(n))) {
329  }
330 
337  var(long int n) :
338  vi_(new vari(static_cast<double>(n))) {
339  }
340 
347  var(unsigned long int n) :
348  vi_(new vari(static_cast<double>(n))) {
349  }
350 
357  var(unsigned long long n) :
358  vi_(new vari(static_cast<double>(n))) {
359  }
360 
367  var(long long n) :
368  vi_(new vari(static_cast<double>(n))) {
369  }
370 
377  var(float x) :
378  vi_(new vari(static_cast<double>(x))) {
379  }
380 
386  var(double x) :
387  vi_(new vari(x)) {
388  }
389 
396  var(long double x) :
397  vi_(new vari(static_cast<double>(x))) {
398  }
399 
405  inline double val() const {
406  return vi_->val_;
407  }
408 
417  inline double adj() const {
418  return vi_->adj_;
419  }
420 
433  void grad(std::vector<var>& x,
434  std::vector<double>& g) {
436  g.resize(x.size());
437  for (size_t i = 0; i < x.size(); ++i)
438  g[i] = x[i].vi_->adj_;
439  recover_memory();
440  }
441 
458  void grad() {
460  recover_memory();
461  }
462 
463  // POINTER OVERRIDES
464 
477  inline vari& operator*() {
478  return *vi_;
479  }
480 
491  inline vari* operator->() {
492  return vi_;
493  }
494 
495  // COMPOUND ASSIGNMENT OPERATORS
496 
507  inline var& operator+=(const var& b);
508 
519  inline var& operator+=(const double b);
520 
532  inline var& operator-=(const var& b);
533 
545  inline var& operator-=(const double b);
546 
558  inline var& operator*=(const var& b);
559 
571  inline var& operator*=(const double b);
572 
583  inline var& operator/=(const var& b);
584 
596  inline var& operator/=(const double b);
597 
606  friend std::ostream& operator<<(std::ostream& os, const var& v) {
607  return os << v.val() << ':' << v.adj();
608  }
609  };
610 
611  namespace {
612 
613  class op_v_vari : public vari {
614  protected:
615  vari* avi_;
616  public:
617  op_v_vari(double f, vari* avi) :
618  vari(f),
619  avi_(avi) {
620  }
621  };
622 
623  class op_vv_vari : public vari {
624  protected:
625  vari* avi_;
626  vari* bvi_;
627  public:
628  op_vv_vari(double f, vari* avi, vari* bvi):
629  vari(f),
630  avi_(avi),
631  bvi_(bvi) {
632  }
633  };
634 
635  class op_vd_vari : public vari {
636  protected:
637  vari* avi_;
638  double bd_;
639  public:
640  op_vd_vari(double f, vari* avi, double b) :
641  vari(f),
642  avi_(avi),
643  bd_(b) {
644  }
645  };
646 
647  class op_dv_vari : public vari {
648  protected:
649  double ad_;
650  vari* bvi_;
651  public:
652  op_dv_vari(double f, double a, vari* bvi) :
653  vari(f),
654  ad_(a),
655  bvi_(bvi) {
656  }
657  };
658 
659  class op_vvv_vari : public vari {
660  protected:
661  vari* avi_;
662  vari* bvi_;
663  vari* cvi_;
664  public:
665  op_vvv_vari(double f, vari* avi, vari* bvi, vari* cvi) :
666  vari(f),
667  avi_(avi),
668  bvi_(bvi),
669  cvi_(cvi) {
670  }
671  };
672 
673  class op_vvd_vari : public vari {
674  protected:
675  vari* avi_;
676  vari* bvi_;
677  double cd_;
678  public:
679  op_vvd_vari(double f, vari* avi, vari* bvi, double c) :
680  vari(f),
681  avi_(avi),
682  bvi_(bvi),
683  cd_(c) {
684  }
685  };
686 
687  class op_vdv_vari : public vari {
688  protected:
689  vari* avi_;
690  double bd_;
691  vari* cvi_;
692  public:
693  op_vdv_vari(double f, vari* avi, double b, vari* cvi) :
694  vari(f),
695  avi_(avi),
696  bd_(b),
697  cvi_(cvi) {
698  }
699  };
700 
701  class op_vdd_vari : public vari {
702  protected:
703  vari* avi_;
704  double bd_;
705  double cd_;
706  public:
707  op_vdd_vari(double f, vari* avi, double b, double c) :
708  vari(f),
709  avi_(avi),
710  bd_(b),
711  cd_(c) {
712  }
713  };
714 
715  class op_dvv_vari : public vari {
716  protected:
717  double ad_;
718  vari* bvi_;
719  vari* cvi_;
720  public:
721  op_dvv_vari(double f, double a, vari* bvi, vari* cvi) :
722  vari(f),
723  ad_(a),
724  bvi_(bvi),
725  cvi_(cvi) {
726  }
727  };
728 
729  class op_dvd_vari : public vari {
730  protected:
731  double ad_;
732  vari* bvi_;
733  double cd_;
734  public:
735  op_dvd_vari(double f, double a, vari* bvi, double c) :
736  vari(f),
737  ad_(a),
738  bvi_(bvi),
739  cd_(c) {
740  }
741  };
742 
743  class op_ddv_vari : public vari {
744  protected:
745  double ad_;
746  double bd_;
747  vari* cvi_;
748  public:
749  op_ddv_vari(double f, double a, double b, vari* cvi) :
750  vari(f),
751  ad_(a),
752  bd_(b),
753  cvi_(cvi) {
754  }
755  };
756 
757  // use for single precomputed partials
758  class precomp_v_vari : public op_v_vari {
759  protected:
760  double da_;
761  public:
762  precomp_v_vari(double val, vari* avi, double da)
763  : op_v_vari(val,avi),
764  da_(da) {
765  }
766  void chain() {
767  avi_->adj_ += adj_ * da_;
768  }
769  };
770 
771  // FIXME: memory leak -- copy vector to local memory
772  class op_vector_vari : public vari {
773  protected:
774  const size_t size_;
775  vari** vis_;
776  public:
777  op_vector_vari(double f, const std::vector<stan::agrad::var>& vs) :
778  vari(f),
779  size_(vs.size()) {
780  vis_ = (vari**) operator new(sizeof(vari*) * vs.size());
781  for (size_t i = 0; i < vs.size(); ++i)
782  vis_[i] = vs[i].vi_;
783  }
784  vari* operator[](size_t n) const {
785  return vis_[n];
786  }
787  size_t size() {
788  return size_;
789  }
790  };
791 
792  class neg_vari : public op_v_vari {
793  public:
794  neg_vari(vari* avi) :
795  op_v_vari(-(avi->val_), avi) {
796  }
797  void chain() {
798  avi_->adj_ -= adj_;
799  }
800  };
801 
802 
803  class add_vv_vari : public op_vv_vari {
804  public:
805  add_vv_vari(vari* avi, vari* bvi) :
806  op_vv_vari(avi->val_ + bvi->val_, avi, bvi) {
807  }
808  void chain() {
809  avi_->adj_ += adj_;
810  bvi_->adj_ += adj_;
811  }
812  };
813 
814  class add_vd_vari : public op_vd_vari {
815  public:
816  add_vd_vari(vari* avi, double b) :
817  op_vd_vari(avi->val_ + b, avi, b) {
818  }
819  void chain() {
820  avi_->adj_ += adj_;
821  }
822  };
823 
824  class increment_vari : public op_v_vari {
825  public:
826  increment_vari(vari* avi) :
827  op_v_vari(avi->val_ + 1.0, avi) {
828  }
829  void chain() {
830  avi_->adj_ += adj_;
831  }
832  };
833 
834  class decrement_vari : public op_v_vari {
835  public:
836  decrement_vari(vari* avi) :
837  op_v_vari(avi->val_ - 1.0, avi) {
838  }
839  void chain() {
840  avi_->adj_ += adj_;
841  }
842  };
843 
844  class subtract_vv_vari : public op_vv_vari {
845  public:
846  subtract_vv_vari(vari* avi, vari* bvi) :
847  op_vv_vari(avi->val_ - bvi->val_, avi, bvi) {
848  }
849  void chain() {
850  avi_->adj_ += adj_;
851  bvi_->adj_ -= adj_;
852  }
853  };
854 
855  class subtract_vd_vari : public op_vd_vari {
856  public:
857  subtract_vd_vari(vari* avi, double b) :
858  op_vd_vari(avi->val_ - b, avi, b) {
859  }
860  void chain() {
861  avi_->adj_ += adj_;
862  }
863  };
864 
865  class subtract_dv_vari : public op_dv_vari {
866  public:
867  subtract_dv_vari(double a, vari* bvi) :
868  op_dv_vari(a - bvi->val_, a, bvi) {
869  }
870  void chain() {
871  bvi_->adj_ -= adj_;
872  }
873  };
874 
875  class multiply_vv_vari : public op_vv_vari {
876  public:
877  multiply_vv_vari(vari* avi, vari* bvi) :
878  op_vv_vari(avi->val_ * bvi->val_, avi, bvi) {
879  }
880  void chain() {
881  avi_->adj_ += bvi_->val_ * adj_;
882  bvi_->adj_ += avi_->val_ * adj_;
883  }
884  };
885 
886  class multiply_vd_vari : public op_vd_vari {
887  public:
888  multiply_vd_vari(vari* avi, double b) :
889  op_vd_vari(avi->val_ * b, avi, b) {
890  }
891  void chain() {
892  avi_->adj_ += adj_ * bd_;
893  }
894  };
895 
896  // (a/b)' = a' * (1 / b) - b' * (a / [b * b])
897  class divide_vv_vari : public op_vv_vari {
898  public:
899  divide_vv_vari(vari* avi, vari* bvi) :
900  op_vv_vari(avi->val_ / bvi->val_, avi, bvi) {
901  }
902  void chain() {
903  avi_->adj_ += adj_ / bvi_->val_;
904  bvi_->adj_ -= adj_ * avi_->val_ / (bvi_->val_ * bvi_->val_);
905  }
906  };
907 
908  class divide_vd_vari : public op_vd_vari {
909  public:
910  divide_vd_vari(vari* avi, double b) :
911  op_vd_vari(avi->val_ / b, avi, b) {
912  }
913  void chain() {
914  avi_->adj_ += adj_ / bd_;
915  }
916  };
917 
918  class divide_dv_vari : public op_dv_vari {
919  public:
920  divide_dv_vari(double a, vari* bvi) :
921  op_dv_vari(a / bvi->val_, a, bvi) {
922  }
923  void chain() {
924  bvi_->adj_ -= adj_ * ad_ / (bvi_->val_ * bvi_->val_);
925  }
926  };
927 
928  class exp_vari : public op_v_vari {
929  public:
930  exp_vari(vari* avi) :
931  op_v_vari(std::exp(avi->val_),avi) {
932  }
933  void chain() {
934  avi_->adj_ += adj_ * val_;
935  }
936  };
937 
938  class log_vari : public op_v_vari {
939  public:
940  log_vari(vari* avi) :
941  op_v_vari(std::log(avi->val_),avi) {
942  }
943  void chain() {
944  avi_->adj_ += adj_ / avi_->val_;
945  }
946  };
947 
948  double LOG_10 = std::log(10.0);
949 
950  class log10_vari : public op_v_vari {
951  public:
952  const double exp_val_;
953  log10_vari(vari* avi) :
954  op_v_vari(std::log10(avi->val_),avi),
955  exp_val_(avi->val_) {
956  }
957  void chain() {
958  avi_->adj_ += adj_ / (LOG_10 * exp_val_);
959  }
960  };
961 
962  class sqrt_vari : public op_v_vari {
963  public:
964  sqrt_vari(vari* avi) :
965  op_v_vari(std::sqrt(avi->val_),avi) {
966  }
967  void chain() {
968  avi_->adj_ += adj_ / (2.0 * val_);
969  }
970  };
971 
972  class pow_vv_vari : public op_vv_vari {
973  public:
974  pow_vv_vari(vari* avi, vari* bvi) :
975  op_vv_vari(std::pow(avi->val_,bvi->val_),avi,bvi) {
976  }
977  void chain() {
978  if (avi_->val_ == 0.0) return; // partials zero, avoids 0 & log(0)
979  avi_->adj_ += adj_ * bvi_->val_ * val_ / avi_->val_;
980  bvi_->adj_ += adj_ * std::log(avi_->val_) * val_;
981  }
982  };
983 
984  class pow_vd_vari : public op_vd_vari {
985  public:
986  pow_vd_vari(vari* avi, double b) :
987  op_vd_vari(std::pow(avi->val_,b),avi,b) {
988  }
989  void chain() {
990  if (avi_->val_ == 0.0) return; // partials zero, avoids 0 & log(0)
991  avi_->adj_ += adj_ * bd_ * val_ / avi_->val_;
992  }
993  };
994 
995  class pow_dv_vari : public op_dv_vari {
996  public:
997  pow_dv_vari(double a, vari* bvi) :
998  op_dv_vari(std::pow(a,bvi->val_),a,bvi) {
999  }
1000  void chain() {
1001  if (ad_ == 0.0) return; // partials zero, avoids 0 & log(0)
1002  bvi_->adj_ += adj_ * std::log(ad_) * val_;
1003  }
1004  };
1005 
1006  class cos_vari : public op_v_vari {
1007  public:
1008  cos_vari(vari* avi) :
1009  op_v_vari(std::cos(avi->val_),avi) {
1010  }
1011  void chain() {
1012  avi_->adj_ -= adj_ * std::sin(avi_->val_);
1013  }
1014  };
1015 
1016  class sin_vari : public op_v_vari {
1017  public:
1018  sin_vari(vari* avi) :
1019  op_v_vari(std::sin(avi->val_),avi) {
1020  }
1021  void chain() {
1022  avi_->adj_ += adj_ * std::cos(avi_->val_);
1023  }
1024  };
1025 
1026  class tan_vari : public op_v_vari {
1027  public:
1028  tan_vari(vari* avi) :
1029  op_v_vari(std::tan(avi->val_),avi) {
1030  }
1031  void chain() {
1032  avi_->adj_ += adj_ * (1.0 + val_ * val_);
1033  }
1034  };
1035 
1036  class acos_vari : public op_v_vari {
1037  public:
1038  acos_vari(vari* avi) :
1039  op_v_vari(std::acos(avi->val_),avi) {
1040  }
1041  void chain() {
1042  avi_->adj_ -= adj_ / std::sqrt(1.0 - (avi_->val_ * avi_->val_));
1043  }
1044  };
1045 
1046  class asin_vari : public op_v_vari {
1047  public:
1048  asin_vari(vari* avi) :
1049  op_v_vari(std::asin(avi->val_),avi) {
1050  }
1051  void chain() {
1052  avi_->adj_ += adj_ / std::sqrt(1.0 - (avi_->val_ * avi_->val_));
1053  }
1054  };
1055 
1056  class atan_vari : public op_v_vari {
1057  public:
1058  atan_vari(vari* avi) :
1059  op_v_vari(std::atan(avi->val_),avi) {
1060  }
1061  void chain() {
1062  avi_->adj_ += adj_ / (1.0 + (avi_->val_ * avi_->val_));
1063  }
1064  };
1065 
1066  class atan2_vv_vari : public op_vv_vari {
1067  public:
1068  atan2_vv_vari(vari* avi, vari* bvi) :
1069  op_vv_vari(std::atan2(avi->val_,bvi->val_),avi,bvi) {
1070  }
1071  void chain() {
1072  double a_sq_plus_b_sq = (avi_->val_ * avi_->val_) + (bvi_->val_ * bvi_->val_);
1073  avi_->adj_ += adj_ * bvi_->val_ / a_sq_plus_b_sq;
1074  bvi_->adj_ -= adj_ * avi_->val_ / a_sq_plus_b_sq;
1075  }
1076  };
1077 
1078  class atan2_vd_vari : public op_vd_vari {
1079  public:
1080  atan2_vd_vari(vari* avi, double b) :
1081  op_vd_vari(std::atan2(avi->val_,b),avi,b) {
1082  }
1083  void chain() {
1084  double a_sq_plus_b_sq = (avi_->val_ * avi_->val_) + (bd_ * bd_);
1085  avi_->adj_ += adj_ * bd_ / a_sq_plus_b_sq;
1086  }
1087  };
1088 
1089  class atan2_dv_vari : public op_dv_vari {
1090  public:
1091  atan2_dv_vari(double a, vari* bvi) :
1092  op_dv_vari(std::atan2(a,bvi->val_),a,bvi) {
1093  }
1094  void chain() {
1095  double a_sq_plus_b_sq = (ad_ * ad_) + (bvi_->val_ * bvi_->val_);
1096  bvi_->adj_ -= adj_ * ad_ / a_sq_plus_b_sq;
1097  }
1098  };
1099 
1100  class cosh_vari : public op_v_vari {
1101  public:
1102  cosh_vari(vari* avi) :
1103  op_v_vari(std::cosh(avi->val_),avi) {
1104  }
1105  void chain() {
1106  avi_->adj_ += adj_ * std::sinh(avi_->val_);
1107  }
1108  };
1109 
1110  class sinh_vari : public op_v_vari {
1111  public:
1112  sinh_vari(vari* avi) :
1113  op_v_vari(std::sinh(avi->val_),avi) {
1114  }
1115  void chain() {
1116  avi_->adj_ += adj_ * std::cosh(avi_->val_);
1117  }
1118  };
1119 
1120  class tanh_vari : public op_v_vari {
1121  public:
1122  tanh_vari(vari* avi) :
1123  op_v_vari(std::tanh(avi->val_),avi) {
1124  }
1125  void chain() {
1126  double cosh = std::cosh(avi_->val_);
1127  avi_->adj_ += adj_ / (cosh * cosh);
1128  }
1129  };
1130 
1131 
1132  class floor_vari : public vari {
1133  public:
1134  floor_vari(vari* avi) :
1135  vari(std::floor(avi->val_)) {
1136  }
1137  };
1138 
1139  class ceil_vari : public vari {
1140  public:
1141  ceil_vari(vari* avi) :
1142  vari(std::ceil(avi->val_)) {
1143  }
1144  };
1145 
1146  class fmod_vv_vari : public op_vv_vari {
1147  public:
1148  fmod_vv_vari(vari* avi, vari* bvi) :
1149  op_vv_vari(std::fmod(avi->val_,bvi->val_),avi,bvi) {
1150  }
1151  void chain() {
1152  avi_->adj_ += adj_;
1153  bvi_->adj_ -= adj_ * static_cast<int>(avi_->val_ / bvi_->val_);
1154  }
1155  };
1156 
1157  class fmod_vd_vari : public op_v_vari {
1158  public:
1159  fmod_vd_vari(vari* avi, double b) :
1160  op_v_vari(std::fmod(avi->val_,b),avi) {
1161  }
1162  void chain() {
1163  avi_->adj_ += adj_;
1164  }
1165  };
1166 
1167  class fmod_dv_vari : public op_dv_vari {
1168  public:
1169  fmod_dv_vari(double a, vari* bvi) :
1170  op_dv_vari(std::fmod(a,bvi->val_),a,bvi) {
1171  }
1172  void chain() {
1173  int d = static_cast<int>(ad_ / bvi_->val_);
1174  bvi_->adj_ -= adj_ * d;
1175  }
1176  };
1177  }
1178 
1179 
1180  // COMPARISON OPERATORS
1181 
1190  inline bool operator==(const var& a, const var& b) {
1191  return a.val() == b.val();
1192  }
1193 
1203  inline bool operator==(const var& a, const double b) {
1204  return a.val() == b;
1205  }
1206 
1215  inline bool operator==(const double a, const var& b) {
1216  return a == b.val();
1217  }
1218 
1227  inline bool operator!=(const var& a, const var& b) {
1228  return a.val() != b.val();
1229  }
1230 
1240  inline bool operator!=(const var& a, const double b) {
1241  return a.val() != b;
1242  }
1243 
1253  inline bool operator!=(const double a, const var& b) {
1254  return a != b.val();
1255  }
1256 
1264  inline bool operator<(const var& a, const var& b) {
1265  return a.val() < b.val();
1266  }
1267 
1276  inline bool operator<(const var& a, const double b) {
1277  return a.val() < b;
1278  }
1279 
1288  inline bool operator<(const double a, const var& b) {
1289  return a < b.val();
1290  }
1291 
1299  inline bool operator>(const var& a, const var& b) {
1300  return a.val() > b.val();
1301  }
1302 
1311  inline bool operator>(const var& a, const double b) {
1312  return a.val() > b;
1313  }
1314 
1323  inline bool operator>(const double a, const var& b) {
1324  return a > b.val();
1325  }
1326 
1336  inline bool operator<=(const var& a, const var& b) {
1337  return a.val() <= b.val();
1338  }
1339 
1349  inline bool operator<=(const var& a, const double b) {
1350  return a.val() <= b;
1351  }
1352 
1362  inline bool operator<=(const double a, const var& b) {
1363  return a <= b.val();
1364  }
1365 
1375  inline bool operator>=(const var& a, const var& b) {
1376  return a.val() >= b.val();
1377  }
1378 
1388  inline bool operator>=(const var& a, const double b) {
1389  return a.val() >= b;
1390  }
1391 
1401  inline bool operator>=(const double a, const var& b) {
1402  return a >= b.val();
1403  }
1404 
1405  // LOGICAL OPERATORS
1406 
1420  inline bool operator!(const var& a) {
1421  return !a.val();
1422  }
1423 
1424 
1425  // ARITHMETIC OPERATORS
1426 
1442  inline var operator+(const var& a) {
1443  return a;
1444  }
1445 
1454  inline var operator-(const var& a) {
1455  return var(new neg_vari(a.vi_));
1456  }
1457 
1471  inline var operator+(const var& a, const var& b) {
1472  return var(new add_vv_vari(a.vi_,b.vi_));
1473  }
1474 
1475 
1487  inline var operator+(const var& a, const double b) {
1488  if (b == 0.0)
1489  return a;
1490  return var(new add_vd_vari(a.vi_,b));
1491  }
1492 
1504  inline var operator+(const double a, const var& b) {
1505  if (a == 0.0)
1506  return b;
1507  return var(new add_vd_vari(b.vi_,a)); // by symmetry
1508  }
1509 
1524  inline var operator-(const var& a, const var& b) {
1525  return var(new subtract_vv_vari(a.vi_,b.vi_));
1526  }
1527 
1539  inline var operator-(const var& a, const double b) {
1540  if (b == 0.0)
1541  return a;
1542  return var(new subtract_vd_vari(a.vi_,b));
1543  }
1544 
1556  inline var operator-(const double a, const var& b) {
1557  return var(new subtract_dv_vari(a,b.vi_));
1558  }
1559 
1573  inline var operator*(const var& a, const var& b) {
1574  return var(new multiply_vv_vari(a.vi_,b.vi_));
1575  }
1576 
1588  inline var operator*(const var& a, const double b) {
1589  if (b == 1.0)
1590  return a;
1591  return var(new multiply_vd_vari(a.vi_,b));
1592  }
1593 
1605  inline var operator*(const double a, const var& b) {
1606  if (a == 1.0)
1607  return b;
1608  return var(new multiply_vd_vari(b.vi_,a)); // by symmetry
1609  }
1610 
1625  inline var operator/(const var& a, const var& b) {
1626  return var(new divide_vv_vari(a.vi_,b.vi_));
1627  }
1628 
1640  inline var operator/(const var& a, const double b) {
1641  if (b == 1.0)
1642  return a;
1643  return var(new divide_vd_vari(a.vi_,b));
1644  }
1645 
1657  inline var operator/(const double a, const var& b) {
1658  return var(new divide_dv_vari(a,b.vi_));
1659  }
1660 
1670  inline var& operator++(var& a) {
1671  a.vi_ = new increment_vari(a.vi_);
1672  return a;
1673  }
1674 
1686  inline var operator++(var& a, int /*dummy*/) {
1687  var temp(a);
1688  a.vi_ = new increment_vari(a.vi_);
1689  return temp;
1690  }
1691 
1705  inline var& operator--(var& a) {
1706  a.vi_ = new decrement_vari(a.vi_);
1707  return a;
1708  }
1709 
1721  inline var operator--(var& a, int /*dummy*/) {
1722  var temp(a);
1723  a.vi_ = new decrement_vari(a.vi_);
1724  return temp;
1725  }
1726 
1727  // CMATH EXP AND LOG
1728 
1735  inline var exp(const var& a) {
1736  return var(new exp_vari(a.vi_));
1737  }
1738 
1749  inline var log(const var& a) {
1750  return var(new log_vari(a.vi_));
1751  }
1752 
1763  inline var log10(const var& a) {
1764  return var(new log10_vari(a.vi_));
1765  }
1766 
1767 
1768  // POWER FUNCTIONS
1769 
1780  inline var sqrt(const var& a) {
1781  return var(new sqrt_vari(a.vi_));
1782  }
1783 
1797  inline var pow(const var& base, const var& exponent) {
1798  return var(new pow_vv_vari(base.vi_,exponent.vi_));
1799  }
1800 
1813  inline var pow(const var& base, const double exponent) {
1814  if (exponent == 0.5)
1815  return sqrt(base);
1816  if (exponent == 1.0)
1817  return base;
1818  if (exponent == 2.0)
1819  return base * base; // FIXME: square() functionality from special_functions
1820  return var(new pow_vd_vari(base.vi_,exponent));
1821  }
1822 
1835  inline var pow(const double base, const var& exponent) {
1836  return var(new pow_dv_vari(base,exponent.vi_));
1837  }
1838 
1839 
1840  // TRIG FUNCTIONS
1841 
1852  inline var cos(const var& a) {
1853  return var(new cos_vari(a.vi_));
1854  }
1855 
1866  inline var sin(const var& a) {
1867  return var(new sin_vari(a.vi_));
1868  }
1869 
1880  inline var tan(const var& a) {
1881  return var(new tan_vari(a.vi_));
1882  }
1883 
1895  inline var acos(const var& a) {
1896  return var(new acos_vari(a.vi_));
1897  }
1898 
1910  inline var asin(const var& a) {
1911  return var(new asin_vari(a.vi_));
1912  }
1913 
1925  inline var atan(const var& a) {
1926  return var(new atan_vari(a.vi_));
1927  }
1928 
1943  inline var atan2(const var& a, const var& b) {
1944  return var(new atan2_vv_vari(a.vi_,b.vi_));
1945  }
1946 
1959  inline var atan2(const var& a, const double b) {
1960  return var(new atan2_vd_vari(a.vi_,b));
1961  }
1962 
1975  inline var atan2(const double a, const var& b) {
1976  return var(new atan2_dv_vari(a,b.vi_));
1977  }
1978 
1979  // HYPERBOLIC FUNCTIONS
1980 
1991  inline var cosh(const var& a) {
1992  return var(new cosh_vari(a.vi_));
1993  }
1994 
2005  inline var sinh(const var& a) {
2006  return var(new sinh_vari(a.vi_));
2007  }
2008 
2019  inline var tanh(const var& a) {
2020  return var(new tanh_vari(a.vi_));
2021  }
2022 
2023 
2024  // ROUNDING FUNCTIONS
2025 
2042  inline var fabs(const var& a) {
2043  // cut-and-paste from abs()
2044  if (a.val() > 0.0)
2045  return a;
2046  if (a.val() < 0.0)
2047  return var(new neg_vari(a.vi_));
2048  // FIXME: is this right? breaks connection to a
2049  return var(new vari(0.0));
2050  }
2051 
2070  inline var floor(const var& a) {
2071  return var(new floor_vari(a.vi_));
2072  }
2073 
2092  inline var ceil(const var& a) {
2093  return var(new ceil_vari(a.vi_));
2094  }
2095 
2113  inline var fmod(const var& a, const var& b) {
2114  return var(new fmod_vv_vari(a.vi_,b.vi_));
2115  }
2116 
2130  inline var fmod(const var& a, const double b) {
2131  return var(new fmod_vd_vari(a.vi_,b));
2132  }
2133 
2147  inline var fmod(const double a, const var& b) {
2148  return var(new fmod_dv_vari(a,b.vi_));
2149  }
2150 
2151 
2152  // STD LIB FUNCTIONS
2153 
2168  inline var abs(const var& a) {
2169  // cut-and-paste from fabs()
2170  if (a.val() > 0.0)
2171  return a;
2172  if (a.val() < 0.0)
2173  return var(new neg_vari(a.vi_));
2174  // FIXME: same as fabs() -- is this right?
2175  return var(new vari(0.0));
2176  }
2177 
2178 
2182  static void recover_memory() {
2183  var_stack_.clear();
2184  var_nochain_stack_.clear();
2186  }
2187 
2191  static void free_memory() {
2192  memalloc_.free_all();
2193  }
2194 
2207  static void grad(chainable* vi) {
2208  std::vector<chainable*>::reverse_iterator it;
2209 
2210  vi->init_dependent();
2211  // propagate derivates for vars
2212  for (it = var_stack_.rbegin(); it < var_stack_.rend(); ++it)
2213  (*it)->chain();
2214  }
2215 
2219  static void set_zero_all_adjoints() {
2220  for (size_t i = 0; i < var_stack_.size(); ++i)
2221  var_stack_[i]->set_zero_adjoint();
2222  for (size_t i = 0; i < var_nochain_stack_.size(); ++i)
2223  var_nochain_stack_[i]->set_zero_adjoint();
2224  }
2225 
2252  inline void jacobian(std::vector<var>& dependents,
2253  std::vector<var>& independents,
2254  std::vector<std::vector<double> >& jacobian) {
2255  jacobian.resize(dependents.size());
2256  for (size_t i = 0; i < dependents.size(); ++i) {
2257  jacobian[i].resize(independents.size());
2258  if (i > 0)
2260  jacobian.push_back(std::vector<double>(0));
2261  grad(dependents[i].vi_);
2262  for (size_t j = 0; j < independents.size(); ++j)
2263  jacobian[i][j] = independents[j].adj();
2264  }
2265  }
2266 
2267 
2268  inline var& var::operator+=(const var& b) {
2269  vi_ = new add_vv_vari(vi_,b.vi_);
2270  return *this;
2271  }
2272 
2273  inline var& var::operator+=(const double b) {
2274  if (b == 0.0)
2275  return *this;
2276  vi_ = new add_vd_vari(vi_,b);
2277  return *this;
2278  }
2279 
2280  inline var& var::operator-=(const var& b) {
2281  vi_ = new subtract_vv_vari(vi_,b.vi_);
2282  return *this;
2283  }
2284 
2285  inline var& var::operator-=(const double b) {
2286  if (b == 0.0)
2287  return *this;
2288  vi_ = new subtract_vd_vari(vi_,b);
2289  return *this;
2290  }
2291 
2292  inline var& var::operator*=(const var& b) {
2293  vi_ = new multiply_vv_vari(vi_,b.vi_);
2294  return *this;
2295  }
2296 
2297  inline var& var::operator*=(const double b) {
2298  if (b == 1.0)
2299  return *this;
2300  vi_ = new multiply_vd_vari(vi_,b);
2301  return *this;
2302  }
2303 
2304  inline var& var::operator/=(const var& b) {
2305  vi_ = new divide_vv_vari(vi_,b.vi_);
2306  return *this;
2307  }
2308 
2309  inline var& var::operator/=(const double b) {
2310  if (b == 1.0)
2311  return *this;
2312  vi_ = new divide_vd_vari(vi_,b);
2313  return *this;
2314  }
2315  }
2316 
2317 }
2318 
2319 
2320 namespace std {
2321 
2328  template<>
2329  struct numeric_limits<stan::agrad::var> {
2330  static const bool is_specialized = true;
2333  static const int digits = numeric_limits<double>::digits;
2334  static const int digits10 = numeric_limits<double>::digits10;
2335  static const bool is_signed = numeric_limits<double>::is_signed;
2336  static const bool is_integer = numeric_limits<double>::is_integer;
2337  static const bool is_exact = numeric_limits<double>::is_exact;
2338  static const int radix = numeric_limits<double>::radix;
2340  static stan::agrad::var round_error() { return numeric_limits<double>::round_error(); }
2341 
2342  static const int min_exponent = numeric_limits<double>::min_exponent;
2343  static const int min_exponent10 = numeric_limits<double>::min_exponent10;
2344  static const int max_exponent = numeric_limits<double>::max_exponent;
2345  static const int max_exponent10 = numeric_limits<double>::max_exponent10;
2346 
2347  static const bool has_infinity = numeric_limits<double>::has_infinity;
2348  static const bool has_quiet_NaN = numeric_limits<double>::has_quiet_NaN;
2349  static const bool has_signaling_NaN = numeric_limits<double>::has_signaling_NaN;
2350  static const float_denorm_style has_denorm = numeric_limits<double>::has_denorm;
2351  static const bool has_denorm_loss = numeric_limits<double>::has_denorm_loss;
2352  static stan::agrad::var infinity() { return numeric_limits<double>::infinity(); }
2353  static stan::agrad::var quiet_NaN() { return numeric_limits<double>::quiet_NaN(); }
2354  static stan::agrad::var signaling_NaN() { return numeric_limits<double>::signaling_NaN(); }
2355  static stan::agrad::var denorm_min() { return numeric_limits<double>::denorm_min(); }
2356 
2357  static const bool is_iec559 = numeric_limits<double>::is_iec559;
2358  static const bool is_bounded = numeric_limits<double>::is_bounded;
2359  static const bool is_modulo = numeric_limits<double>::is_modulo;
2360 
2361  static const bool traps = numeric_limits<double>::traps;
2362  static const bool tinyness_before = numeric_limits<double>::tinyness_before;
2363  static const float_round_style round_style = numeric_limits<double>::round_style;
2364  };
2365 
2375  inline int isnan(const stan::agrad::var& a) {
2376  return isnan(a.val());
2377  }
2378 
2388  inline int isinf(const stan::agrad::var& a) {
2389  return isinf(a.val());
2390  }
2391 
2392 }
2393 
2394 #endif

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