Stan  1.3
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_HPP__
2 #define __STAN__AGRAD__AGRAD_HPP__
3 
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <vector>
7 #include <cmath>
8 #include <cstddef>
10 
11 // FIXME: Should include common defs, not this huge cut-and-paste!
12 
13 namespace stan {
14 
15  namespace agrad {
16 
17  class vari;
18 
19  namespace {
20  struct var_allocator {
21  std::vector<vari*> var_stack_;
22  memory::stack_alloc memalloc_;
23  inline void* alloc(size_t nbytes) {
24  return memalloc_.alloc(nbytes);
25  }
26  inline void recover() {
27  var_stack_.resize(0);
29  }
30  inline void free() {
32  }
33  };
34 #ifdef AGRAD_THREAD_SAFE
35  __thread
36 #endif
37  var_allocator* allocator_;
38  }
39 
53  class vari {
54  private:
55  friend class var;
56 
57  public:
58 
62  const double val_;
63 
68  double adj_;
69 
82  vari(const double x):
83  val_(x),
84  adj_(0.0) {
85  allocator_->var_stack_.push_back(this);
86  }
87 
93  virtual void chain() {
94  }
95 
105  static inline void* operator new(size_t nbytes) {
106  if (allocator_ == 0)
107  allocator_ = new var_allocator();
108  return allocator_->alloc(nbytes);
109  }
110 
114  static void recover_memory() {
115  return allocator_->recover();
116  // allocator_.var_stack_.resize(0);
117  // allocator_.memalloc_.recover_all();
118  }
119 
123  static void free_memory() {
124  allocator_->free();
125  // allocator_.memalloc_.free_all();
126  }
127 
128  private:
137  static void grad(vari* vi) {
138  std::vector<vari*>::iterator it = allocator_->var_stack_.end();
139  std::vector<vari*>::iterator begin = allocator_->var_stack_.begin();
140  // skip to root variable
141  for (; (it >= begin) && (*it != vi); --it)
142  ;
143  vi->adj_ = 1.0; // droot/droot = 1
144  // propagate derivates for remaining vars
145  for (; it >= begin; --it)
146  (*it)->chain();
147  }
148 
149  };
150 
151  namespace {
152 
153  class op_v_vari : public vari {
154  protected:
155  vari* avi_;
156  public:
157  op_v_vari(double f, vari* avi) :
158  vari(f),
159  avi_(avi) {
160  }
161  };
162 
163  class op_vv_vari : public vari {
164  protected:
165  vari* avi_;
166  vari* bvi_;
167  public:
168  op_vv_vari(double f, vari* avi, vari* bvi):
169  vari(f),
170  avi_(avi),
171  bvi_(bvi) {
172  }
173  };
174 
175  class op_vd_vari : public vari {
176  protected:
177  vari* avi_;
178  double bd_;
179  public:
180  op_vd_vari(double f, vari* avi, double b) :
181  vari(f),
182  avi_(avi),
183  bd_(b) {
184  }
185  };
186 
187  class op_dv_vari : public vari {
188  protected:
189  double ad_;
190  vari* bvi_;
191  public:
192  op_dv_vari(double f, double a, vari* bvi) :
193  vari(f),
194  ad_(a),
195  bvi_(bvi) {
196  }
197  };
198 
199  class op_vvv_vari : public vari {
200  protected:
201  vari* avi_;
202  vari* bvi_;
203  vari* cvi_;
204  public:
205  op_vvv_vari(double f, vari* avi, vari* bvi, vari* cvi) :
206  vari(f),
207  avi_(avi),
208  bvi_(bvi),
209  cvi_(cvi) {
210  }
211  };
212 
213  class op_vvd_vari : public vari {
214  protected:
215  vari* avi_;
216  vari* bvi_;
217  double cd_;
218  public:
219  op_vvd_vari(double f, vari* avi, vari* bvi, double c) :
220  vari(f),
221  avi_(avi),
222  bvi_(bvi),
223  cd_(c) {
224  }
225  };
226 
227  class op_vdv_vari : public vari {
228  protected:
229  vari* avi_;
230  double bd_;
231  vari* cvi_;
232  public:
233  op_vdv_vari(double f, vari* avi, double b, vari* cvi) :
234  vari(f),
235  avi_(avi),
236  bd_(b),
237  cvi_(cvi) {
238  }
239  };
240 
241  class op_vdd_vari : public vari {
242  protected:
243  vari* avi_;
244  double bd_;
245  double cd_;
246  public:
247  op_vdd_vari(double f, vari* avi, double b, double c) :
248  vari(f),
249  avi_(avi),
250  bd_(b),
251  cd_(c) {
252  }
253  };
254 
255  class op_dvv_vari : public vari {
256  protected:
257  double ad_;
258  vari* bvi_;
259  vari* cvi_;
260  public:
261  op_dvv_vari(double f, double a, vari* bvi, vari* cvi) :
262  vari(f),
263  ad_(a),
264  bvi_(bvi),
265  cvi_(cvi) {
266  }
267  };
268 
269  class op_dvd_vari : public vari {
270  protected:
271  double ad_;
272  vari* bvi_;
273  double cd_;
274  public:
275  op_dvd_vari(double f, double a, vari* bvi, double c) :
276  vari(f),
277  ad_(a),
278  bvi_(bvi),
279  cd_(c) {
280  }
281  };
282 
283  class op_ddv_vari : public vari {
284  protected:
285  double ad_;
286  double bd_;
287  vari* cvi_;
288  public:
289  op_ddv_vari(double f, double a, double b, vari* cvi) :
290  vari(f),
291  ad_(a),
292  bd_(b),
293  cvi_(cvi) {
294  }
295  };
296 
297  class neg_vari : public op_v_vari {
298  public:
299  neg_vari(vari* avi) :
300  op_v_vari(-(avi->val_), avi) {
301  }
302  void chain() {
303  avi_->adj_ -= adj_;
304  }
305  };
306 
307 
308  class add_vv_vari : public op_vv_vari {
309  public:
310  add_vv_vari(vari* avi, vari* bvi) :
311  op_vv_vari(avi->val_ + bvi->val_, avi, bvi) {
312  }
313  void chain() {
314  avi_->adj_ += adj_;
315  bvi_->adj_ += adj_;
316  }
317  };
318 
319  class add_vd_vari : public op_vd_vari {
320  public:
321  add_vd_vari(vari* avi, double b) :
322  op_vd_vari(avi->val_ + b, avi, b) {
323  }
324  void chain() {
325  avi_->adj_ += adj_;
326  }
327  };
328 
329  class increment_vari : public op_v_vari {
330  public:
331  increment_vari(vari* avi) :
332  op_v_vari(avi->val_ + 1.0, avi) {
333  }
334  void chain() {
335  avi_->adj_ += adj_;
336  }
337  };
338 
339  class decrement_vari : public op_v_vari {
340  public:
341  decrement_vari(vari* avi) :
342  op_v_vari(avi->val_ - 1.0, avi) {
343  }
344  void chain() {
345  avi_->adj_ += adj_;
346  }
347  };
348 
349  class subtract_vv_vari : public op_vv_vari {
350  public:
351  subtract_vv_vari(vari* avi, vari* bvi) :
352  op_vv_vari(avi->val_ - bvi->val_, avi, bvi) {
353  }
354  void chain() {
355  avi_->adj_ += adj_;
356  bvi_->adj_ -= adj_;
357  }
358  };
359 
360  class subtract_vd_vari : public op_vd_vari {
361  public:
362  subtract_vd_vari(vari* avi, double b) :
363  op_vd_vari(avi->val_ - b, avi, b) {
364  }
365  void chain() {
366  avi_->adj_ += adj_;
367  }
368  };
369 
370  class subtract_dv_vari : public op_dv_vari {
371  public:
372  subtract_dv_vari(double a, vari* bvi) :
373  op_dv_vari(a - bvi->val_, a, bvi) {
374  }
375  void chain() {
376  bvi_->adj_ -= adj_;
377  }
378  };
379 
380  class multiply_vv_vari : public op_vv_vari {
381  public:
382  multiply_vv_vari(vari* avi, vari* bvi) :
383  op_vv_vari(avi->val_ * bvi->val_, avi, bvi) {
384  }
385  void chain() {
386  avi_->adj_ += bvi_->val_ * adj_;
387  bvi_->adj_ += avi_->val_ * adj_;
388  }
389  };
390 
391  class multiply_vd_vari : public op_vd_vari {
392  public:
393  multiply_vd_vari(vari* avi, double b) :
394  op_vd_vari(avi->val_ * b, avi, b) {
395  }
396  void chain() {
397  avi_->adj_ += adj_ * bd_;
398  }
399  };
400 
401  // (a/b)' = a' * (1 / b) - b' * (a / [b * b])
402  class divide_vv_vari : public op_vv_vari {
403  public:
404  divide_vv_vari(vari* avi, vari* bvi) :
405  op_vv_vari(avi->val_ / bvi->val_, avi, bvi) {
406  }
407  void chain() {
408  avi_->adj_ += adj_ / bvi_->val_;
409  bvi_->adj_ -= adj_ * avi_->val_ / (bvi_->val_ * bvi_->val_);
410  }
411  };
412 
413  class divide_vd_vari : public op_vd_vari {
414  public:
415  divide_vd_vari(vari* avi, double b) :
416  op_vd_vari(avi->val_ / b, avi, b) {
417  }
418  void chain() {
419  avi_->adj_ += adj_ / bd_;
420  }
421  };
422 
423  class divide_dv_vari : public op_dv_vari {
424  public:
425  divide_dv_vari(double a, vari* bvi) :
426  op_dv_vari(a / bvi->val_, a, bvi) {
427  }
428  void chain() {
429  bvi_->adj_ -= adj_ * ad_ / (bvi_->val_ * bvi_->val_);
430  }
431  };
432 
433  class exp_vari : public op_v_vari {
434  public:
435  exp_vari(vari* avi) :
436  op_v_vari(std::exp(avi->val_),avi) {
437  }
438  void chain() {
439  avi_->adj_ += adj_ * val_;
440  }
441  };
442 
443  class log_vari : public op_v_vari {
444  public:
445  log_vari(vari* avi) :
446  op_v_vari(std::log(avi->val_),avi) {
447  }
448  void chain() {
449  avi_->adj_ += adj_ / avi_->val_;
450  }
451  };
452 
453  double LOG_10 = std::log(10.0);
454 
455  class log10_vari : public op_v_vari {
456  public:
457  const double exp_val_;
458  log10_vari(vari* avi) :
459  op_v_vari(std::log10(avi->val_),avi),
460  exp_val_(avi->val_) {
461  }
462  void chain() {
463  avi_->adj_ += adj_ / (LOG_10 * exp_val_);
464  }
465  };
466 
467  class sqrt_vari : public op_v_vari {
468  public:
469  sqrt_vari(vari* avi) :
470  op_v_vari(std::sqrt(avi->val_),avi) {
471  }
472  void chain() {
473  avi_->adj_ += adj_ / (2.0 * val_);
474  }
475  };
476 
477  class pow_vv_vari : public op_vv_vari {
478  public:
479  pow_vv_vari(vari* avi, vari* bvi) :
480  op_vv_vari(std::pow(avi->val_,bvi->val_),avi,bvi) {
481  }
482  void chain() {
483  if (avi_->val_ == 0.0) return; // partials zero, avoids /0 & log(0)
484  avi_->adj_ += adj_ * bvi_->val_ * val_ / avi_->val_;
485  bvi_->adj_ += adj_ * std::log(avi_->val_) * val_;
486  }
487  };
488 
489  class pow_vd_vari : public op_vd_vari {
490  public:
491  pow_vd_vari(vari* avi, double b) :
492  op_vd_vari(std::pow(avi->val_,b),avi,b) {
493  }
494  void chain() {
495  if (avi_->val_ == 0.0) return; // partials zero, avoids /0 & log(0)
496  avi_->adj_ += adj_ * bd_ * val_ / avi_->val_;
497  }
498  };
499 
500  class pow_dv_vari : public op_dv_vari {
501  public:
502  pow_dv_vari(double a, vari* bvi) :
503  op_dv_vari(std::pow(a,bvi->val_),a,bvi) {
504  }
505  void chain() {
506  if (ad_ == 0.0) return; // partials zero, avoids /0 & log(0)
507  bvi_->adj_ += adj_ * std::log(ad_) * val_;
508  }
509  };
510 
511  class cos_vari : public op_v_vari {
512  public:
513  cos_vari(vari* avi) :
514  op_v_vari(std::cos(avi->val_),avi) {
515  }
516  void chain() {
517  avi_->adj_ -= adj_ * std::sin(avi_->val_);
518  }
519  };
520 
521  class sin_vari : public op_v_vari {
522  public:
523  sin_vari(vari* avi) :
524  op_v_vari(std::sin(avi->val_),avi) {
525  }
526  void chain() {
527  avi_->adj_ += adj_ * std::cos(avi_->val_);
528  }
529  };
530 
531  class tan_vari : public op_v_vari {
532  public:
533  tan_vari(vari* avi) :
534  op_v_vari(std::tan(avi->val_),avi) {
535  }
536  void chain() {
537  avi_->adj_ += adj_ * (1.0 + val_ * val_);
538  }
539  };
540 
541  class acos_vari : public op_v_vari {
542  public:
543  acos_vari(vari* avi) :
544  op_v_vari(std::acos(avi->val_),avi) {
545  }
546  void chain() {
547  avi_->adj_ -= adj_ / std::sqrt(1.0 - (avi_->val_ * avi_->val_));
548  }
549  };
550 
551  class asin_vari : public op_v_vari {
552  public:
553  asin_vari(vari* avi) :
554  op_v_vari(std::asin(avi->val_),avi) {
555  }
556  void chain() {
557  avi_->adj_ += adj_ / std::sqrt(1.0 - (avi_->val_ * avi_->val_));
558  }
559  };
560 
561  class atan_vari : public op_v_vari {
562  public:
563  atan_vari(vari* avi) :
564  op_v_vari(std::atan(avi->val_),avi) {
565  }
566  void chain() {
567  avi_->adj_ += adj_ / (1.0 + (avi_->val_ * avi_->val_));
568  }
569  };
570 
571  class atan2_vv_vari : public op_vv_vari {
572  public:
573  atan2_vv_vari(vari* avi, vari* bvi) :
574  op_vv_vari(std::atan2(avi->val_,bvi->val_),avi,bvi) {
575  }
576  void chain() {
577  double a_sq_plus_b_sq = (avi_->val_ * avi_->val_) + (bvi_->val_ * bvi_->val_);
578  avi_->adj_ += bvi_->val_ / a_sq_plus_b_sq;
579  bvi_->adj_ -= avi_->val_ / a_sq_plus_b_sq;
580  }
581  };
582 
583  class atan2_vd_vari : public op_vd_vari {
584  public:
585  atan2_vd_vari(vari* avi, double b) :
586  op_vd_vari(std::atan2(avi->val_,b),avi,b) {
587  }
588  void chain() {
589  double a_sq_plus_b_sq = (avi_->val_ * avi_->val_) + (bd_ * bd_);
590  avi_->adj_ += bd_ / a_sq_plus_b_sq;
591  }
592  };
593 
594  class atan2_dv_vari : public op_dv_vari {
595  public:
596  atan2_dv_vari(double a, vari* bvi) :
597  op_dv_vari(std::atan2(a,bvi->val_),a,bvi) {
598  }
599  void chain() {
600  double a_sq_plus_b_sq = (ad_ * ad_) + (bvi_->val_ * bvi_->val_);
601  bvi_->adj_ -= ad_ / a_sq_plus_b_sq;
602  }
603  };
604 
605  class cosh_vari : public op_v_vari {
606  public:
607  cosh_vari(vari* avi) :
608  op_v_vari(std::cosh(avi->val_),avi) {
609  }
610  void chain() {
611  avi_->adj_ += adj_ * std::sinh(avi_->val_);
612  }
613  };
614 
615  class sinh_vari : public op_v_vari {
616  public:
617  sinh_vari(vari* avi) :
618  op_v_vari(std::sinh(avi->val_),avi) {
619  }
620  void chain() {
621  avi_->adj_ += adj_ * std::cosh(avi_->val_);
622  }
623  };
624 
625  class tanh_vari : public op_v_vari {
626  public:
627  tanh_vari(vari* avi) :
628  op_v_vari(std::tanh(avi->val_),avi) {
629  }
630  void chain() {
631  double cosh = std::cosh(avi_->val_);
632  avi_->adj_ += adj_ / (cosh * cosh);
633  }
634  };
635 
636 
637  class floor_vari : public vari {
638  public:
639  floor_vari(vari* avi) :
640  vari(std::floor(avi->val_)) {
641  }
642  };
643 
644  class ceil_vari : public vari {
645  public:
646  ceil_vari(vari* avi) :
647  vari(std::ceil(avi->val_)) {
648  }
649  };
650 
651  class fmod_vv_vari : public op_vv_vari {
652  public:
653  fmod_vv_vari(vari* avi, vari* bvi) :
654  op_vv_vari(std::fmod(avi->val_,bvi->val_),avi,bvi) {
655  }
656  void chain() {
657  avi_->adj_ += adj_;
658  bvi_->adj_ -= adj_ * static_cast<int>(avi_->val_ / bvi_->val_);
659  }
660  };
661 
662  class fmod_vd_vari : public op_v_vari {
663  public:
664  fmod_vd_vari(vari* avi, double b) :
665  op_v_vari(std::fmod(avi->val_,b),avi) {
666  }
667  void chain() {
668  avi_->adj_ += adj_;
669  }
670  };
671 
672  class fmod_dv_vari : public op_dv_vari {
673  public:
674  fmod_dv_vari(double a, vari* bvi) :
675  op_dv_vari(std::fmod(a,bvi->val_),a,bvi) {
676  }
677  void chain() {
678  int d = static_cast<int>(ad_ / bvi_->val_);
679  bvi_->adj_ -= adj_ * d;
680  }
681  };
682 
683 
684 
685 
686 
687  }
688 
689  // ********************* vari UP, var DOWN ***********************************************************
690 
691 
701  class var {
702  public:
703 
704  typedef double Scalar;
705 
714 
720  explicit var(vari* vi) :
721  vi_(vi) {
722  }
723 
731  var() :
732  vi_(0) {
733  }
734 
741  var(bool b) :
742  vi_(new vari(static_cast<double>(b))) {
743  }
744 
751  var(char c) :
752  vi_(new vari(static_cast<double>(c))) {
753  }
754 
761  var(short n) :
762  vi_(new vari(static_cast<double>(n))) {
763  }
764 
771  var(unsigned short n) :
772  vi_(new vari(static_cast<double>(n))) {
773  }
774 
781  var(int n) :
782  vi_(new vari(static_cast<double>(n))) {
783  }
784 
791  var(unsigned int n) :
792  vi_(new vari(static_cast<double>(n))) {
793  }
794 
801  var(long int n) :
802  vi_(new vari(static_cast<double>(n))) {
803  }
804 
811  var(unsigned long int n) :
812  vi_(new vari(static_cast<double>(n))) {
813  }
814 
821  var(float x) :
822  vi_(new vari(static_cast<double>(x))) {
823  }
824 
830  var(double x) :
831  vi_(new vari(x)) {
832  }
833 
840  var(long double x) :
841  vi_(new vari(static_cast<double>(x))) {
842  }
843 
849  inline double val() const {
850  return vi_->val_;
851  }
852 
865  void grad(std::vector<var>& x,
866  std::vector<double>& g) {
867  vari::grad(vi_);
868  g.resize(x.size());
869  for (size_t i = 0U; i < x.size(); ++i)
870  g[i] = x[i].vi_->adj_;
872  }
873 
890  void grad() {
891  vari::grad(vi_);
893  }
894 
895  // COMPOUND ASSIGNMENT OPERATORS
896 
907  inline var& operator+=(const var& b) {
908  vi_ = new add_vv_vari(vi_,b.vi_);
909  return *this;
910  }
911 
922  inline var& operator+=(const double& b) {
923  vi_ = new add_vd_vari(vi_,b);
924  return *this;
925  }
926 
938  inline var& operator-=(const var& b) {
939  vi_ = new subtract_vv_vari(vi_,b.vi_);
940  return *this;
941  }
942 
954  inline var& operator-=(const double& b) {
955  vi_ = new subtract_vd_vari(vi_,b);
956  return *this;
957  }
958 
970  inline var& operator*=(const var& b) {
971  vi_ = new multiply_vv_vari(vi_,b.vi_);
972  return *this;
973  }
974 
986  inline var& operator*=(const double& b) {
987  vi_ = new multiply_vd_vari(vi_,b);
988  return *this;
989  }
990 
1001  inline var& operator/=(const var& b) {
1002  vi_ = new divide_vv_vari(vi_,b.vi_);
1003  return *this;
1004  }
1005 
1017  inline var& operator/=(const double& b) {
1018  vi_ = new divide_vd_vari(vi_,b);
1019  return *this;
1020  };
1021 
1022 
1023  };
1024 
1025  // COMPARISON OPERATORS
1026 
1035  inline bool operator==(const var& a, const var& b) {
1036  return a.val() == b.val();
1037  }
1038 
1048  inline bool operator==(const var& a, const double& b) {
1049  return a.val() == b;
1050  }
1051 
1060  inline bool operator==(const double& a, const var& b) {
1061  return a == b.val();
1062  }
1063 
1072  inline bool operator!=(const var& a, const var& b) {
1073  return a.val() != b.val();
1074  }
1075 
1085  inline bool operator!=(const var& a, const double& b) {
1086  return a.val() != b;
1087  }
1088 
1098  inline bool operator!=(const double& a, const var& b) {
1099  return a != b.val();
1100  }
1101 
1109  inline bool operator<(const var& a, const var& b) {
1110  return a.val() < b.val();
1111  }
1112 
1121  inline bool operator<(const var& a, const double& b) {
1122  return a.val() < b;
1123  }
1124 
1133  inline bool operator<(const double& a, const var& b) {
1134  return a < b.val();
1135  }
1136 
1144  inline bool operator>(const var& a, const var& b) {
1145  return a.val() > b.val();
1146  }
1147 
1156  inline bool operator>(const var& a, const double& b) {
1157  return a.val() > b;
1158  }
1159 
1168  inline bool operator>(const double& a, const var& b) {
1169  return a > b.val();
1170  }
1171 
1181  inline bool operator<=(const var& a, const var& b) {
1182  return a.val() <= b.val();
1183  }
1184 
1194  inline bool operator<=(const var& a, const double& b) {
1195  return a.val() <= b;
1196  }
1197 
1207  inline bool operator<=(const double& a, const var& b) {
1208  return a <= b.val();
1209  }
1210 
1220  inline bool operator>=(const var& a, const var& b) {
1221  return a.val() >= b.val();
1222  }
1223 
1233  inline bool operator>=(const var& a, const double& b) {
1234  return a.val() >= b;
1235  }
1236 
1246  inline bool operator>=(const double& a, const var& b) {
1247  return a >= b.val();
1248  }
1249 
1250  // LOGICAL OPERATORS
1251 
1265  inline bool operator!(const var& a) {
1266  return !a.val();
1267  }
1268 
1269  // ARITHMETIC OPERATORS
1270 
1286  inline var operator+(const var& a) {
1287  return a;
1288  }
1289 
1298  inline var operator-(const var& a) {
1299  return var(new neg_vari(a.vi_));
1300  }
1301 
1315  inline var operator+(const var& a, const var& b) {
1316  return var(new add_vv_vari(a.vi_,b.vi_));
1317  }
1318 
1319 
1331  inline var operator+(const var& a, const double& b) {
1332  return var(new add_vd_vari(a.vi_,b));
1333  }
1334 
1346  inline var operator+(const double& a, const var& b) {
1347  return var(new add_vd_vari(b.vi_,a)); // by symmetry
1348  }
1349 
1364  inline var operator-(const var& a, const var& b) {
1365  return var(new subtract_vv_vari(a.vi_,b.vi_));
1366  }
1367 
1379  inline var operator-(const var& a, const double& b) {
1380  return var(new subtract_vd_vari(a.vi_,b));
1381  }
1382 
1394  inline var operator-(const double& a, const var& b) {
1395  return var(new subtract_dv_vari(a,b.vi_));
1396  }
1397 
1411  inline var operator*(const var& a, const var& b) {
1412  return var(new multiply_vv_vari(a.vi_,b.vi_));
1413  }
1414 
1426  inline var operator*(const var& a, const double& b) {
1427  return var(new multiply_vd_vari(a.vi_,b));
1428  }
1429 
1441  inline var operator*(const double& a, const var& b) {
1442  return var(new multiply_vd_vari(b.vi_,a)); // by symmetry
1443  }
1444 
1459  inline var operator/(const var& a, const var& b) {
1460  return var(new divide_vv_vari(a.vi_,b.vi_));
1461  }
1462 
1474  inline var operator/(const var& a, const double& b) {
1475  return var(new divide_vd_vari(a.vi_,b));
1476  }
1477 
1489  inline var operator/(const double& a, const var& b) {
1490  return var(new divide_dv_vari(a,b.vi_));
1491  }
1492 
1502  inline var& operator++(var& a) {
1503  a.vi_ = new increment_vari(a.vi_);
1504  return a;
1505  }
1506 
1520  inline var operator++(var& a, int /*dummy*/) {
1521  var temp(a);
1522  a.vi_ = new increment_vari(a.vi_);
1523  return temp;
1524  }
1525 
1539  inline var& operator--(var& a) {
1540  a.vi_ = new decrement_vari(a.vi_);
1541  return a;
1542  }
1543 
1557  inline var operator--(var& a, int /*dummy*/) {
1558  var temp(a);
1559  a.vi_ = new decrement_vari(a.vi_);
1560  return temp;
1561  }
1562 
1563  // CMATH EXP AND LOG
1564 
1571  inline var exp(const var& a) {
1572  return var(new exp_vari(a.vi_));
1573  }
1574 
1585  inline var log(const var& a) {
1586  return var(new log_vari(a.vi_));
1587  }
1588 
1599  inline var log10(const var& a) {
1600  return var(new log10_vari(a.vi_));
1601  }
1602 
1603 
1604  // POWER FUNCTIONS
1605 
1616  inline var sqrt(const var& a) {
1617  return var(new sqrt_vari(a.vi_));
1618  }
1619 
1633  inline var pow(const var& base, const var& exponent) {
1634  return var(new pow_vv_vari(base.vi_,exponent.vi_));
1635  }
1636 
1649  inline var pow(const var& base, const double& exponent) {
1650  return var(new pow_vd_vari(base.vi_,exponent));
1651  }
1652 
1665  inline var pow(const double& base, const var& exponent) {
1666  return var(new pow_dv_vari(base,exponent.vi_));
1667  }
1668 
1669 
1670  // TRIG FUNCTIONS
1671 
1682  inline var cos(const var& a) {
1683  return var(new cos_vari(a.vi_));
1684  }
1685 
1696  inline var sin(const var& a) {
1697  return var(new sin_vari(a.vi_));
1698  }
1699 
1710  inline var tan(const var& a) {
1711  return var(new tan_vari(a.vi_));
1712  }
1713 
1725  inline var acos(const var& a) {
1726  return var(new acos_vari(a.vi_));
1727  }
1728 
1740  inline var asin(const var& a) {
1741  return var(new asin_vari(a.vi_));
1742  }
1743 
1755  inline var atan(const var& a) {
1756  return var(new atan_vari(a.vi_));
1757  }
1758 
1774  inline var atan2(const var& a, const var& b) {
1775  return var(new atan2_vv_vari(a.vi_,b.vi_));
1776  }
1777 
1790  inline var atan2(const var& a, const double& b) {
1791  return var(new atan2_vd_vari(a.vi_,b));
1792  }
1793 
1806  inline var atan2(const double& a, const var& b) {
1807  return var(new atan2_dv_vari(a,b.vi_));
1808  }
1809 
1810  // HYPERBOLIC FUNCTIONS
1811 
1822  inline var cosh(const var& a) {
1823  return var(new cosh_vari(a.vi_));
1824  }
1825 
1836  inline var sinh(const var& a) {
1837  return var(new sinh_vari(a.vi_));
1838  }
1839 
1850  inline var tanh(const var& a) {
1851  return var(new tanh_vari(a.vi_));
1852  }
1853 
1854 
1855  // ROUNDING FUNCTIONS
1856 
1873  inline var fabs(const var& a) {
1874  // cut-and-paste from abs()
1875  if (a.val() > 0.0)
1876  return a;
1877  if (a.val() < 0.0)
1878  return var(new neg_vari(a.vi_));
1879  return var(new vari(0.0));
1880  }
1881 
1900  inline var floor(const var& a) {
1901  return var(new floor_vari(a.vi_));
1902  }
1903 
1922  inline var ceil(const var& a) {
1923  return var(new ceil_vari(a.vi_));
1924  }
1925 
1943  inline var fmod(const var& a, const var& b) {
1944  return var(new fmod_vv_vari(a.vi_,b.vi_));
1945  }
1946 
1960  inline var fmod(const var& a, const double& b) {
1961  return var(new fmod_vd_vari(a.vi_,b));
1962  }
1963 
1977  inline var fmod(const double& a, const var& b) {
1978  return var(new fmod_dv_vari(a,b.vi_));
1979  }
1980 
1981 
1982  // STD LIB FUNCTIONS
1983 
1998  inline var abs(const var& a) {
1999  // cut-and-paste from fabs()
2000  if (a.val() > 0.0)
2001  return a;
2002  if (a.val() < 0.0)
2003  return var(new neg_vari(a.vi_));
2004  return var(new vari(0.0));
2005  }
2006 
2007  }
2008 
2009 }
2010 
2011 #endif

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