Stan  1.0
probability, sampling & optimization
 All Classes Namespaces Files Functions Variables Typedefs Enumerator Friends Macros Pages
special_functions.hpp
Go to the documentation of this file.
1 #ifndef __STAN__AGRAD__AGRAD_SPECIAL_FUNCTIONS__H__
2 #define __STAN__AGRAD__AGRAD_SPECIAL_FUNCTIONS__H__
3 
4 #include <cstddef>
5 #include <boost/math/special_functions.hpp>
6 #include <stan/agrad/agrad.hpp>
10 
11 namespace stan {
12 
13  namespace agrad {
14 
15  namespace {
16 
17  class lgamma_vari : public op_v_vari {
18  public:
19  lgamma_vari(double value, vari* avi) :
20  op_v_vari(value, avi) {
21  }
22  void chain() {
23  avi_->adj_ += adj_ * boost::math::digamma(avi_->val_);
24  }
25  };
26 
27  class tgamma_vari : public op_v_vari {
28  public:
29  tgamma_vari(vari* avi) :
30  op_v_vari(boost::math::tgamma(avi->val_), avi) {
31  }
32  void chain() {
33  avi_->adj_ += adj_ * val_ * boost::math::digamma(avi_->val_);
34  }
35  };
36 
37  class log1p_vari : public op_v_vari {
38  public:
39  log1p_vari(vari* avi) :
40  op_v_vari(stan::math::log1p(avi->val_),avi) {
41  }
42  void chain() {
43  avi_->adj_ += adj_ / (1 + avi_->val_);
44  }
45  };
46 
47  class log1m_vari : public op_v_vari {
48  public:
49  log1m_vari(vari* avi) :
50  op_v_vari(stan::math::log1p(-avi->val_),avi) {
51  }
52  void chain() {
53  avi_->adj_ += adj_ / (avi_->val_ - 1);
54  }
55  };
56 
57  class binary_log_loss_1_vari : public op_v_vari {
58  public:
59  binary_log_loss_1_vari(vari* avi) :
60  op_v_vari(-std::log(avi->val_),avi) {
61  }
62  void chain() {
63  avi_->adj_ -= adj_ / avi_->val_;
64  }
65  };
66 
67  class binary_log_loss_0_vari : public op_v_vari {
68  public:
69  binary_log_loss_0_vari(vari* avi) :
70  op_v_vari(-stan::math::log1p(-avi->val_),avi) {
71  }
72  void chain() {
73  avi_->adj_ += adj_ / (1.0 - avi_->val_);
74  }
75  };
76 
77  class fdim_vv_vari : public op_vv_vari {
78  public:
79  fdim_vv_vari(vari* avi, vari* bvi) :
80  op_vv_vari(avi->val_ - bvi->val_, avi, bvi) {
81  }
82  void chain() {
83  avi_->adj_ += adj_;
84  bvi_->adj_ -= adj_;
85  }
86  };
87 
88  class fdim_vd_vari : public op_v_vari {
89  public:
90  fdim_vd_vari(vari* avi, double b) :
91  op_v_vari(avi->val_ - b, avi) {
92  }
93  void chain() {
94  avi_->adj_ += adj_;
95  }
96  };
97 
98  class fdim_dv_vari : public op_v_vari {
99  public:
100  fdim_dv_vari(double a, vari* bvi) :
101  op_v_vari(a - bvi->val_, bvi) {
102  }
103  void chain() {
104  // avi_ is bvi argument to constructor
105  avi_->adj_ -= adj_;
106  }
107  };
108 
109  class fma_vvv_vari : public op_vvv_vari {
110  public:
111  fma_vvv_vari(vari* avi, vari* bvi, vari* cvi) :
112  op_vvv_vari(avi->val_ * bvi->val_ + cvi->val_,
113  avi,bvi,cvi) {
114  }
115  void chain() {
116  avi_->adj_ += adj_ * bvi_->val_;
117  bvi_->adj_ += adj_ * avi_->val_;
118  cvi_->adj_ += adj_;
119  }
120  };
121 
122  class fma_vvd_vari : public op_vv_vari {
123  public:
124  fma_vvd_vari(vari* avi, vari* bvi, double c) :
125  op_vv_vari(avi->val_ * bvi->val_ + c,
126  avi,bvi) {
127  }
128  void chain() {
129  avi_->adj_ += adj_ * bvi_->val_;
130  bvi_->adj_ += adj_ * avi_->val_;
131  }
132  };
133 
134  class fma_vdv_vari : public op_vdv_vari {
135  public:
136  fma_vdv_vari(vari* avi, double b, vari* cvi) :
137  op_vdv_vari(avi->val_ * b + cvi->val_,
138  avi,b,cvi) {
139  }
140  void chain() {
141  avi_->adj_ += adj_ * bd_;
142  cvi_->adj_ += adj_;
143  }
144  };
145 
146  class fma_vdd_vari : public op_vd_vari {
147  public:
148  fma_vdd_vari(vari* avi, double b, double c) :
149  op_vd_vari(avi->val_ * b + c,
150  avi,b) {
151  }
152  void chain() {
153  avi_->adj_ += adj_ * bd_;
154  }
155  };
156 
157  class fma_ddv_vari : public op_v_vari {
158  public:
159  fma_ddv_vari(double a, double b, vari* cvi) :
160  op_v_vari(a * b + cvi->val_,
161  cvi) {
162  }
163  void chain() {
164  // avi_ is cvi from constructor
165  avi_->adj_ += adj_;
166  }
167  };
168 
169  class inv_logit_vari : public op_v_vari {
170  public:
171  inv_logit_vari(vari* avi) :
172  op_v_vari(math::inv_logit(avi->val_),avi) {
173  }
174  void chain() {
175  avi_->adj_ += adj_ * val_ * (1.0 - val_);
176  }
177  };
178 
179  class acosh_vari : public op_v_vari {
180  public:
181  acosh_vari(vari* avi) :
182  op_v_vari(boost::math::acosh(avi->val_),avi) {
183  }
184  void chain() {
185  avi_->adj_ += adj_ / std::sqrt(avi_->val_ * avi_->val_ - 1.0);
186  }
187  };
188 
189  class asinh_vari : public op_v_vari {
190  public:
191  asinh_vari(vari* avi) :
192  op_v_vari(boost::math::asinh(avi->val_),avi) {
193  }
194  void chain() {
195  avi_->adj_ += adj_ / std::sqrt(avi_->val_ * avi_->val_ + 1.0);
196  }
197  };
198 
199  class atanh_vari : public op_v_vari {
200  public:
201  atanh_vari(vari* avi) :
202  op_v_vari(boost::math::atanh(avi->val_),avi) {
203  }
204  void chain() {
205  avi_->adj_ += adj_ / (1.0 - avi_->val_ * avi_->val_);
206  }
207  };
208 
209  const double TWO_OVER_SQRT_PI = 2.0 / std::sqrt(boost::math::constants::pi<double>());
210 
211  class erf_vari : public op_v_vari {
212  public:
213  erf_vari(vari* avi) :
214  op_v_vari(boost::math::erf(avi->val_),avi) {
215  }
216  void chain() {
217  avi_->adj_ += adj_ * TWO_OVER_SQRT_PI * std::exp(- avi_->val_ * avi_->val_);
218  }
219  };
220 
221  const double NEG_TWO_OVER_SQRT_PI = - TWO_OVER_SQRT_PI;
222 
223  class erfc_vari : public op_v_vari {
224  public:
225  erfc_vari(vari* avi) :
226  op_v_vari(boost::math::erfc(avi->val_),avi) {
227  }
228  void chain() {
229  avi_->adj_ += adj_ * NEG_TWO_OVER_SQRT_PI * std::exp(- avi_->val_ * avi_->val_);
230  }
231  };
232 
233  const double LOG_2 = std::log(2.0);
234 
235  class exp2_vari : public op_v_vari {
236  public:
237  exp2_vari(vari* avi) :
238  op_v_vari(std::pow(2.0,avi->val_),avi) {
239  }
240  void chain() {
241  avi_->adj_ += adj_ * val_ * LOG_2;
242  }
243  };
244 
245  class expm1_vari : public op_v_vari {
246  public:
247  expm1_vari(vari* avi) :
248  op_v_vari(std::exp(avi->val_) - 1.0,avi) {
249  }
250  void chain() {
251  avi_->adj_ += adj_ * val_;
252  }
253  };
254 
255  class hypot_vv_vari : public op_vv_vari {
256  public:
257  hypot_vv_vari(vari* avi, vari* bvi) :
258  op_vv_vari(boost::math::hypot(avi->val_,bvi->val_),
259  avi,bvi) {
260  }
261  void chain() {
262  avi_->adj_ += adj_ * avi_->val_ / val_;
263  bvi_->adj_ += adj_ * bvi_->val_ / val_;
264  }
265  };
266 
267  class hypot_vd_vari : public op_v_vari {
268  public:
269  hypot_vd_vari(vari* avi, double b) :
270  op_v_vari(boost::math::hypot(avi->val_,b),
271  avi) {
272  }
273  void chain() {
274  avi_->adj_ += adj_ * avi_->val_ / val_;
275  }
276  };
277 
278  const double LOG2 = std::log(2.0);
279 
280  class log2_vari : public op_v_vari {
281  public:
282  log2_vari(vari* avi) :
283  op_v_vari(stan::math::log2(avi->val_),avi) {
284  }
285  void chain() {
286  avi_->adj_ += adj_ / (LOG2 * avi_->val_);
287  }
288  };
289 
290  class cbrt_vari : public op_v_vari {
291  public:
292  cbrt_vari(vari* avi) :
293  op_v_vari(boost::math::cbrt(avi->val_),avi) {
294  }
295  void chain() {
296  avi_->adj_ += adj_ / (3.0 * val_ * val_);
297  }
298  };
299 
300  // derivative 0 almost everywhere
301  class round_vari : public vari {
302  public:
303  round_vari(vari* avi) :
304  vari(boost::math::round(avi->val_)) {
305  }
306  };
307 
308  // derivative 0 almost everywhere
309  class trunc_vari : public vari {
310  public:
311  trunc_vari(vari* avi) :
312  vari(boost::math::trunc(avi->val_)) {
313  }
314  };
315 
316  class inv_cloglog_vari : public op_v_vari {
317  public:
318  inv_cloglog_vari(vari* avi) :
319  op_v_vari(stan::math::inv_cloglog(avi->val_), avi) {
320  }
321  void chain() {
322  avi_->adj_ -= adj_ * std::exp(avi_->val_ - std::exp(avi_->val_));
323  }
324  };
325 
326  class Phi_vari : public op_v_vari {
327  public:
328  Phi_vari(vari* avi) :
329  op_v_vari(stan::math::Phi(avi->val_), avi) {
330  }
331  void chain() {
332  static const double NEG_HALF = -0.5;
333  static const double INV_SQRT_TWO_PI
334  = 1.0 / std::sqrt(2.0 * boost::math::constants::pi<double>());
335  avi_->adj_ += adj_ * INV_SQRT_TWO_PI * std::exp(NEG_HALF * avi_->val_ * avi_->val_);
336  }
337  };
338 
339  inline double calculate_chain(const double& x, const double& val) {
340  return std::exp(x - val);
341  }
342 
343  double log_sum_exp_as_double(const std::vector<var>& x) {
344  using std::numeric_limits;
345  using std::exp;
346  using std::log;
347  double max = -numeric_limits<double>::infinity();
348  for (size_t i = 0; i < x.size(); ++i)
349  if (x[i] > max)
350  max = x[i].val();
351  double sum = 0.0;
352  for (size_t i = 0; i < x.size(); ++i)
353  if (x[i] != -numeric_limits<double>::infinity())
354  sum += exp(x[i].val() - max);
355  return max + log(sum);
356  }
357 
358  class log1p_exp_v_vari : public op_v_vari {
359  public:
360  log1p_exp_v_vari(vari* avi) :
361  op_v_vari(stan::math::log1p_exp(avi->val_),
362  avi) {
363  }
364  void chain() {
365  avi_->adj_ += adj_ * calculate_chain(avi_->val_, val_);
366  }
367  };
368  class log_sum_exp_vv_vari : public op_vv_vari {
369  public:
370  log_sum_exp_vv_vari(vari* avi, vari* bvi) :
371  op_vv_vari(stan::math::log_sum_exp(avi->val_, bvi->val_),
372  avi, bvi) {
373  }
374  void chain() {
375  avi_->adj_ += adj_ * calculate_chain(avi_->val_, val_);
376  bvi_->adj_ += adj_ * calculate_chain(bvi_->val_, val_);
377  }
378  };
379  class log_sum_exp_vd_vari : public op_vd_vari {
380  public:
381  log_sum_exp_vd_vari(vari* avi, double b) :
382  op_vd_vari(stan::math::log_sum_exp(avi->val_, b),
383  avi, b) {
384  }
385  void chain() {
386  avi_->adj_ += adj_ * calculate_chain(avi_->val_, val_);
387  }
388  };
389  class log_sum_exp_dv_vari : public op_dv_vari {
390  public:
391  log_sum_exp_dv_vari(double a, vari* bvi) :
392  op_dv_vari(stan::math::log_sum_exp(a, bvi->val_),
393  a, bvi) {
394  }
395  void chain() {
396  bvi_->adj_ += adj_ * calculate_chain(bvi_->val_, val_);
397  }
398  };
399  class log_sum_exp_vector_vari : public op_vector_vari {
400  public:
401  log_sum_exp_vector_vari(const std::vector<var>& x) :
402  op_vector_vari(log_sum_exp_as_double(x), x) {
403  }
404  void chain() {
405  for (size_t i = 0; i < size_; ++i) {
406  vis_[i]->adj_ += adj_ * calculate_chain(vis_[i]->val_, val_);
407  }
408  }
409  };
410 
411  class square_vari : public op_v_vari {
412  public:
413  square_vari(vari* avi) :
414  op_v_vari(avi->val_ * avi->val_,avi) {
415  }
416  void chain() {
417  avi_->adj_ += adj_ * 2.0 * avi_->val_;
418  }
419  };
420 
421  class multiply_log_vv_vari : public op_vv_vari {
422  public:
423  multiply_log_vv_vari(vari* avi, vari* bvi) :
424  op_vv_vari(stan::math::multiply_log(avi->val_,bvi->val_),avi,bvi) {
425  }
426  void chain() {
427  using std::log;
428  avi_->adj_ += adj_ * log(bvi_->val_);
429  if (bvi_->val_ == 0.0 && avi_->val_ == 0)
430  bvi_->adj_ += adj_ * std::numeric_limits<double>::infinity();
431  else
432  bvi_->adj_ += adj_ * avi_->val_ / bvi_->val_;
433  }
434  };
435  class multiply_log_vd_vari : public op_vd_vari {
436  public:
437  multiply_log_vd_vari(vari* avi, double b) :
438  op_vd_vari(stan::math::multiply_log(avi->val_,b),avi,b) {
439  }
440  void chain() {
441  using std::log;
442  avi_->adj_ += adj_ * log(bd_);
443  }
444  };
445  class multiply_log_dv_vari : public op_dv_vari {
446  public:
447  multiply_log_dv_vari(double a, vari* bvi) :
448  op_dv_vari(stan::math::multiply_log(a,bvi->val_),a,bvi) {
449  }
450  void chain() {
451  if (bvi_->val_ == 0.0 && ad_ == 0.0)
452  bvi_->adj_ += adj_ * std::numeric_limits<double>::infinity();
453  else
454  bvi_->adj_ += adj_ * ad_ / bvi_->val_;
455  }
456  };
457  namespace {
463  double ibeta_hypergeometric_helper(double a, double b, double z, double precision=1e-8, double max_steps=1000) {
464  double val=0;
465  double diff=1;
466  double k=0;
467  double a_2 = a*a;
468  double bprod = 1;
469  while (std::abs(diff) > precision && (++k < max_steps) && !std::isnan(diff)) {
470  val += diff;
471  bprod *= b+k-1.0;
472  diff = a_2*std::pow(a+k,-2)*bprod*std::pow(z,k)/boost::math::tgamma(k+1);
473  }
474  return val;
475  }
476  }
477  class ibeta_vvv_vari : public op_vvv_vari {
478  public:
479  ibeta_vvv_vari(vari* avi, vari* bvi, vari* xvi) :
480  op_vvv_vari(stan::math::ibeta(avi->val_,bvi->val_,xvi->val_),avi,bvi,xvi) {
481  }
482  void chain() {
483  double a = avi_->val_;
484  double b = bvi_->val_;
485  double c = cvi_->val_;
486 
487  using std::sin;
488  using std::pow;
489  using std::log;
491  using boost::math::tgamma;
492  using boost::math::digamma;
493  using boost::math::ibeta;
494  using stan::agrad::ibeta_hypergeometric_helper;
495  avi_->adj_ += adj_ *
496  (log(c) - digamma(a) + digamma(a+b)) * val_ -
497  tgamma(a)*tgamma(a+b)/tgamma(b) * pow(c,a) / tgamma(1+a) / tgamma(1+a) * ibeta_hypergeometric_helper(a, 1-b, c);
498  bvi_->adj_ += adj_ *
499  (tgamma(b)*tgamma(a+b)/tgamma(a)*pow(1-c,b) * ibeta_hypergeometric_helper(b,1-a,1-c)/tgamma(b+1)/tgamma(b+1)
500  + ibeta(b, a, 1-c) * (digamma(b) - digamma(a+b) - log(1-c)));
501  cvi_->adj_ += adj_ *
502  boost::math::ibeta_derivative(a,b,c);
503  }
504  };
505  class ibeta_vvd_vari : public op_vvd_vari {
506  public:
507  ibeta_vvd_vari(vari* avi, vari* bvi, double x) :
508  op_vvd_vari(stan::math::ibeta(avi->val_,bvi->val_,x),avi,bvi,x) {
509  }
510  void chain() {
511  double a = avi_->val_;
512  double b = bvi_->val_;
513  double c = cd_;
514 
515  using std::sin;
516  using std::pow;
517  using std::log;
519  using boost::math::tgamma;
520  using boost::math::digamma;
521  using boost::math::ibeta;
522  using stan::agrad::ibeta_hypergeometric_helper;
523  avi_->adj_ += adj_ *
524  (log(c) - digamma(a) + digamma(a+b)) * val_ -
525  tgamma(a)*tgamma(a+b)/tgamma(b) * pow(c,a) / tgamma(1+a) / tgamma(1+a) * ibeta_hypergeometric_helper(a, 1-b, c);
526  bvi_->adj_ += adj_ *
527  (tgamma(b)*tgamma(a+b)/tgamma(a)*pow(1-c,b) * ibeta_hypergeometric_helper(b,1-a,1-c)/tgamma(b+1)/tgamma(b+1)
528  + ibeta(b, a, 1-c) * (digamma(b) - digamma(a+b) - log(1-c)));
529  }
530  };
531  class ibeta_vdv_vari : public op_vdv_vari {
532  public:
533  ibeta_vdv_vari(vari* avi, double b, vari* xvi) :
534  op_vdv_vari(stan::math::ibeta(avi->val_,b,xvi->val_),avi,b,xvi) {
535  }
536  void chain() {
537  double a = avi_->val_;
538  double b = bd_;
539  double c = cvi_->val_;
540 
541  using std::sin;
542  using std::pow;
543  using std::log;
545  using boost::math::tgamma;
546  using boost::math::digamma;
547  using boost::math::ibeta;
548  using stan::agrad::ibeta_hypergeometric_helper;
549  avi_->adj_ += adj_ *
550  (log(c) - digamma(a) + digamma(a+b)) * val_ -
551  tgamma(a)*tgamma(a+b)/tgamma(b) * pow(c,a) / tgamma(1+a) / tgamma(1+a) * ibeta_hypergeometric_helper(a, 1-b, c);
552  cvi_->adj_ += adj_ *
553  boost::math::ibeta_derivative(a,b,c);
554  }
555  };
556  class ibeta_vdd_vari : public op_vdd_vari {
557  public:
558  ibeta_vdd_vari(vari* avi, double b, double x) :
559  op_vdd_vari(stan::math::ibeta(avi->val_,b,x),avi,b,x) {
560  }
561  void chain() {
562  double a = avi_->val_;
563  double b = bd_;
564  double c = cd_;
565 
566  using std::sin;
567  using std::pow;
568  using std::log;
570  using boost::math::tgamma;
571  using boost::math::digamma;
572  using boost::math::ibeta;
573  using stan::agrad::ibeta_hypergeometric_helper;
574  avi_->adj_ += adj_ *
575  (log(c) - digamma(a) + digamma(a+b)) * val_ -
576  tgamma(a)*tgamma(a+b)/tgamma(b) * pow(c,a) / tgamma(1+a) / tgamma(1+a) * ibeta_hypergeometric_helper(a, 1-b, c);
577  }
578  };
579  class ibeta_dvv_vari : public op_dvv_vari {
580  public:
581  ibeta_dvv_vari(double a, vari* bvi, vari* xvi) :
582  op_dvv_vari(stan::math::ibeta(a,bvi->val_,xvi->val_),a,bvi,xvi) {
583  }
584  void chain() {
585  double a = ad_;
586  double b = bvi_->val_;
587  double c = cvi_->val_;
588 
589  using std::sin;
590  using std::pow;
591  using std::log;
593  using boost::math::tgamma;
594  using boost::math::digamma;
595  using boost::math::ibeta;
596  using stan::agrad::ibeta_hypergeometric_helper;
597  bvi_->adj_ += adj_ *
598  (tgamma(b)*tgamma(a+b)/tgamma(a)*pow(1-c,b) * ibeta_hypergeometric_helper(b,1-a,1-c)/tgamma(b+1)/tgamma(b+1)
599  + ibeta(b, a, 1-c) * (digamma(b) - digamma(a+b) - log(1-c)));
600  cvi_->adj_ += adj_ *
601  boost::math::ibeta_derivative(a,b,c);
602  }
603  };
604  class ibeta_dvd_vari : public op_dvd_vari {
605  public:
606  ibeta_dvd_vari(double a, vari* bvi, double x) :
607  op_dvd_vari(stan::math::ibeta(a,bvi->val_,x),a,bvi,x) {
608  }
609  void chain() {
610  double a = ad_;
611  double b = bvi_->val_;
612  double c = cd_;
613 
614  using std::sin;
615  using std::pow;
616  using std::log;
618  using boost::math::tgamma;
619  using boost::math::digamma;
620  using boost::math::ibeta;
621  using stan::agrad::ibeta_hypergeometric_helper;
622  bvi_->adj_ += adj_ *
623  (tgamma(b)*tgamma(a+b)/tgamma(a)*pow(1-c,b) * ibeta_hypergeometric_helper(b,1-a,1-c)/tgamma(b+1)/tgamma(b+1)
624  + ibeta(b, a, 1-c) * (digamma(b) - digamma(a+b) - log(1-c)));
625  }
626  };
627  class ibeta_ddv_vari : public op_ddv_vari {
628  public:
629  ibeta_ddv_vari(double a, double b, vari* xvi) :
630  op_ddv_vari(stan::math::ibeta(a,b,xvi->val_),a,b,xvi) {
631  }
632  void chain() {
633  double a = ad_;
634  double b = bd_;
635  double c = cvi_->val_;
636 
637  cvi_->adj_ += adj_ *
638  boost::math::ibeta_derivative(a,b,c);
639  }
640  };
641  }
642 
643 
646 
659  inline var acosh(const stan::agrad::var& a) {
660  return var(new acosh_vari(a.vi_));
661  }
662 
675  inline var asinh(const stan::agrad::var& a) {
676  return var(new asinh_vari(a.vi_));
677  }
678 
691  inline var atanh(const stan::agrad::var& a) {
692  return var(new atanh_vari(a.vi_));
693  }
694 
707  inline var erf(const stan::agrad::var& a) {
708  return var(new erf_vari(a.vi_));
709  }
710 
723  inline var erfc(const stan::agrad::var& a) {
724  return var(new erfc_vari(a.vi_));
725  }
726 
739  inline var exp2(const stan::agrad::var& a) {
740  return var(new exp2_vari(a.vi_));
741  }
742 
755  inline var expm1(const stan::agrad::var& a) {
756  return var(new expm1_vari(a.vi_));
757  }
758 
769  inline var lgamma(const stan::agrad::var& a) {
770  double lgamma_a = boost::math::lgamma(a.val());
771  return var(new lgamma_vari(lgamma_a, a.vi_));
772  }
773 
784  inline var log1p(const stan::agrad::var& a) {
785  return var(new log1p_vari(a.vi_));
786  }
787 
798  inline var log1m(const stan::agrad::var& a) {
799  return var(new log1m_vari(a.vi_));
800  }
801 
822  inline var fma(const stan::agrad::var& a,
823  const stan::agrad::var& b,
824  const stan::agrad::var& c) {
825  return var(new fma_vvv_vari(a.vi_,b.vi_,c.vi_));
826  }
827 
846  inline var fma(const stan::agrad::var& a,
847  const stan::agrad::var& b,
848  const double& c) {
849  return var(new fma_vvd_vari(a.vi_,b.vi_,c));
850  }
851 
870  inline var fma(const stan::agrad::var& a,
871  const double& b,
872  const stan::agrad::var& c) {
873  return var(new fma_vdv_vari(a.vi_,b,c.vi_));
874  }
875 
892  inline var fma(const stan::agrad::var& a,
893  const double& b,
894  const double& c) {
895  return var(new fma_vdd_vari(a.vi_,b,c));
896  }
897 
914  inline var fma(const double& a,
915  const stan::agrad::var& b,
916  const double& c) {
917  return var(new fma_vdd_vari(b.vi_,a,c));
918  }
919 
936  inline var fma(const double& a,
937  const double& b,
938  const stan::agrad::var& c) {
939  return var(new fma_ddv_vari(a,b,c.vi_));
940  }
941 
960  inline var fma(const double& a,
961  const stan::agrad::var& b,
962  const stan::agrad::var& c) {
963  return var(new fma_vdv_vari(b.vi_,a,c.vi_)); // a-b symmetry
964  }
965 
966 
984  inline var fmax(const stan::agrad::var& a,
985  const stan::agrad::var& b) {
986  return a.vi_->val_ > b.vi_->val_ ? a : b;
987  }
988 
1005  inline var fmax(const stan::agrad::var& a,
1006  const double& b) {
1007  return a.vi_->val_ >= b ? a : var(b);
1008  }
1009 
1026  inline var fmax(const double& a,
1027  const stan::agrad::var& b) {
1028  return a > b.vi_->val_ ? var(a) : b;
1029  }
1030 
1044  inline var fmin(const stan::agrad::var& a,
1045  const stan::agrad::var& b) {
1046  return a.vi_->val_ < b.vi_->val_ ? a : b;
1047  }
1048 
1063  inline var fmin(const stan::agrad::var& a,
1064  const double& b) {
1065  return a.vi_->val_ <= b ? a : var(b);
1066  }
1067 
1084  inline var fmin(const double& a,
1085  const stan::agrad::var& b) {
1086  return a < b.vi_->val_ ? var(a) : b;
1087  }
1088 
1105  inline var hypot(const stan::agrad::var& a,
1106  const stan::agrad::var& b) {
1107  return var(new hypot_vv_vari(a.vi_,b.vi_));
1108  }
1109 
1124  inline var hypot(const stan::agrad::var& a,
1125  const double& b) {
1126  return var(new hypot_vd_vari(a.vi_,b));
1127  }
1128 
1143  inline var hypot(const double& a,
1144  const stan::agrad::var& b) {
1145  return var(new hypot_vd_vari(b.vi_,a));
1146  }
1147 
1160  inline var log2(const stan::agrad::var& a) {
1161  return var(new log2_vari(a.vi_));
1162  }
1163 
1176  inline var cbrt(const stan::agrad::var& a) {
1177  return var(new cbrt_vari(a.vi_));
1178  }
1179 
1194  inline var round(const stan::agrad::var& a) {
1195  return var(new round_vari(a.vi_));
1196  }
1197 
1211  inline var trunc(const stan::agrad::var& a) {
1212  return var(new trunc_vari(a.vi_));
1213  }
1214 
1215 
1239  inline var fdim(const stan::agrad::var& a,
1240  const stan::agrad::var& b) {
1241  if (a.vi_->val_ > b.vi_->val_)
1242  return var(new fdim_vv_vari(a.vi_,b.vi_));
1243  else
1244  return var(new vari(0.0));
1245  }
1246 
1264  inline var fdim(const double& a,
1265  const stan::agrad::var& b) {
1266  return a > b.vi_->val_
1267  ? var(new fdim_dv_vari(a,b.vi_))
1268  : var(new vari(0.0));
1269  }
1270 
1287  inline var fdim(const stan::agrad::var& a,
1288  const double& b) {
1289  return a.vi_->val_ > b
1290  ? var(new fdim_vd_vari(a.vi_,b))
1291  : var(new vari(0.0));
1292  }
1293 
1310  inline var tgamma(const stan::agrad::var& a) {
1311  return var(new tgamma_vari(a.vi_));
1312  }
1313 
1330  inline var step(const stan::agrad::var& a) {
1331  return var(new vari(a.vi_->val_ < 0.0 ? 0.0 : 1.0));
1332  }
1333 
1348  inline var inv_cloglog(const stan::agrad::var& a) {
1349  return var(new inv_cloglog_vari(a.vi_));
1350  }
1351 
1364  inline var Phi(const stan::agrad::var& a) {
1365  return var(new Phi_vari(a.vi_));
1366  }
1367 
1380  inline var inv_logit(const stan::agrad::var& a) {
1381  return var(new inv_logit_vari(a.vi_));
1382  }
1383 
1399  inline var log_loss(const int& y,
1400  const stan::agrad::var& y_hat) {
1401  return y == 0
1402  ? var(new binary_log_loss_0_vari(y_hat.vi_))
1403  : var(new binary_log_loss_1_vari(y_hat.vi_));
1404  }
1405 
1410  inline var log1p_exp(const stan::agrad::var& a) {
1411  return var(new log1p_exp_v_vari(a.vi_));
1412  }
1413 
1418  const stan::agrad::var& b) {
1419  return var(new log_sum_exp_vv_vari(a.vi_, b.vi_));
1420  }
1425  const double& b) {
1426  return var(new log_sum_exp_vd_vari(a.vi_, b));
1427  }
1431  inline var log_sum_exp(const double& a,
1432  const stan::agrad::var& b) {
1433  return var(new log_sum_exp_dv_vari(a, b.vi_));
1434  }
1438  inline var log_sum_exp(const std::vector<var>& x) {
1439  return var(new log_sum_exp_vector_vari(x));
1440  }
1441 
1451  inline var square(const var& x) {
1452  return var(new square_vari(x.vi_));
1453  }
1454 
1455  // OTHER FUNCTIONS: stan/math/special_functions.hpp implementations
1468  inline var multiply_log(const var& a, const var& b) {
1469  return var(new multiply_log_vv_vari(a.vi_,b.vi_));
1470  }
1481  inline var multiply_log(const var& a, const double b) {
1482  return var(new multiply_log_vd_vari(a.vi_,b));
1483  }
1495  inline var multiply_log(const double a, const var& b) {
1496  if (a == 1.0)
1497  return log(b);
1498  return var(new multiply_log_dv_vari(a,b.vi_));
1499  }
1500 
1501 
1510  inline var if_else(bool c, const var& y_true, const var&y_false) {
1511  return c ? y_true : y_false;
1512  }
1522  inline var if_else(bool c, double y_true, const var& y_false) {
1523  if (c)
1524  return var(y_true);
1525  else
1526  return y_false;
1527  }
1537  inline var if_else(bool c, const var& y_true, const double y_false) {
1538  if (c)
1539  return y_true;
1540  else
1541  return var(y_false);
1542  }
1543 
1561  inline var ibeta(const var& a,
1562  const var& b,
1563  const var& x) {
1564  return var(new ibeta_vvv_vari(a.vi_, b.vi_, x.vi_));
1565  }
1566 
1580  inline double value_of(const agrad::var& v) {
1581  return v.vi_->val_;
1582  }
1583 
1584  } // namespace math
1585 
1586 } // namespace stan
1587 
1588 
1589 #endif

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