| Stan Math Library 2.11.0 reverse mode automatic differentiation

- Main Page
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

fma.hpp
Go to the documentation of this file.
1 #ifndef STAN_MATH_REV_SCAL_FUN_FMA_HPP
2 #define STAN_MATH_REV_SCAL_FUN_FMA_HPP
3
4 #include <math.h>
5 #include <stan/math/rev/core.hpp>
6 #include <stan/math/prim/scal/fun/constants.hpp>
7 #include <boost/math/special_functions/fpclassify.hpp>
8 #include <stan/math/prim/scal/meta/likely.hpp>
9 #include <valarray>
10 #include <limits>
11
12 #ifdef _MSC_VER
13 template<typename T>
14 T fma(T x, T y, T z) {
15 return x*y+z;
16 }
17 #endif
18
19 namespace stan {
20 namespace math {
21
22 namespace {
23 class fma_vvv_vari : public op_vvv_vari {
24 public:
25 fma_vvv_vari(vari* avi, vari* bvi, vari* cvi) :
26 op_vvv_vari(::fma(avi->val_, bvi->val_, cvi->val_),
27 avi, bvi, cvi) {
28 }
29 void chain() {
30 if (unlikely(boost::math::isnan(avi_->val_)
31 || boost::math::isnan(bvi_->val_)
32 || boost::math::isnan(cvi_->val_))) {
33 avi_->adj_ = std::numeric_limits<double>::quiet_NaN();
34 bvi_->adj_ = std::numeric_limits<double>::quiet_NaN();
35 cvi_->adj_ = std::numeric_limits<double>::quiet_NaN();
36 } else {
37 avi_->adj_ += adj_ * bvi_->val_;
38 bvi_->adj_ += adj_ * avi_->val_;
39 cvi_->adj_ += adj_;
40 }
41 }
42 };
43
44 class fma_vvd_vari : public op_vvd_vari {
45 public:
46 fma_vvd_vari(vari* avi, vari* bvi, double c) :
47 op_vvd_vari(::fma(avi->val_, bvi->val_, c),
48 avi, bvi, c) {
49 }
50 void chain() {
51 if (unlikely(boost::math::isnan(avi_->val_)
52 || boost::math::isnan(bvi_->val_)
53 || boost::math::isnan(cd_))) {
54 avi_->adj_ = std::numeric_limits<double>::quiet_NaN();
55 bvi_->adj_ = std::numeric_limits<double>::quiet_NaN();
56 } else {
57 avi_->adj_ += adj_ * bvi_->val_;
58 bvi_->adj_ += adj_ * avi_->val_;
59 }
60 }
61 };
62
63 class fma_vdv_vari : public op_vdv_vari {
64 public:
65 fma_vdv_vari(vari* avi, double b, vari* cvi) :
66 op_vdv_vari(::fma(avi->val_ , b, cvi->val_),
67 avi, b, cvi) {
68 }
69 void chain() {
70 if (unlikely(boost::math::isnan(avi_->val_)
71 || boost::math::isnan(cvi_->val_)
72 || boost::math::isnan(bd_))) {
73 avi_->adj_ = std::numeric_limits<double>::quiet_NaN();
74 cvi_->adj_ = std::numeric_limits<double>::quiet_NaN();
75 } else {
76 avi_->adj_ += adj_ * bd_;
77 cvi_->adj_ += adj_;
78 }
79 }
80 };
81
82 class fma_vdd_vari : public op_vdd_vari {
83 public:
84 fma_vdd_vari(vari* avi, double b, double c) :
85 op_vdd_vari(::fma(avi->val_ , b, c),
86 avi, b, c) {
87 }
88 void chain() {
89 if (unlikely(boost::math::isnan(avi_->val_)
90 || boost::math::isnan(bd_)
91 || boost::math::isnan(cd_)))
92 avi_->adj_ = std::numeric_limits<double>::quiet_NaN();
93 else
94 avi_->adj_ += adj_ * bd_;
95 }
96 };
97
98 class fma_ddv_vari : public op_ddv_vari {
99 public:
100 fma_ddv_vari(double a, double b, vari* cvi) :
101 op_ddv_vari(::fma(a, b, cvi->val_),
102 a, b, cvi) {
103 }
104 void chain() {
105 if (unlikely(boost::math::isnan(cvi_->val_)
106 || boost::math::isnan(ad_)
107 || boost::math::isnan(bd_)))
108 cvi_->adj_ = std::numeric_limits<double>::quiet_NaN();
109 else
110 cvi_->adj_ += adj_;
111 }
112 };
113 }
114
136 inline var fma(const stan::math::var& a,
137 const stan::math::var& b,
138 const stan::math::var& c) {
139 return var(new fma_vvv_vari(a.vi_, b.vi_, c.vi_));
140 }
141
161 inline var fma(const stan::math::var& a,
162 const stan::math::var& b,
163 const double& c) {
164 return var(new fma_vvd_vari(a.vi_, b.vi_, c));
165 }
166
186 inline var fma(const stan::math::var& a,
187 const double& b,
188 const stan::math::var& c) {
189 return var(new fma_vdv_vari(a.vi_, b, c.vi_));
190 }
191
209 inline var fma(const stan::math::var& a,
210 const double& b,
211 const double& c) {
212 return var(new fma_vdd_vari(a.vi_, b, c));
213 }
214
232 inline var fma(const double& a,
233 const stan::math::var& b,
234 const double& c) {
235 return var(new fma_vdd_vari(b.vi_, a, c));
236 }
237
255 inline var fma(const double& a,
256 const double& b,
257 const stan::math::var& c) {
258 return var(new fma_ddv_vari(a, b, c.vi_));
259 }
260
280 inline var fma(const double& a,
281 const stan::math::var& b,
282 const stan::math::var& c) {
283 return var(new fma_vdv_vari(b.vi_, a, c.vi_)); // a-b symmetry
284 }
285
286 }
287 }
288 #endif
core.hpp
stan
Definition: log_sum_exp.hpp:8
stan::math::var
Independent (input) and dependent (output) variables for gradients.
Definition: var.hpp:31
boost::math::isnan
bool isnan(const stan::math::var &v)
Checks if the given number is NaN.
Definition: boost_isnan.hpp:22
unlikely
#define unlikely(x)
Definition: likely.hpp:9
stan::math::fma
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:61
stan::math::var::vi_
vari * vi_
Pointer to the implementation of this variable.
Definition: var.hpp:43
likely.hpp
constants.hpp
stan::math::fma
var fma(const double &a, const stan::math::var &b, const stan::math::var &c)
The fused multiply-add function for a value and two variables (C99).
Definition: fma.hpp:280

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