Stan  1.0
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  template <typename T>
23  struct var_to_vi {
24  typedef T type;
25  };
26  template <>
27  struct var_to_vi<stan::agrad::var> {
29  };
30 
31 
32  // FIXME: manage all this as a single singleton (thread local)
33  extern std::vector<chainable*> var_stack_;
35 
36  static void recover_memory();
37 
38  static void grad(chainable* vi);
39 
44  class chainable {
45 
46  public:
47 
52  chainable() { }
53 
60  throw std::logic_error("chainable destruction handled automatically");
61  }
62 
68  virtual void chain() {
69  }
70 
75  virtual void init_dependent() {
76  }
77 
82  virtual void set_zero_adjoint() {
83  }
84 
85 
95  static inline void* operator new(size_t nbytes) {
96  return memalloc_.alloc(nbytes);
97  }
98 
99  };
100 
114  class vari : public chainable {
115  private:
116  friend class var;
117 
118  public:
119 
123  const double val_;
124 
129  double adj_;
130 
143  vari(const double x):
144  val_(x),
145  adj_(0.0) {
146  var_stack_.push_back(this);
147  }
148 
156  ~vari() {
157  throw std::logic_error("vari destruction handled automatically");
158  }
159 
165  virtual void init_dependent() {
166  adj_ = 1.0; // droot/droot = 1
167  }
168 
172  virtual void set_zero_adjoint() {
173  adj_ = 0.0;
174  }
175 
185  friend std::ostream& operator<<(std::ostream& os, const vari* v) {
186  return os << v << " " << v->val_ << " : " << v->adj_;
187  }
188 
189  };
190 
197  inline size_t stack_size() {
198  return var_stack_.size();
199  }
200 
201 
208  inline void print_stack(std::ostream& o) {
209  o << "STACK, size=" << var_stack_.size() << std::endl;
210  for (size_t i = 0; i < var_stack_.size(); ++i)
211  o << i
212  << " " << var_stack_[i]
213  << " " << ((vari*)var_stack_[i])->val_
214  << " : " << ((vari*)var_stack_[i])->adj_
215  << std::endl;
216  }
217 
218 
232  class var {
233  public:
234 
235  // FIXME: doc what this is for
236  typedef double Scalar;
237 
246 
257  return (vi_ == static_cast<vari*>(0U));
258  }
259 
265  explicit var(vari* vi)
266  : vi_(vi)
267  { }
268 
276  var()
277  : vi_(static_cast<vari*>(0U))
278  { }
279 
286  var(bool b) :
287  vi_(new vari(static_cast<double>(b))) {
288  }
289 
296  var(char c) :
297  vi_(new vari(static_cast<double>(c))) {
298  }
299 
306  var(short n) :
307  vi_(new vari(static_cast<double>(n))) {
308  }
309 
316  var(unsigned short n) :
317  vi_(new vari(static_cast<double>(n))) {
318  }
319 
326  var(int n) :
327  vi_(new vari(static_cast<double>(n))) {
328  }
329 
336  var(unsigned int n) :
337  vi_(new vari(static_cast<double>(n))) {
338  }
339 
346  var(long int n) :
347  vi_(new vari(static_cast<double>(n))) {
348  }
349 
356  var(unsigned long int n) :
357  vi_(new vari(static_cast<double>(n))) {
358  }
359 
366  var(unsigned long long n) :
367  vi_(new vari(static_cast<double>(n))) {
368  }
369 
376  var(long long n) :
377  vi_(new vari(static_cast<double>(n))) {
378  }
379 
386  var(float x) :
387  vi_(new vari(static_cast<double>(x))) {
388  }
389 
395  var(double x) :
396  vi_(new vari(x)) {
397  }
398 
405  var(long double x) :
406  vi_(new vari(static_cast<double>(x))) {
407  }
408 
414  inline double val() const {
415  return vi_->val_;
416  }
417 
426  inline double adj() const {
427  return vi_->adj_;
428  }
429 
442  void grad(std::vector<var>& x,
443  std::vector<double>& g) {
445  g.resize(0);
446  for (size_t i = 0; i < x.size(); ++i)
447  g.push_back(x[i].vi_->adj_);
448  recover_memory();
449  }
450 
467  void grad() {
469  recover_memory();
470  }
471 
472  // POINTER OVERRIDES
473 
486  inline vari& operator*() {
487  return *vi_;
488  }
489 
500  inline vari* operator->() {
501  return vi_;
502  }
503 
504  // COMPOUND ASSIGNMENT OPERATORS
505 
516  inline var& operator+=(const var& b);
517 
528  inline var& operator+=(const double b);
529 
541  inline var& operator-=(const var& b);
542 
554  inline var& operator-=(const double b);
555 
567  inline var& operator*=(const var& b);
568 
580  inline var& operator*=(const double b);
581 
592  inline var& operator/=(const var& b);
593 
605  inline var& operator/=(const double b);
606 
615  friend std::ostream& operator<<(std::ostream& os, const var& v) {
616  return os << v.val() << ':' << v.adj();
617  }
618  };
619 
620  namespace {
621 
622  class op_v_vari : public vari {
623  protected:
624  vari* avi_;
625  public:
626  op_v_vari(double f, vari* avi) :
627  vari(f),
628  avi_(avi) {
629  }
630  };
631 
632  class op_vv_vari : public vari {
633  protected:
634  vari* avi_;
635  vari* bvi_;
636  public:
637  op_vv_vari(double f, vari* avi, vari* bvi):
638  vari(f),
639  avi_(avi),
640  bvi_(bvi) {
641  }
642  };
643 
644  class op_vd_vari : public vari {
645  protected:
646  vari* avi_;
647  double bd_;
648  public:
649  op_vd_vari(double f, vari* avi, double b) :
650  vari(f),
651  avi_(avi),
652  bd_(b) {
653  }
654  };
655 
656  class op_dv_vari : public vari {
657  protected:
658  double ad_;
659  vari* bvi_;
660  public:
661  op_dv_vari(double f, double a, vari* bvi) :
662  vari(f),
663  ad_(a),
664  bvi_(bvi) {
665  }
666  };
667 
668  class op_vvv_vari : public vari {
669  protected:
670  vari* avi_;
671  vari* bvi_;
672  vari* cvi_;
673  public:
674  op_vvv_vari(double f, vari* avi, vari* bvi, vari* cvi) :
675  vari(f),
676  avi_(avi),
677  bvi_(bvi),
678  cvi_(cvi) {
679  }
680  };
681 
682  class op_vvd_vari : public vari {
683  protected:
684  vari* avi_;
685  vari* bvi_;
686  double cd_;
687  public:
688  op_vvd_vari(double f, vari* avi, vari* bvi, double c) :
689  vari(f),
690  avi_(avi),
691  bvi_(bvi),
692  cd_(c) {
693  }
694  };
695 
696  class op_vdv_vari : public vari {
697  protected:
698  vari* avi_;
699  double bd_;
700  vari* cvi_;
701  public:
702  op_vdv_vari(double f, vari* avi, double b, vari* cvi) :
703  vari(f),
704  avi_(avi),
705  bd_(b),
706  cvi_(cvi) {
707  }
708  };
709 
710  class op_vdd_vari : public vari {
711  protected:
712  vari* avi_;
713  double bd_;
714  double cd_;
715  public:
716  op_vdd_vari(double f, vari* avi, double b, double c) :
717  vari(f),
718  avi_(avi),
719  bd_(b),
720  cd_(c) {
721  }
722  };
723 
724  class op_dvv_vari : public vari {
725  protected:
726  double ad_;
727  vari* bvi_;
728  vari* cvi_;
729  public:
730  op_dvv_vari(double f, double a, vari* bvi, vari* cvi) :
731  vari(f),
732  ad_(a),
733  bvi_(bvi),
734  cvi_(cvi) {
735  }
736  };
737 
738  class op_dvd_vari : public vari {
739  protected:
740  double ad_;
741  vari* bvi_;
742  double cd_;
743  public:
744  op_dvd_vari(double f, double a, vari* bvi, double c) :
745  vari(f),
746  ad_(a),
747  bvi_(bvi),
748  cd_(c) {
749  }
750  };
751 
752  class op_ddv_vari : public vari {
753  protected:
754  double ad_;
755  double bd_;
756  vari* cvi_;
757  public:
758  op_ddv_vari(double f, double a, double b, vari* cvi) :
759  vari(f),
760  ad_(a),
761  bd_(b),
762  cvi_(cvi) {
763  }
764  };
765 
766  // FIXME: memory leak -- copy vector to local memory
767  class op_vector_vari : public vari {
768  protected:
769  const size_t size_;
770  vari** vis_;
771  public:
772  op_vector_vari(double f, const std::vector<stan::agrad::var>& vs) :
773  vari(f),
774  size_(vs.size()) {
775  vis_ = (vari**) operator new(sizeof(vari*[vs.size()]));
776  for (size_t i = 0; i < vs.size(); ++i)
777  vis_[i] = vs[i].vi_;
778  }
779  vari* operator[](size_t n) const {
780  return vis_[n];
781  }
782  size_t size() {
783  return size_;
784  }
785  };
786 
787  class neg_vari : public op_v_vari {
788  public:
789  neg_vari(vari* avi) :
790  op_v_vari(-(avi->val_), avi) {
791  }
792  void chain() {
793  avi_->adj_ -= adj_;
794  }
795  };
796 
797 
798  class add_vv_vari : public op_vv_vari {
799  public:
800  add_vv_vari(vari* avi, vari* bvi) :
801  op_vv_vari(avi->val_ + bvi->val_, avi, bvi) {
802  }
803  void chain() {
804  avi_->adj_ += adj_;
805  bvi_->adj_ += adj_;
806  }
807  };
808 
809  class add_vd_vari : public op_vd_vari {
810  public:
811  add_vd_vari(vari* avi, double b) :
812  op_vd_vari(avi->val_ + b, avi, b) {
813  }
814  void chain() {
815  avi_->adj_ += adj_;
816  }
817  };
818 
819  class increment_vari : public op_v_vari {
820  public:
821  increment_vari(vari* avi) :
822  op_v_vari(avi->val_ + 1.0, avi) {
823  }
824  void chain() {
825  avi_->adj_ += adj_;
826  }
827  };
828 
829  class decrement_vari : public op_v_vari {
830  public:
831  decrement_vari(vari* avi) :
832  op_v_vari(avi->val_ - 1.0, avi) {
833  }
834  void chain() {
835  avi_->adj_ += adj_;
836  }
837  };
838 
839  class subtract_vv_vari : public op_vv_vari {
840  public:
841  subtract_vv_vari(vari* avi, vari* bvi) :
842  op_vv_vari(avi->val_ - bvi->val_, avi, bvi) {
843  }
844  void chain() {
845  avi_->adj_ += adj_;
846  bvi_->adj_ -= adj_;
847  }
848  };
849 
850  class subtract_vd_vari : public op_vd_vari {
851  public:
852  subtract_vd_vari(vari* avi, double b) :
853  op_vd_vari(avi->val_ - b, avi, b) {
854  }
855  void chain() {
856  avi_->adj_ += adj_;
857  }
858  };
859 
860  class subtract_dv_vari : public op_dv_vari {
861  public:
862  subtract_dv_vari(double a, vari* bvi) :
863  op_dv_vari(a - bvi->val_, a, bvi) {
864  }
865  void chain() {
866  bvi_->adj_ -= adj_;
867  }
868  };
869 
870  class multiply_vv_vari : public op_vv_vari {
871  public:
872  multiply_vv_vari(vari* avi, vari* bvi) :
873  op_vv_vari(avi->val_ * bvi->val_, avi, bvi) {
874  }
875  void chain() {
876  avi_->adj_ += bvi_->val_ * adj_;
877  bvi_->adj_ += avi_->val_ * adj_;
878  }
879  };
880 
881  class multiply_vd_vari : public op_vd_vari {
882  public:
883  multiply_vd_vari(vari* avi, double b) :
884  op_vd_vari(avi->val_ * b, avi, b) {
885  }
886  void chain() {
887  avi_->adj_ += adj_ * bd_;
888  }
889  };
890 
891  // (a/b)' = a' * (1 / b) - b' * (a / [b * b])
892  class divide_vv_vari : public op_vv_vari {
893  public:
894  divide_vv_vari(vari* avi, vari* bvi) :
895  op_vv_vari(avi->val_ / bvi->val_, avi, bvi) {
896  }
897  void chain() {
898  avi_->adj_ += adj_ / bvi_->val_;
899  bvi_->adj_ -= adj_ * avi_->val_ / (bvi_->val_ * bvi_->val_);
900  }
901  };
902 
903  class divide_vd_vari : public op_vd_vari {
904  public:
905  divide_vd_vari(vari* avi, double b) :
906  op_vd_vari(avi->val_ / b, avi, b) {
907  }
908  void chain() {
909  avi_->adj_ += adj_ / bd_;
910  }
911  };
912 
913  class divide_dv_vari : public op_dv_vari {
914  public:
915  divide_dv_vari(double a, vari* bvi) :
916  op_dv_vari(a / bvi->val_, a, bvi) {
917  }
918  void chain() {
919  bvi_->adj_ -= adj_ * ad_ / (bvi_->val_ * bvi_->val_);
920  }
921  };
922 
923  class exp_vari : public op_v_vari {
924  public:
925  exp_vari(vari* avi) :
926  op_v_vari(std::exp(avi->val_),avi) {
927  }
928  void chain() {
929  avi_->adj_ += adj_ * val_;
930  }
931  };
932 
933  class log_vari : public op_v_vari {
934  public:
935  log_vari(vari* avi) :
936  op_v_vari(std::log(avi->val_),avi) {
937  }
938  void chain() {
939  avi_->adj_ += adj_ / avi_->val_;
940  }
941  };
942 
943  double LOG_10 = std::log(10.0);
944 
945  class log10_vari : public op_v_vari {
946  public:
947  const double exp_val_;
948  log10_vari(vari* avi) :
949  op_v_vari(std::log10(avi->val_),avi),
950  exp_val_(avi->val_) {
951  }
952  void chain() {
953  avi_->adj_ += adj_ / (LOG_10 * exp_val_);
954  }
955  };
956 
957  class sqrt_vari : public op_v_vari {
958  public:
959  sqrt_vari(vari* avi) :
960  op_v_vari(std::sqrt(avi->val_),avi) {
961  }
962  void chain() {
963  avi_->adj_ += adj_ / (2.0 * val_);
964  }
965  };
966 
967  class pow_vv_vari : public op_vv_vari {
968  public:
969  pow_vv_vari(vari* avi, vari* bvi) :
970  op_vv_vari(std::pow(avi->val_,bvi->val_),avi,bvi) {
971  }
972  void chain() {
973  if (avi_->val_ == 0.0) return; // partials zero, avoids 0 & log(0)
974  avi_->adj_ += adj_ * bvi_->val_ * val_ / avi_->val_;
975  bvi_->adj_ += adj_ * std::log(avi_->val_) * val_;
976  }
977  };
978 
979  class pow_vd_vari : public op_vd_vari {
980  public:
981  pow_vd_vari(vari* avi, double b) :
982  op_vd_vari(std::pow(avi->val_,b),avi,b) {
983  }
984  void chain() {
985  if (avi_->val_ == 0.0) return; // partials zero, avoids 0 & log(0)
986  avi_->adj_ += adj_ * bd_ * val_ / avi_->val_;
987  }
988  };
989 
990  class pow_dv_vari : public op_dv_vari {
991  public:
992  pow_dv_vari(double a, vari* bvi) :
993  op_dv_vari(std::pow(a,bvi->val_),a,bvi) {
994  }
995  void chain() {
996  if (ad_ == 0.0) return; // partials zero, avoids 0 & log(0)
997  bvi_->adj_ += adj_ * std::log(ad_) * val_;
998  }
999  };
1000 
1001  class cos_vari : public op_v_vari {
1002  public:
1003  cos_vari(vari* avi) :
1004  op_v_vari(std::cos(avi->val_),avi) {
1005  }
1006  void chain() {
1007  avi_->adj_ -= adj_ * std::sin(avi_->val_);
1008  }
1009  };
1010 
1011  class sin_vari : public op_v_vari {
1012  public:
1013  sin_vari(vari* avi) :
1014  op_v_vari(std::sin(avi->val_),avi) {
1015  }
1016  void chain() {
1017  avi_->adj_ += adj_ * std::cos(avi_->val_);
1018  }
1019  };
1020 
1021  class tan_vari : public op_v_vari {
1022  public:
1023  tan_vari(vari* avi) :
1024  op_v_vari(std::tan(avi->val_),avi) {
1025  }
1026  void chain() {
1027  avi_->adj_ += adj_ * (1.0 + val_ * val_);
1028  }
1029  };
1030 
1031  class acos_vari : public op_v_vari {
1032  public:
1033  acos_vari(vari* avi) :
1034  op_v_vari(std::acos(avi->val_),avi) {
1035  }
1036  void chain() {
1037  avi_->adj_ -= adj_ / std::sqrt(1.0 - (avi_->val_ * avi_->val_));
1038  }
1039  };
1040 
1041  class asin_vari : public op_v_vari {
1042  public:
1043  asin_vari(vari* avi) :
1044  op_v_vari(std::asin(avi->val_),avi) {
1045  }
1046  void chain() {
1047  avi_->adj_ += adj_ / std::sqrt(1.0 - (avi_->val_ * avi_->val_));
1048  }
1049  };
1050 
1051  class atan_vari : public op_v_vari {
1052  public:
1053  atan_vari(vari* avi) :
1054  op_v_vari(std::atan(avi->val_),avi) {
1055  }
1056  void chain() {
1057  avi_->adj_ += adj_ / (1.0 + (avi_->val_ * avi_->val_));
1058  }
1059  };
1060 
1061  class atan2_vv_vari : public op_vv_vari {
1062  public:
1063  atan2_vv_vari(vari* avi, vari* bvi) :
1064  op_vv_vari(std::atan2(avi->val_,bvi->val_),avi,bvi) {
1065  }
1066  void chain() {
1067  double a_sq_plus_b_sq = (avi_->val_ * avi_->val_) + (bvi_->val_ * bvi_->val_);
1068  avi_->adj_ += bvi_->val_ / a_sq_plus_b_sq;
1069  bvi_->adj_ -= avi_->val_ / a_sq_plus_b_sq;
1070  }
1071  };
1072 
1073  class atan2_vd_vari : public op_vd_vari {
1074  public:
1075  atan2_vd_vari(vari* avi, double b) :
1076  op_vd_vari(std::atan2(avi->val_,b),avi,b) {
1077  }
1078  void chain() {
1079  double a_sq_plus_b_sq = (avi_->val_ * avi_->val_) + (bd_ * bd_);
1080  avi_->adj_ += bd_ / a_sq_plus_b_sq;
1081  }
1082  };
1083 
1084  class atan2_dv_vari : public op_dv_vari {
1085  public:
1086  atan2_dv_vari(double a, vari* bvi) :
1087  op_dv_vari(std::atan2(a,bvi->val_),a,bvi) {
1088  }
1089  void chain() {
1090  double a_sq_plus_b_sq = (ad_ * ad_) + (bvi_->val_ * bvi_->val_);
1091  bvi_->adj_ -= ad_ / a_sq_plus_b_sq;
1092  }
1093  };
1094 
1095  class cosh_vari : public op_v_vari {
1096  public:
1097  cosh_vari(vari* avi) :
1098  op_v_vari(std::cosh(avi->val_),avi) {
1099  }
1100  void chain() {
1101  avi_->adj_ += adj_ * std::sinh(avi_->val_);
1102  }
1103  };
1104 
1105  class sinh_vari : public op_v_vari {
1106  public:
1107  sinh_vari(vari* avi) :
1108  op_v_vari(std::sinh(avi->val_),avi) {
1109  }
1110  void chain() {
1111  avi_->adj_ += adj_ * std::cosh(avi_->val_);
1112  }
1113  };
1114 
1115  class tanh_vari : public op_v_vari {
1116  public:
1117  tanh_vari(vari* avi) :
1118  op_v_vari(std::tanh(avi->val_),avi) {
1119  }
1120  void chain() {
1121  double cosh = std::cosh(avi_->val_);
1122  avi_->adj_ += adj_ / (cosh * cosh);
1123  }
1124  };
1125 
1126 
1127  class floor_vari : public vari {
1128  public:
1129  floor_vari(vari* avi) :
1130  vari(std::floor(avi->val_)) {
1131  }
1132  };
1133 
1134  class ceil_vari : public vari {
1135  public:
1136  ceil_vari(vari* avi) :
1137  vari(std::ceil(avi->val_)) {
1138  }
1139  };
1140 
1141  class fmod_vv_vari : public op_vv_vari {
1142  public:
1143  fmod_vv_vari(vari* avi, vari* bvi) :
1144  op_vv_vari(std::fmod(avi->val_,bvi->val_),avi,bvi) {
1145  }
1146  void chain() {
1147  avi_->adj_ += adj_;
1148  bvi_->adj_ -= adj_ * static_cast<int>(avi_->val_ / bvi_->val_);
1149  }
1150  };
1151 
1152  class fmod_vd_vari : public op_v_vari {
1153  public:
1154  fmod_vd_vari(vari* avi, double b) :
1155  op_v_vari(std::fmod(avi->val_,b),avi) {
1156  }
1157  void chain() {
1158  avi_->adj_ += adj_;
1159  }
1160  };
1161 
1162  class fmod_dv_vari : public op_dv_vari {
1163  public:
1164  fmod_dv_vari(double a, vari* bvi) :
1165  op_dv_vari(std::fmod(a,bvi->val_),a,bvi) {
1166  }
1167  void chain() {
1168  int d = static_cast<int>(ad_ / bvi_->val_);
1169  bvi_->adj_ -= adj_ * d;
1170  }
1171  };
1172 
1173 
1174  }
1175 
1176 
1185  template <typename T>
1186  inline double as_double(T x) { return (double)x; }
1187 
1198  template <>
1199  inline double as_double<agrad::var>(agrad::var x) { return x.vi_->val_; }
1200 
1201  // COMPARISON OPERATORS
1202 
1211  inline bool operator==(const var& a, const var& b) {
1212  return a.val() == b.val();
1213  }
1214 
1224  inline bool operator==(const var& a, const double b) {
1225  return a.val() == b;
1226  }
1227 
1236  inline bool operator==(const double a, const var& b) {
1237  return a == b.val();
1238  }
1239 
1248  inline bool operator!=(const var& a, const var& b) {
1249  return a.val() != b.val();
1250  }
1251 
1261  inline bool operator!=(const var& a, const double b) {
1262  return a.val() != b;
1263  }
1264 
1274  inline bool operator!=(const double a, const var& b) {
1275  return a != b.val();
1276  }
1277 
1285  inline bool operator<(const var& a, const var& b) {
1286  return a.val() < b.val();
1287  }
1288 
1297  inline bool operator<(const var& a, const double b) {
1298  return a.val() < b;
1299  }
1300 
1309  inline bool operator<(const double a, const var& b) {
1310  return a < b.val();
1311  }
1312 
1320  inline bool operator>(const var& a, const var& b) {
1321  return a.val() > b.val();
1322  }
1323 
1332  inline bool operator>(const var& a, const double b) {
1333  return a.val() > b;
1334  }
1335 
1344  inline bool operator>(const double a, const var& b) {
1345  return a > b.val();
1346  }
1347 
1357  inline bool operator<=(const var& a, const var& b) {
1358  return a.val() <= b.val();
1359  }
1360 
1370  inline bool operator<=(const var& a, const double b) {
1371  return a.val() <= b;
1372  }
1373 
1383  inline bool operator<=(const double a, const var& b) {
1384  return a <= b.val();
1385  }
1386 
1396  inline bool operator>=(const var& a, const var& b) {
1397  return a.val() >= b.val();
1398  }
1399 
1409  inline bool operator>=(const var& a, const double b) {
1410  return a.val() >= b;
1411  }
1412 
1422  inline bool operator>=(const double a, const var& b) {
1423  return a >= b.val();
1424  }
1425 
1426  // LOGICAL OPERATORS
1427 
1441  inline bool operator!(const var& a) {
1442  return !a.val();
1443  }
1444 
1445 
1446  // ARITHMETIC OPERATORS
1447 
1463  inline var operator+(const var& a) {
1464  return a;
1465  }
1466 
1475  inline var operator-(const var& a) {
1476  return var(new neg_vari(a.vi_));
1477  }
1478 
1492  inline var operator+(const var& a, const var& b) {
1493  return var(new add_vv_vari(a.vi_,b.vi_));
1494  }
1495 
1496 
1508  inline var operator+(const var& a, const double b) {
1509  if (b == 0.0)
1510  return a;
1511  return var(new add_vd_vari(a.vi_,b));
1512  }
1513 
1525  inline var operator+(const double a, const var& b) {
1526  if (a == 0.0)
1527  return b;
1528  return var(new add_vd_vari(b.vi_,a)); // by symmetry
1529  }
1530 
1545  inline var operator-(const var& a, const var& b) {
1546  return var(new subtract_vv_vari(a.vi_,b.vi_));
1547  }
1548 
1560  inline var operator-(const var& a, const double b) {
1561  if (b == 0.0)
1562  return a;
1563  return var(new subtract_vd_vari(a.vi_,b));
1564  }
1565 
1577  inline var operator-(const double a, const var& b) {
1578  return var(new subtract_dv_vari(a,b.vi_));
1579  }
1580 
1594  inline var operator*(const var& a, const var& b) {
1595  return var(new multiply_vv_vari(a.vi_,b.vi_));
1596  }
1597 
1609  inline var operator*(const var& a, const double b) {
1610  if (b == 1.0)
1611  return a;
1612  return var(new multiply_vd_vari(a.vi_,b));
1613  }
1614 
1626  inline var operator*(const double a, const var& b) {
1627  if (a == 1.0)
1628  return b;
1629  return var(new multiply_vd_vari(b.vi_,a)); // by symmetry
1630  }
1631 
1646  inline var operator/(const var& a, const var& b) {
1647  return var(new divide_vv_vari(a.vi_,b.vi_));
1648  }
1649 
1661  inline var operator/(const var& a, const double b) {
1662  if (b == 1.0)
1663  return a;
1664  return var(new divide_vd_vari(a.vi_,b));
1665  }
1666 
1678  inline var operator/(const double a, const var& b) {
1679  return var(new divide_dv_vari(a,b.vi_));
1680  }
1681 
1691  inline var& operator++(var& a) {
1692  a.vi_ = new increment_vari(a.vi_);
1693  return a;
1694  }
1695 
1709  inline var operator++(var& a, int dummy) {
1710  var temp(a);
1711  a.vi_ = new increment_vari(a.vi_);
1712  return temp;
1713  }
1714 
1728  inline var& operator--(var& a) {
1729  a.vi_ = new decrement_vari(a.vi_);
1730  return a;
1731  }
1732 
1746  inline var operator--(var& a, int dummy) {
1747  var temp(a);
1748  a.vi_ = new decrement_vari(a.vi_);
1749  return temp;
1750  }
1751 
1752  // CMATH EXP AND LOG
1753 
1760  inline var exp(const var& a) {
1761  return var(new exp_vari(a.vi_));
1762  }
1763 
1774  inline var log(const var& a) {
1775  return var(new log_vari(a.vi_));
1776  }
1777 
1788  inline var log10(const var& a) {
1789  return var(new log10_vari(a.vi_));
1790  }
1791 
1792 
1793  // POWER FUNCTIONS
1794 
1805  inline var sqrt(const var& a) {
1806  return var(new sqrt_vari(a.vi_));
1807  }
1808 
1822  inline var pow(const var& base, const var& exponent) {
1823  return var(new pow_vv_vari(base.vi_,exponent.vi_));
1824  }
1825 
1838  inline var pow(const var& base, const double exponent) {
1839  if (exponent == 0.5)
1840  return sqrt(base);
1841  if (exponent == 1.0)
1842  return base;
1843  if (exponent == 2.0)
1844  return base * base; // FIXME: square() functionality from special_functions
1845  return var(new pow_vd_vari(base.vi_,exponent));
1846  }
1847 
1860  inline var pow(const double base, const var& exponent) {
1861  return var(new pow_dv_vari(base,exponent.vi_));
1862  }
1863 
1864 
1865  // TRIG FUNCTIONS
1866 
1877  inline var cos(const var& a) {
1878  return var(new cos_vari(a.vi_));
1879  }
1880 
1891  inline var sin(const var& a) {
1892  return var(new sin_vari(a.vi_));
1893  }
1894 
1905  inline var tan(const var& a) {
1906  return var(new tan_vari(a.vi_));
1907  }
1908 
1920  inline var acos(const var& a) {
1921  return var(new acos_vari(a.vi_));
1922  }
1923 
1935  inline var asin(const var& a) {
1936  return var(new asin_vari(a.vi_));
1937  }
1938 
1950  inline var atan(const var& a) {
1951  return var(new atan_vari(a.vi_));
1952  }
1953 
1968  inline var atan2(const var& a, const var& b) {
1969  return var(new atan2_vv_vari(a.vi_,b.vi_));
1970  }
1971 
1984  inline var atan2(const var& a, const double b) {
1985  return var(new atan2_vd_vari(a.vi_,b));
1986  }
1987 
2000  inline var atan2(const double a, const var& b) {
2001  return var(new atan2_dv_vari(a,b.vi_));
2002  }
2003 
2004  // HYPERBOLIC FUNCTIONS
2005 
2016  inline var cosh(const var& a) {
2017  return var(new cosh_vari(a.vi_));
2018  }
2019 
2030  inline var sinh(const var& a) {
2031  return var(new sinh_vari(a.vi_));
2032  }
2033 
2044  inline var tanh(const var& a) {
2045  return var(new tanh_vari(a.vi_));
2046  }
2047 
2048 
2049  // ROUNDING FUNCTIONS
2050 
2067  inline var fabs(const var& a) {
2068  // cut-and-paste from abs()
2069  if (a.val() > 0.0)
2070  return a;
2071  if (a.val() < 0.0)
2072  return var(new neg_vari(a.vi_));
2073  // FIXME: is this right? breaks connection to a
2074  return var(new vari(0.0));
2075  }
2076 
2095  inline var floor(const var& a) {
2096  return var(new floor_vari(a.vi_));
2097  }
2098 
2117  inline var ceil(const var& a) {
2118  return var(new ceil_vari(a.vi_));
2119  }
2120 
2138  inline var fmod(const var& a, const var& b) {
2139  return var(new fmod_vv_vari(a.vi_,b.vi_));
2140  }
2141 
2155  inline var fmod(const var& a, const double b) {
2156  return var(new fmod_vd_vari(a.vi_,b));
2157  }
2158 
2172  inline var fmod(const double a, const var& b) {
2173  return var(new fmod_dv_vari(a,b.vi_));
2174  }
2175 
2176 
2177  // STD LIB FUNCTIONS
2178 
2193  inline var abs(const var& a) {
2194  // cut-and-paste from fabs()
2195  if (a.val() > 0.0)
2196  return a;
2197  if (a.val() < 0.0)
2198  return var(new neg_vari(a.vi_));
2199  // FIXME: same as fabs() -- is this right?
2200  return var(new vari(0.0));
2201  }
2202 
2203 
2207  static void recover_memory() {
2208  var_stack_.resize(0);
2210  }
2211 
2215  static void free_memory() {
2216  memalloc_.free_all();
2217  }
2218 
2231  static void grad(chainable* vi) {
2232  // old with subtle *2 bug
2233  // std::vector<chainable*>::iterator begin = var_stack_.begin();
2234  // std::vector<chainable*>::iterator it = var_stack_.end();
2235  // for (; (it >= begin) && (*it != vi); --it) ;
2236 
2237  std::vector<chainable*>::iterator begin = var_stack_.begin();
2238  std::vector<chainable*>::iterator it = var_stack_.end();
2239  if (begin == it) return; // nothing on stack
2240  for (--it; (it >= begin) && (*it != vi); --it) ;
2241 
2242  vi->init_dependent();
2243  // propagate derivates for remaining vars
2244  for (; it >= begin; --it)
2245  (*it)->chain();
2246  }
2247 
2251  static void set_zero_all_adjoints() {
2252  for (size_t i = 0; i < var_stack_.size(); ++i)
2253  var_stack_[i]->set_zero_adjoint();
2254  }
2255 
2282  inline void jacobian(std::vector<var>& dependents,
2283  std::vector<var>& independents,
2284  std::vector<std::vector<double> >& jacobian) {
2285  jacobian.resize(dependents.size());
2286  for (size_t i = 0; i < dependents.size(); ++i) {
2287  jacobian[i].resize(independents.size());
2288  if (i > 0)
2290  jacobian.push_back(std::vector<double>(0));
2291  grad(dependents[i].vi_);
2292  for (size_t j = 0; j < independents.size(); ++j)
2293  jacobian[i][j] = independents[j].adj();
2294  }
2295  }
2296 
2297 
2298  inline var& var::operator+=(const var& b) {
2299  vi_ = new add_vv_vari(vi_,b.vi_);
2300  return *this;
2301  }
2302 
2303  inline var& var::operator+=(const double b) {
2304  if (b == 0.0)
2305  return *this;
2306  vi_ = new add_vd_vari(vi_,b);
2307  return *this;
2308  }
2309 
2310  inline var& var::operator-=(const var& b) {
2311  vi_ = new subtract_vv_vari(vi_,b.vi_);
2312  return *this;
2313  }
2314 
2315  inline var& var::operator-=(const double b) {
2316  if (b == 0.0)
2317  return *this;
2318  vi_ = new subtract_vd_vari(vi_,b);
2319  return *this;
2320  }
2321 
2322  inline var& var::operator*=(const var& b) {
2323  vi_ = new multiply_vv_vari(vi_,b.vi_);
2324  return *this;
2325  }
2326 
2327  inline var& var::operator*=(const double b) {
2328  if (b == 1.0)
2329  return *this;
2330  vi_ = new multiply_vd_vari(vi_,b);
2331  return *this;
2332  }
2333 
2334  inline var& var::operator/=(const var& b) {
2335  vi_ = new divide_vv_vari(vi_,b.vi_);
2336  return *this;
2337  }
2338 
2339  inline var& var::operator/=(const double b) {
2340  if (b == 1.0)
2341  return *this;
2342  vi_ = new divide_vd_vari(vi_,b);
2343  return *this;
2344  }
2345  }
2346 
2347 }
2348 
2349 
2350 namespace std {
2351 
2358  template<>
2359  struct numeric_limits<stan::agrad::var> {
2360  static const bool is_specialized = true;
2363  static const int digits = numeric_limits<double>::digits;
2364  static const int digits10 = numeric_limits<double>::digits10;
2365  static const bool is_signed = numeric_limits<double>::is_signed;
2366  static const bool is_integer = numeric_limits<double>::is_integer;
2367  static const bool is_exact = numeric_limits<double>::is_exact;
2368  static const int radix = numeric_limits<double>::radix;
2370  static stan::agrad::var round_error() { return numeric_limits<double>::round_error(); }
2371 
2372  static const int min_exponent = numeric_limits<double>::min_exponent;
2373  static const int min_exponent10 = numeric_limits<double>::min_exponent10;
2374  static const int max_exponent = numeric_limits<double>::max_exponent;
2375  static const int max_exponent10 = numeric_limits<double>::max_exponent10;
2376 
2377  static const bool has_infinity = numeric_limits<double>::has_infinity;
2378  static const bool has_quiet_NaN = numeric_limits<double>::has_quiet_NaN;
2379  static const bool has_signaling_NaN = numeric_limits<double>::has_signaling_NaN;
2380  static const float_denorm_style has_denorm = numeric_limits<double>::has_denorm;
2381  static const bool has_denorm_loss = numeric_limits<double>::has_denorm_loss;
2382  static stan::agrad::var infinity() { return numeric_limits<double>::infinity(); }
2383  static stan::agrad::var quiet_NaN() { return numeric_limits<double>::quiet_NaN(); }
2384  static stan::agrad::var signaling_NaN() { return numeric_limits<double>::signaling_NaN(); }
2385  static stan::agrad::var denorm_min() { return numeric_limits<double>::denorm_min(); }
2386 
2387  static const bool is_iec559 = numeric_limits<double>::is_iec559;
2388  static const bool is_bounded = numeric_limits<double>::is_bounded;
2389  static const bool is_modulo = numeric_limits<double>::is_modulo;
2390 
2391  static const bool traps = numeric_limits<double>::traps;
2392  static const bool tinyness_before = numeric_limits<double>::tinyness_before;
2393  static const float_round_style round_style = numeric_limits<double>::round_style;
2394  };
2395 
2405  inline int isnan(const stan::agrad::var& a) {
2406  return isnan(a.val());
2407  }
2408 
2418  inline int isinf(const stan::agrad::var& a) {
2419  return isinf(a.val());
2420  }
2421 
2422 }
2423 
2424 #endif

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