Stan  2.5.0
probability, sampling & optimization
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
fma.hpp
Go to the documentation of this file.
1 #ifndef STAN__AGRAD__REV__FUNCTIONS__FMA_HPP
2 #define STAN__AGRAD__REV__FUNCTIONS__FMA_HPP
3 
4 #include <cmath>
5 #include <valarray>
6 #include <stan/agrad/rev/var.hpp>
12 #include <stan/math/constants.hpp>
13 #include <boost/math/special_functions/fpclassify.hpp>
14 #include <stan/meta/likely.hpp>
15 
16 namespace stan {
17  namespace agrad {
18 
19  namespace {
20  class fma_vvv_vari : public op_vvv_vari {
21  public:
22  fma_vvv_vari(vari* avi, vari* bvi, vari* cvi) :
23  op_vvv_vari(::fma(avi->val_, bvi->val_, cvi->val_),
24  avi,bvi,cvi) {
25  }
26  void chain() {
27  if (unlikely(boost::math::isnan(avi_->val_)
28  || boost::math::isnan(bvi_->val_)
29  || boost::math::isnan(cvi_->val_))) {
30  avi_->adj_ = std::numeric_limits<double>::quiet_NaN();
31  bvi_->adj_ = std::numeric_limits<double>::quiet_NaN();
32  cvi_->adj_ = std::numeric_limits<double>::quiet_NaN();
33  } else {
34  avi_->adj_ += adj_ * bvi_->val_;
35  bvi_->adj_ += adj_ * avi_->val_;
36  cvi_->adj_ += adj_;
37  }
38  }
39  };
40 
41  class fma_vvd_vari : public op_vvd_vari {
42  public:
43  fma_vvd_vari(vari* avi, vari* bvi, double c) :
44  op_vvd_vari(::fma(avi->val_, bvi->val_, c),
45  avi,bvi,c) {
46  }
47  void chain() {
48  if (unlikely(boost::math::isnan(avi_->val_)
49  || boost::math::isnan(bvi_->val_)
50  || boost::math::isnan(cd_))) {
51  avi_->adj_ = std::numeric_limits<double>::quiet_NaN();
52  bvi_->adj_ = std::numeric_limits<double>::quiet_NaN();
53  } else {
54  avi_->adj_ += adj_ * bvi_->val_;
55  bvi_->adj_ += adj_ * avi_->val_;
56  }
57  }
58  };
59 
60  class fma_vdv_vari : public op_vdv_vari {
61  public:
62  fma_vdv_vari(vari* avi, double b, vari* cvi) :
63  op_vdv_vari(::fma(avi->val_ , b, cvi->val_),
64  avi,b,cvi) {
65  }
66  void chain() {
67  if (unlikely(boost::math::isnan(avi_->val_)
68  || boost::math::isnan(cvi_->val_)
69  || boost::math::isnan(bd_))) {
70  avi_->adj_ = std::numeric_limits<double>::quiet_NaN();
71  cvi_->adj_ = std::numeric_limits<double>::quiet_NaN();
72  } else {
73  avi_->adj_ += adj_ * bd_;
74  cvi_->adj_ += adj_;
75  }
76  }
77  };
78 
79  class fma_vdd_vari : public op_vdd_vari {
80  public:
81  fma_vdd_vari(vari* avi, double b, double c) :
82  op_vdd_vari(::fma(avi->val_ , b, c),
83  avi,b,c) {
84  }
85  void chain() {
86  if (unlikely(boost::math::isnan(avi_->val_)
87  || boost::math::isnan(bd_)
88  || boost::math::isnan(cd_)))
89  avi_->adj_ = std::numeric_limits<double>::quiet_NaN();
90  else
91  avi_->adj_ += adj_ * bd_;
92  }
93  };
94 
95  class fma_ddv_vari : public op_ddv_vari {
96  public:
97  fma_ddv_vari(double a, double b, vari* cvi) :
98  op_ddv_vari(::fma(a, b, cvi->val_),
99  a,b,cvi) {
100  }
101  void chain() {
102 
103  if (unlikely(boost::math::isnan(cvi_->val_)
104  || boost::math::isnan(ad_)
105  || boost::math::isnan(bd_)))
106  cvi_->adj_ = std::numeric_limits<double>::quiet_NaN();
107  else
108  cvi_->adj_ += adj_;
109  }
110  };
111  }
112 
134  inline var fma(const stan::agrad::var& a,
135  const stan::agrad::var& b,
136  const stan::agrad::var& c) {
137  return var(new fma_vvv_vari(a.vi_,b.vi_,c.vi_));
138  }
139 
159  inline var fma(const stan::agrad::var& a,
160  const stan::agrad::var& b,
161  const double& c) {
162  return var(new fma_vvd_vari(a.vi_,b.vi_,c));
163  }
164 
184  inline var fma(const stan::agrad::var& a,
185  const double& b,
186  const stan::agrad::var& c) {
187  return var(new fma_vdv_vari(a.vi_,b,c.vi_));
188  }
189 
207  inline var fma(const stan::agrad::var& a,
208  const double& b,
209  const double& c) {
210  return var(new fma_vdd_vari(a.vi_,b,c));
211  }
212 
230  inline var fma(const double& a,
231  const stan::agrad::var& b,
232  const double& c) {
233  return var(new fma_vdd_vari(b.vi_,a,c));
234  }
235 
253  inline var fma(const double& a,
254  const double& b,
255  const stan::agrad::var& c) {
256  return var(new fma_ddv_vari(a,b,c.vi_));
257  }
258 
278  inline var fma(const double& a,
279  const stan::agrad::var& b,
280  const stan::agrad::var& c) {
281  return var(new fma_vdv_vari(b.vi_,a,c.vi_)); // a-b symmetry
282  }
283 
284  }
285 }
286 #endif
fvar< typename stan::return_type< T1, T2, T3 >::type > fma(const fvar< T1 > &x1, const fvar< T2 > &x2, const fvar< T3 > &x3)
The fused multiply-add operation (C99).
Definition: fma.hpp:62
bool isnan(const stan::agrad::var &v)
Checks if the given number is NaN.
vari * vi_
Pointer to the implementation of this variable.
Definition: var.hpp:40
#define unlikely(x)
Definition: likely.hpp:9
Independent (input) and dependent (output) variables for gradients.
Definition: var.hpp:27

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