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