1 #ifndef STAN_MATH_FWD_SCAL_FUN_FMA_HPP
2 #define STAN_MATH_FWD_SCAL_FUN_FMA_HPP
3 
4 #include <stan/math/fwd/core.hpp>
5 #include <stan/math/prim/scal/fun/fma.hpp>
6 #include <stan/math/prim/scal/meta/return_type.hpp>
7 
8 namespace stan {
9 namespace math {
10 
11 /**
12  * The fused multiply-add operation (C99).
13  *
14  * This double-based operation delegates to <code>fma</code>.
15  *
16  * The function is defined by
17  *
18  * <code>fma(a, b, c) = (a * b) + c</code>.
19  *
20  *
21    \f[
22    \mbox{fma}(x, y, z) =
23    \begin{cases}
24      x\cdot y+z & \mbox{if } -\infty\leq x, y, z \leq \infty \\[6pt]
25      \textrm{NaN} & \mbox{if } x = \textrm{NaN}
26    \end{cases}
27    \f]
28 
29    \f[
30    \frac{\partial\, \mbox{fma}(x, y, z)}{\partial x} =
31    \begin{cases}
32      y & \mbox{if } -\infty\leq x, y, z \leq \infty \\[6pt]
33      \textrm{NaN} & \mbox{if } x = \textrm{NaN}
34    \end{cases}
35    \f]
36 
37    \f[
38    \frac{\partial\, \mbox{fma}(x, y, z)}{\partial y} =
39    \begin{cases}
40      x & \mbox{if } -\infty\leq x, y, z \leq \infty \\[6pt]
41      \textrm{NaN} & \mbox{if } x = \textrm{NaN}
42    \end{cases}
43    \f]
44 
45    \f[
46    \frac{\partial\, \mbox{fma}(x, y, z)}{\partial z} =
47    \begin{cases}
48      1 & \mbox{if } -\infty\leq x, y, z \leq \infty \\[6pt]
49      \textrm{NaN} & \mbox{if } x = \textrm{NaN}
50    \end{cases}
51    \f]
52  *
53  * @param x1 First value.
54  * @param x2 Second value.
55  * @param x3 Third value.
56  * @return Product of the first two values plus the third.
57  */
58 template <typename T1, typename T2, typename T3>
fma(const fvar<T1> & x1,const fvar<T2> & x2,const fvar<T3> & x3)59 inline fvar<typename stan::return_type<T1, T2, T3>::type> fma(
60     const fvar<T1>& x1, const fvar<T2>& x2, const fvar<T3>& x3) {
61   return fvar<typename stan::return_type<T1, T2, T3>::type>(
62       fma(x1.val_, x2.val_, x3.val_),
63       x1.d_ * x2.val_ + x2.d_ * x1.val_ + x3.d_);
64 }
65 
66 /**
67  * See all-var input signature for details on the function and derivatives.
68  */
69 template <typename T1, typename T2, typename T3>
fma(const T1 & x1,const fvar<T2> & x2,const fvar<T3> & x3)70 inline fvar<typename stan::return_type<T1, T2, T3>::type> fma(
71     const T1& x1, const fvar<T2>& x2, const fvar<T3>& x3) {
72   return fvar<typename stan::return_type<T1, T2, T3>::type>(
73       fma(x1, x2.val_, x3.val_), x2.d_ * x1 + x3.d_);
74 }
75 
76 /**
77  * See all-var input signature for details on the function and derivatives.
78  */
79 template <typename T1, typename T2, typename T3>
fma(const fvar<T1> & x1,const T2 & x2,const fvar<T3> & x3)80 inline fvar<typename stan::return_type<T1, T2, T3>::type> fma(
81     const fvar<T1>& x1, const T2& x2, const fvar<T3>& x3) {
82   return fvar<typename stan::return_type<T1, T2, T3>::type>(
83       fma(x1.val_, x2, x3.val_), x1.d_ * x2 + x3.d_);
84 }
85 
86 /**
87  * See all-var input signature for details on the function and derivatives.
88  */
89 template <typename T1, typename T2, typename T3>
fma(const fvar<T1> & x1,const fvar<T2> & x2,const T3 & x3)90 inline fvar<typename stan::return_type<T1, T2, T3>::type> fma(
91     const fvar<T1>& x1, const fvar<T2>& x2, const T3& x3) {
92   return fvar<typename stan::return_type<T1, T2, T3>::type>(
93       fma(x1.val_, x2.val_, x3), x1.d_ * x2.val_ + x2.d_ * x1.val_);
94 }
95 
96 /**
97  * See all-var input signature for details on the function and derivatives.
98  */
99 template <typename T1, typename T2, typename T3>
fma(const T1 & x1,const T2 & x2,const fvar<T3> & x3)100 inline fvar<typename stan::return_type<T1, T2, T3>::type> fma(
101     const T1& x1, const T2& x2, const fvar<T3>& x3) {
102   return fvar<typename stan::return_type<T1, T2, T3>::type>(
103       fma(x1, x2, x3.val_), x3.d_);
104 }
105 
106 /**
107  * See all-var input signature for details on the function and derivatives.
108  */
109 template <typename T1, typename T2, typename T3>
fma(const fvar<T1> & x1,const T2 & x2,const T3 & x3)110 inline fvar<typename stan::return_type<T1, T2, T3>::type> fma(
111     const fvar<T1>& x1, const T2& x2, const T3& x3) {
112   return fvar<typename stan::return_type<T1, T2, T3>::type>(
113       fma(x1.val_, x2, x3), x1.d_ * x2);
114 }
115 
116 /**
117  * See all-var input signature for details on the function and derivatives.
118  */
119 template <typename T1, typename T2, typename T3>
fma(const T1 & x1,const fvar<T2> & x2,const T3 & x3)120 inline fvar<typename stan::return_type<T1, T2, T3>::type> fma(
121     const T1& x1, const fvar<T2>& x2, const T3& x3) {
122   return fvar<typename stan::return_type<T1, T2, T3>::type>(
123       fma(x1, x2.val_, x3), x2.d_ * x1);
124 }
125 
126 }  // namespace math
127 }  // namespace stan
128 #endif
129