Stan  1.0
probability, sampling & optimization
 All Classes Namespaces Files Functions Variables Typedefs Enumerator Friends Macros Pages
agrad_thread_safe.hpp
Go to the documentation of this file.
1 #ifndef __STAN__AGRAD__AGRAD__H__
2 #define __STAN__AGRAD__AGRAD__H__
3 
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <vector>
7 #include <cmath>
8 #include <cstddef>
10 
11 
12 namespace stan {
13 
14  namespace agrad {
15 
16  class vari;
17 
18  namespace {
19  struct var_allocator {
20  std::vector<vari*> var_stack_;
21  memory::stack_alloc memalloc_;
22  inline void* alloc(size_t nbytes) {
23  return memalloc_.alloc(nbytes);
24  }
25  inline void recover() {
26  var_stack_.resize(0);
28  }
29  inline void free() {
31  }
32  };
33 #ifdef AGRAD_THREAD_SAFE
34  __thread
35 #endif
36  var_allocator* allocator_;
37  }
38 
52  class vari {
53  private:
54  friend class var;
55 
56  public:
57 
61  const double val_;
62 
67  double adj_;
68 
81  vari(const double x):
82  val_(x),
83  adj_(0.0) {
84  allocator_->var_stack_.push_back(this);
85  }
86 
92  virtual void chain() {
93  }
94 
104  static inline void* operator new(size_t nbytes) {
105  if (allocator_ == 0)
106  allocator_ = new var_allocator();
107  return allocator_->alloc(nbytes);
108  }
109 
113  static void recover_memory() {
114  return allocator_->recover();
115  // allocator_.var_stack_.resize(0);
116  // allocator_.memalloc_.recover_all();
117  }
118 
122  static void free_memory() {
123  allocator_->free();
124  // allocator_.memalloc_.free_all();
125  }
126 
127  private:
136  static void grad(vari* vi) {
137  std::vector<vari*>::iterator it = allocator_->var_stack_.end();
138  std::vector<vari*>::iterator begin = allocator_->var_stack_.begin();
139  // skip to root variable
140  for (; (it >= begin) && (*it != vi); --it)
141  ;
142  vi->adj_ = 1.0; // droot/droot = 1
143  // propagate derivates for remaining vars
144  for (; it >= begin; --it)
145  (*it)->chain();
146  }
147 
148  };
149 
150  namespace {
151 
152  class op_v_vari : public vari {
153  protected:
154  vari* avi_;
155  public:
156  op_v_vari(double f, vari* avi) :
157  vari(f),
158  avi_(avi) {
159  }
160  };
161 
162  class op_vv_vari : public vari {
163  protected:
164  vari* avi_;
165  vari* bvi_;
166  public:
167  op_vv_vari(double f, vari* avi, vari* bvi):
168  vari(f),
169  avi_(avi),
170  bvi_(bvi) {
171  }
172  };
173 
174  class op_vd_vari : public vari {
175  protected:
176  vari* avi_;
177  double bd_;
178  public:
179  op_vd_vari(double f, vari* avi, double b) :
180  vari(f),
181  avi_(avi),
182  bd_(b) {
183  }
184  };
185 
186  class op_dv_vari : public vari {
187  protected:
188  double ad_;
189  vari* bvi_;
190  public:
191  op_dv_vari(double f, double a, vari* bvi) :
192  vari(f),
193  ad_(a),
194  bvi_(bvi) {
195  }
196  };
197 
198  class op_vvv_vari : public vari {
199  protected:
200  vari* avi_;
201  vari* bvi_;
202  vari* cvi_;
203  public:
204  op_vvv_vari(double f, vari* avi, vari* bvi, vari* cvi) :
205  vari(f),
206  avi_(avi),
207  bvi_(bvi),
208  cvi_(cvi) {
209  }
210  };
211 
212  class op_vvd_vari : public vari {
213  protected:
214  vari* avi_;
215  vari* bvi_;
216  double cd_;
217  public:
218  op_vvd_vari(double f, vari* avi, vari* bvi, double c) :
219  vari(f),
220  avi_(avi),
221  bvi_(bvi),
222  cd_(c) {
223  }
224  };
225 
226  class op_vdv_vari : public vari {
227  protected:
228  vari* avi_;
229  double bd_;
230  vari* cvi_;
231  public:
232  op_vdv_vari(double f, vari* avi, double b, vari* cvi) :
233  vari(f),
234  avi_(avi),
235  bd_(b),
236  cvi_(cvi) {
237  }
238  };
239 
240  class op_vdd_vari : public vari {
241  protected:
242  vari* avi_;
243  double bd_;
244  double cd_;
245  public:
246  op_vdd_vari(double f, vari* avi, double b, double c) :
247  vari(f),
248  avi_(avi),
249  bd_(b),
250  cd_(c) {
251  }
252  };
253 
254  class op_dvv_vari : public vari {
255  protected:
256  double ad_;
257  vari* bvi_;
258  vari* cvi_;
259  public:
260  op_dvv_vari(double f, double a, vari* bvi, vari* cvi) :
261  vari(f),
262  ad_(a),
263  bvi_(bvi),
264  cvi_(cvi) {
265  }
266  };
267 
268  class op_dvd_vari : public vari {
269  protected:
270  double ad_;
271  vari* bvi_;
272  double cd_;
273  public:
274  op_dvd_vari(double f, double a, vari* bvi, double c) :
275  vari(f),
276  ad_(a),
277  bvi_(bvi),
278  cd_(c) {
279  }
280  };
281 
282  class op_ddv_vari : public vari {
283  protected:
284  double ad_;
285  double bd_;
286  vari* cvi_;
287  public:
288  op_ddv_vari(double f, double a, double b, vari* cvi) :
289  vari(f),
290  ad_(a),
291  bd_(b),
292  cvi_(cvi) {
293  }
294  };
295 
296  class neg_vari : public op_v_vari {
297  public:
298  neg_vari(vari* avi) :
299  op_v_vari(-(avi->val_), avi) {
300  }
301  void chain() {
302  avi_->adj_ -= adj_;
303  }
304  };
305 
306 
307  class add_vv_vari : public op_vv_vari {
308  public:
309  add_vv_vari(vari* avi, vari* bvi) :
310  op_vv_vari(avi->val_ + bvi->val_, avi, bvi) {
311  }
312  void chain() {
313  avi_->adj_ += adj_;
314  bvi_->adj_ += adj_;
315  }
316  };
317 
318  class add_vd_vari : public op_vd_vari {
319  public:
320  add_vd_vari(vari* avi, double b) :
321  op_vd_vari(avi->val_ + b, avi, b) {
322  }
323  void chain() {
324  avi_->adj_ += adj_;
325  }
326  };
327 
328  class increment_vari : public op_v_vari {
329  public:
330  increment_vari(vari* avi) :
331  op_v_vari(avi->val_ + 1.0, avi) {
332  }
333  void chain() {
334  avi_->adj_ += adj_;
335  }
336  };
337 
338  class decrement_vari : public op_v_vari {
339  public:
340  decrement_vari(vari* avi) :
341  op_v_vari(avi->val_ - 1.0, avi) {
342  }
343  void chain() {
344  avi_->adj_ += adj_;
345  }
346  };
347 
348  class subtract_vv_vari : public op_vv_vari {
349  public:
350  subtract_vv_vari(vari* avi, vari* bvi) :
351  op_vv_vari(avi->val_ - bvi->val_, avi, bvi) {
352  }
353  void chain() {
354  avi_->adj_ += adj_;
355  bvi_->adj_ -= adj_;
356  }
357  };
358 
359  class subtract_vd_vari : public op_vd_vari {
360  public:
361  subtract_vd_vari(vari* avi, double b) :
362  op_vd_vari(avi->val_ - b, avi, b) {
363  }
364  void chain() {
365  avi_->adj_ += adj_;
366  }
367  };
368 
369  class subtract_dv_vari : public op_dv_vari {
370  public:
371  subtract_dv_vari(double a, vari* bvi) :
372  op_dv_vari(a - bvi->val_, a, bvi) {
373  }
374  void chain() {
375  bvi_->adj_ -= adj_;
376  }
377  };
378 
379  class multiply_vv_vari : public op_vv_vari {
380  public:
381  multiply_vv_vari(vari* avi, vari* bvi) :
382  op_vv_vari(avi->val_ * bvi->val_, avi, bvi) {
383  }
384  void chain() {
385  avi_->adj_ += bvi_->val_ * adj_;
386  bvi_->adj_ += avi_->val_ * adj_;
387  }
388  };
389 
390  class multiply_vd_vari : public op_vd_vari {
391  public:
392  multiply_vd_vari(vari* avi, double b) :
393  op_vd_vari(avi->val_ * b, avi, b) {
394  }
395  void chain() {
396  avi_->adj_ += adj_ * bd_;
397  }
398  };
399 
400  // (a/b)' = a' * (1 / b) - b' * (a / [b * b])
401  class divide_vv_vari : public op_vv_vari {
402  public:
403  divide_vv_vari(vari* avi, vari* bvi) :
404  op_vv_vari(avi->val_ / bvi->val_, avi, bvi) {
405  }
406  void chain() {
407  avi_->adj_ += adj_ / bvi_->val_;
408  bvi_->adj_ -= adj_ * avi_->val_ / (bvi_->val_ * bvi_->val_);
409  }
410  };
411 
412  class divide_vd_vari : public op_vd_vari {
413  public:
414  divide_vd_vari(vari* avi, double b) :
415  op_vd_vari(avi->val_ / b, avi, b) {
416  }
417  void chain() {
418  avi_->adj_ += adj_ / bd_;
419  }
420  };
421 
422  class divide_dv_vari : public op_dv_vari {
423  public:
424  divide_dv_vari(double a, vari* bvi) :
425  op_dv_vari(a / bvi->val_, a, bvi) {
426  }
427  void chain() {
428  bvi_->adj_ -= adj_ * ad_ / (bvi_->val_ * bvi_->val_);
429  }
430  };
431 
432  class exp_vari : public op_v_vari {
433  public:
434  exp_vari(vari* avi) :
435  op_v_vari(std::exp(avi->val_),avi) {
436  }
437  void chain() {
438  avi_->adj_ += adj_ * val_;
439  }
440  };
441 
442  class log_vari : public op_v_vari {
443  public:
444  log_vari(vari* avi) :
445  op_v_vari(std::log(avi->val_),avi) {
446  }
447  void chain() {
448  avi_->adj_ += adj_ / avi_->val_;
449  }
450  };
451 
452  double LOG_10 = std::log(10.0);
453 
454  class log10_vari : public op_v_vari {
455  public:
456  const double exp_val_;
457  log10_vari(vari* avi) :
458  op_v_vari(std::log10(avi->val_),avi),
459  exp_val_(avi->val_) {
460  }
461  void chain() {
462  avi_->adj_ += adj_ / (LOG_10 * exp_val_);
463  }
464  };
465 
466  class sqrt_vari : public op_v_vari {
467  public:
468  sqrt_vari(vari* avi) :
469  op_v_vari(std::sqrt(avi->val_),avi) {
470  }
471  void chain() {
472  avi_->adj_ += adj_ / (2.0 * val_);
473  }
474  };
475 
476  class pow_vv_vari : public op_vv_vari {
477  public:
478  pow_vv_vari(vari* avi, vari* bvi) :
479  op_vv_vari(std::pow(avi->val_,bvi->val_),avi,bvi) {
480  }
481  void chain() {
482  if (avi_->val_ == 0.0) return; // partials zero, avoids /0 & log(0)
483  avi_->adj_ += adj_ * bvi_->val_ * val_ / avi_->val_;
484  bvi_->adj_ += adj_ * std::log(avi_->val_) * val_;
485  }
486  };
487 
488  class pow_vd_vari : public op_vd_vari {
489  public:
490  pow_vd_vari(vari* avi, double b) :
491  op_vd_vari(std::pow(avi->val_,b),avi,b) {
492  }
493  void chain() {
494  if (avi_->val_ == 0.0) return; // partials zero, avoids /0 & log(0)
495  avi_->adj_ += adj_ * bd_ * val_ / avi_->val_;
496  }
497  };
498 
499  class pow_dv_vari : public op_dv_vari {
500  public:
501  pow_dv_vari(double a, vari* bvi) :
502  op_dv_vari(std::pow(a,bvi->val_),a,bvi) {
503  }
504  void chain() {
505  if (ad_ == 0.0) return; // partials zero, avoids /0 & log(0)
506  bvi_->adj_ += adj_ * std::log(ad_) * val_;
507  }
508  };
509 
510  class cos_vari : public op_v_vari {
511  public:
512  cos_vari(vari* avi) :
513  op_v_vari(std::cos(avi->val_),avi) {
514  }
515  void chain() {
516  avi_->adj_ -= adj_ * std::sin(avi_->val_);
517  }
518  };
519 
520  class sin_vari : public op_v_vari {
521  public:
522  sin_vari(vari* avi) :
523  op_v_vari(std::sin(avi->val_),avi) {
524  }
525  void chain() {
526  avi_->adj_ += adj_ * std::cos(avi_->val_);
527  }
528  };
529 
530  class tan_vari : public op_v_vari {
531  public:
532  tan_vari(vari* avi) :
533  op_v_vari(std::tan(avi->val_),avi) {
534  }
535  void chain() {
536  avi_->adj_ += adj_ * (1.0 + val_ * val_);
537  }
538  };
539 
540  class acos_vari : public op_v_vari {
541  public:
542  acos_vari(vari* avi) :
543  op_v_vari(std::acos(avi->val_),avi) {
544  }
545  void chain() {
546  avi_->adj_ -= adj_ / std::sqrt(1.0 - (avi_->val_ * avi_->val_));
547  }
548  };
549 
550  class asin_vari : public op_v_vari {
551  public:
552  asin_vari(vari* avi) :
553  op_v_vari(std::asin(avi->val_),avi) {
554  }
555  void chain() {
556  avi_->adj_ += adj_ / std::sqrt(1.0 - (avi_->val_ * avi_->val_));
557  }
558  };
559 
560  class atan_vari : public op_v_vari {
561  public:
562  atan_vari(vari* avi) :
563  op_v_vari(std::atan(avi->val_),avi) {
564  }
565  void chain() {
566  avi_->adj_ += adj_ / (1.0 + (avi_->val_ * avi_->val_));
567  }
568  };
569 
570  class atan2_vv_vari : public op_vv_vari {
571  public:
572  atan2_vv_vari(vari* avi, vari* bvi) :
573  op_vv_vari(std::atan2(avi->val_,bvi->val_),avi,bvi) {
574  }
575  void chain() {
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;
579  }
580  };
581 
582  class atan2_vd_vari : public op_vd_vari {
583  public:
584  atan2_vd_vari(vari* avi, double b) :
585  op_vd_vari(std::atan2(avi->val_,b),avi,b) {
586  }
587  void chain() {
588  double a_sq_plus_b_sq = (avi_->val_ * avi_->val_) + (bd_ * bd_);
589  avi_->adj_ += bd_ / a_sq_plus_b_sq;
590  }
591  };
592 
593  class atan2_dv_vari : public op_dv_vari {
594  public:
595  atan2_dv_vari(double a, vari* bvi) :
596  op_dv_vari(std::atan2(a,bvi->val_),a,bvi) {
597  }
598  void chain() {
599  double a_sq_plus_b_sq = (ad_ * ad_) + (bvi_->val_ * bvi_->val_);
600  bvi_->adj_ -= ad_ / a_sq_plus_b_sq;
601  }
602  };
603 
604  class cosh_vari : public op_v_vari {
605  public:
606  cosh_vari(vari* avi) :
607  op_v_vari(std::cosh(avi->val_),avi) {
608  }
609  void chain() {
610  avi_->adj_ += adj_ * std::sinh(avi_->val_);
611  }
612  };
613 
614  class sinh_vari : public op_v_vari {
615  public:
616  sinh_vari(vari* avi) :
617  op_v_vari(std::sinh(avi->val_),avi) {
618  }
619  void chain() {
620  avi_->adj_ += adj_ * std::cosh(avi_->val_);
621  }
622  };
623 
624  class tanh_vari : public op_v_vari {
625  public:
626  tanh_vari(vari* avi) :
627  op_v_vari(std::tanh(avi->val_),avi) {
628  }
629  void chain() {
630  double cosh = std::cosh(avi_->val_);
631  avi_->adj_ += adj_ / (cosh * cosh);
632  }
633  };
634 
635 
636  class floor_vari : public vari {
637  public:
638  floor_vari(vari* avi) :
639  vari(std::floor(avi->val_)) {
640  }
641  };
642 
643  class ceil_vari : public vari {
644  public:
645  ceil_vari(vari* avi) :
646  vari(std::ceil(avi->val_)) {
647  }
648  };
649 
650  class fmod_vv_vari : public op_vv_vari {
651  public:
652  fmod_vv_vari(vari* avi, vari* bvi) :
653  op_vv_vari(std::fmod(avi->val_,bvi->val_),avi,bvi) {
654  }
655  void chain() {
656  avi_->adj_ += adj_;
657  bvi_->adj_ -= adj_ * static_cast<int>(avi_->val_ / bvi_->val_);
658  }
659  };
660 
661  class fmod_vd_vari : public op_v_vari {
662  public:
663  fmod_vd_vari(vari* avi, double b) :
664  op_v_vari(std::fmod(avi->val_,b),avi) {
665  }
666  void chain() {
667  avi_->adj_ += adj_;
668  }
669  };
670 
671  class fmod_dv_vari : public op_dv_vari {
672  public:
673  fmod_dv_vari(double a, vari* bvi) :
674  op_dv_vari(std::fmod(a,bvi->val_),a,bvi) {
675  }
676  void chain() {
677  int d = static_cast<int>(ad_ / bvi_->val_);
678  bvi_->adj_ -= adj_ * d;
679  }
680  };
681 
682 
683 
684 
685 
686  }
687 
688  // ********************* vari UP, var DOWN ***********************************************************
689 
690 
700  class var {
701  public:
702 
703  typedef double Scalar;
704 
712  vari * vi_;
713 
719  explicit var(vari* vi) :
720  vi_(vi) {
721  }
722 
730  var() {
731  }
732 
739  var(bool b) :
740  vi_(new vari(static_cast<double>(b))) {
741  }
742 
749  var(char c) :
750  vi_(new vari(static_cast<double>(c))) {
751  }
752 
759  var(short n) :
760  vi_(new vari(static_cast<double>(n))) {
761  }
762 
769  var(unsigned short n) :
770  vi_(new vari(static_cast<double>(n))) {
771  }
772 
779  var(int n) :
780  vi_(new vari(static_cast<double>(n))) {
781  }
782 
789  var(unsigned int n) :
790  vi_(new vari(static_cast<double>(n))) {
791  }
792 
799  var(long int n) :
800  vi_(new vari(static_cast<double>(n))) {
801  }
802 
809  var(unsigned long int n) :
810  vi_(new vari(static_cast<double>(n))) {
811  }
812 
819  var(float x) :
820  vi_(new vari(static_cast<double>(x))) {
821  }
822 
828  var(double x) :
829  vi_(new vari(x)) {
830  }
831 
838  var(long double x) :
839  vi_(new vari(static_cast<double>(x))) {
840  }
841 
847  inline double val() const {
848  return vi_->val_;
849  }
850 
863  void grad(std::vector<var>& x,
864  std::vector<double>& g) {
865  vari::grad(vi_);
866  g.resize(0);
867  for (size_t i = 0U; i < x.size(); ++i)
868  g.push_back(x[i].vi_->adj_);
870  }
871 
888  void grad() {
889  vari::grad(vi_);
891  }
892 
893  // COMPOUND ASSIGNMENT OPERATORS
894 
905  inline var& operator+=(const var& b) {
906  vi_ = new add_vv_vari(vi_,b.vi_);
907  return *this;
908  }
909 
920  inline var& operator+=(const double& b) {
921  vi_ = new add_vd_vari(vi_,b);
922  return *this;
923  }
924 
936  inline var& operator-=(const var& b) {
937  vi_ = new subtract_vv_vari(vi_,b.vi_);
938  return *this;
939  }
940 
952  inline var& operator-=(const double& b) {
953  vi_ = new subtract_vd_vari(vi_,b);
954  return *this;
955  }
956 
968  inline var& operator*=(const var& b) {
969  vi_ = new multiply_vv_vari(vi_,b.vi_);
970  return *this;
971  }
972 
984  inline var& operator*=(const double& b) {
985  vi_ = new multiply_vd_vari(vi_,b);
986  return *this;
987  }
988 
999  inline var& operator/=(const var& b) {
1000  vi_ = new divide_vv_vari(vi_,b.vi_);
1001  return *this;
1002  }
1003 
1015  inline var& operator/=(const double& b) {
1016  vi_ = new divide_vd_vari(vi_,b);
1017  return *this;
1018  };
1019 
1020 
1021  };
1022 
1023  // COMPARISON OPERATORS
1024 
1033  inline bool operator==(const var& a, const var& b) {
1034  return a.val() == b.val();
1035  }
1036 
1046  inline bool operator==(const var& a, const double& b) {
1047  return a.val() == b;
1048  }
1049 
1058  inline bool operator==(const double& a, const var& b) {
1059  return a == b.val();
1060  }
1061 
1070  inline bool operator!=(const var& a, const var& b) {
1071  return a.val() != b.val();
1072  }
1073 
1083  inline bool operator!=(const var& a, const double& b) {
1084  return a.val() != b;
1085  }
1086 
1096  inline bool operator!=(const double& a, const var& b) {
1097  return a != b.val();
1098  }
1099 
1107  inline bool operator<(const var& a, const var& b) {
1108  return a.val() < b.val();
1109  }
1110 
1119  inline bool operator<(const var& a, const double& b) {
1120  return a.val() < b;
1121  }
1122 
1131  inline bool operator<(const double& a, const var& b) {
1132  return a < b.val();
1133  }
1134 
1142  inline bool operator>(const var& a, const var& b) {
1143  return a.val() > b.val();
1144  }
1145 
1154  inline bool operator>(const var& a, const double& b) {
1155  return a.val() > b;
1156  }
1157 
1166  inline bool operator>(const double& a, const var& b) {
1167  return a > b.val();
1168  }
1169 
1179  inline bool operator<=(const var& a, const var& b) {
1180  return a.val() <= b.val();
1181  }
1182 
1192  inline bool operator<=(const var& a, const double& b) {
1193  return a.val() <= b;
1194  }
1195 
1205  inline bool operator<=(const double& a, const var& b) {
1206  return a <= b.val();
1207  }
1208 
1218  inline bool operator>=(const var& a, const var& b) {
1219  return a.val() >= b.val();
1220  }
1221 
1231  inline bool operator>=(const var& a, const double& b) {
1232  return a.val() >= b;
1233  }
1234 
1244  inline bool operator>=(const double& a, const var& b) {
1245  return a >= b.val();
1246  }
1247 
1248  // LOGICAL OPERATORS
1249 
1263  inline bool operator!(const var& a) {
1264  return !a.val();
1265  }
1266 
1267  // ARITHMETIC OPERATORS
1268 
1284  inline var operator+(const var& a) {
1285  return a;
1286  }
1287 
1296  inline var operator-(const var& a) {
1297  return var(new neg_vari(a.vi_));
1298  }
1299 
1313  inline var operator+(const var& a, const var& b) {
1314  return var(new add_vv_vari(a.vi_,b.vi_));
1315  }
1316 
1317 
1329  inline var operator+(const var& a, const double& b) {
1330  return var(new add_vd_vari(a.vi_,b));
1331  }
1332 
1344  inline var operator+(const double& a, const var& b) {
1345  return var(new add_vd_vari(b.vi_,a)); // by symmetry
1346  }
1347 
1362  inline var operator-(const var& a, const var& b) {
1363  return var(new subtract_vv_vari(a.vi_,b.vi_));
1364  }
1365 
1377  inline var operator-(const var& a, const double& b) {
1378  return var(new subtract_vd_vari(a.vi_,b));
1379  }
1380 
1392  inline var operator-(const double& a, const var& b) {
1393  return var(new subtract_dv_vari(a,b.vi_));
1394  }
1395 
1409  inline var operator*(const var& a, const var& b) {
1410  return var(new multiply_vv_vari(a.vi_,b.vi_));
1411  }
1412 
1424  inline var operator*(const var& a, const double& b) {
1425  return var(new multiply_vd_vari(a.vi_,b));
1426  }
1427 
1439  inline var operator*(const double& a, const var& b) {
1440  return var(new multiply_vd_vari(b.vi_,a)); // by symmetry
1441  }
1442 
1457  inline var operator/(const var& a, const var& b) {
1458  return var(new divide_vv_vari(a.vi_,b.vi_));
1459  }
1460 
1472  inline var operator/(const var& a, const double& b) {
1473  return var(new divide_vd_vari(a.vi_,b));
1474  }
1475 
1487  inline var operator/(const double& a, const var& b) {
1488  return var(new divide_dv_vari(a,b.vi_));
1489  }
1490 
1500  inline var& operator++(var& a) {
1501  a.vi_ = new increment_vari(a.vi_);
1502  return a;
1503  }
1504 
1518  inline var operator++(var& a, int dummy) {
1519  var temp(a);
1520  a.vi_ = new increment_vari(a.vi_);
1521  return temp;
1522  }
1523 
1537  inline var& operator--(var& a) {
1538  a.vi_ = new decrement_vari(a.vi_);
1539  return a;
1540  }
1541 
1555  inline var operator--(var& a, int dummy) {
1556  var temp(a);
1557  a.vi_ = new decrement_vari(a.vi_);
1558  return temp;
1559  }
1560 
1561  // CMATH EXP AND LOG
1562 
1569  inline var exp(const var& a) {
1570  return var(new exp_vari(a.vi_));
1571  }
1572 
1583  inline var log(const var& a) {
1584  return var(new log_vari(a.vi_));
1585  }
1586 
1597  inline var log10(const var& a) {
1598  return var(new log10_vari(a.vi_));
1599  }
1600 
1601 
1602  // POWER FUNCTIONS
1603 
1614  inline var sqrt(const var& a) {
1615  return var(new sqrt_vari(a.vi_));
1616  }
1617 
1631  inline var pow(const var& base, const var& exponent) {
1632  return var(new pow_vv_vari(base.vi_,exponent.vi_));
1633  }
1634 
1647  inline var pow(const var& base, const double& exponent) {
1648  return var(new pow_vd_vari(base.vi_,exponent));
1649  }
1650 
1663  inline var pow(const double& base, const var& exponent) {
1664  return var(new pow_dv_vari(base,exponent.vi_));
1665  }
1666 
1667 
1668  // TRIG FUNCTIONS
1669 
1680  inline var cos(const var& a) {
1681  return var(new cos_vari(a.vi_));
1682  }
1683 
1694  inline var sin(const var& a) {
1695  return var(new sin_vari(a.vi_));
1696  }
1697 
1708  inline var tan(const var& a) {
1709  return var(new tan_vari(a.vi_));
1710  }
1711 
1723  inline var acos(const var& a) {
1724  return var(new acos_vari(a.vi_));
1725  }
1726 
1738  inline var asin(const var& a) {
1739  return var(new asin_vari(a.vi_));
1740  }
1741 
1753  inline var atan(const var& a) {
1754  return var(new atan_vari(a.vi_));
1755  }
1756 
1772  inline var atan2(const var& a, const var& b) {
1773  return var(new atan2_vv_vari(a.vi_,b.vi_));
1774  }
1775 
1788  inline var atan2(const var& a, const double& b) {
1789  return var(new atan2_vd_vari(a.vi_,b));
1790  }
1791 
1804  inline var atan2(const double& a, const var& b) {
1805  return var(new atan2_dv_vari(a,b.vi_));
1806  }
1807 
1808  // HYPERBOLIC FUNCTIONS
1809 
1820  inline var cosh(const var& a) {
1821  return var(new cosh_vari(a.vi_));
1822  }
1823 
1834  inline var sinh(const var& a) {
1835  return var(new sinh_vari(a.vi_));
1836  }
1837 
1848  inline var tanh(const var& a) {
1849  return var(new tanh_vari(a.vi_));
1850  }
1851 
1852 
1853  // ROUNDING FUNCTIONS
1854 
1871  inline var fabs(const var& a) {
1872  // cut-and-paste from abs()
1873  if (a.val() > 0.0)
1874  return a;
1875  if (a.val() < 0.0)
1876  return var(new neg_vari(a.vi_));
1877  return var(new vari(0.0));
1878  }
1879 
1898  inline var floor(const var& a) {
1899  return var(new floor_vari(a.vi_));
1900  }
1901 
1920  inline var ceil(const var& a) {
1921  return var(new ceil_vari(a.vi_));
1922  }
1923 
1941  inline var fmod(const var& a, const var& b) {
1942  return var(new fmod_vv_vari(a.vi_,b.vi_));
1943  }
1944 
1958  inline var fmod(const var& a, const double& b) {
1959  return var(new fmod_vd_vari(a.vi_,b));
1960  }
1961 
1975  inline var fmod(const double& a, const var& b) {
1976  return var(new fmod_dv_vari(a,b.vi_));
1977  }
1978 
1979 
1980  // STD LIB FUNCTIONS
1981 
1996  inline var abs(const var& a) {
1997  // cut-and-paste from fabs()
1998  if (a.val() > 0.0)
1999  return a;
2000  if (a.val() < 0.0)
2001  return var(new neg_vari(a.vi_));
2002  return var(new vari(0.0));
2003  }
2004 
2005  }
2006 
2007 }
2008 
2009 #endif

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